AnyRouter

App Attribution

Attribute your API usage to your app with HTTP-Referer and X-AnyRouter headers and appear in public rankings and analytics.

By default your API traffic is anonymous — AnyRouter can't tell which of your apps made which call, and none of it surfaces publicly. App attribution ties each request to the app that made it, so your app earns a spot in AnyRouter's public rankings and model leaderboards, and you get per-app usage analytics. It's driven by one header you probably already send — HTTP-Referer — plus optional X-AnyRouter-* headers for display metadata and marketplace categories.

Overview

Send HTTP-Referer on your requests and AnyRouter creates an app page keyed to your origin. Add the optional headers to control the display name, platform, version, and marketplace categories.

When your app is attributed:

  • Public app rankings — your app appears on the rankings page with daily, weekly, and monthly views, sorted by total token consumption.
  • Top apps on model pages — once your app clears the listing thresholds, it appears in the "Top apps" strip on the pages of the models it uses.
  • Per-app analytics — model-usage breakdowns, token consumption, and adoption metrics scoped to your app.
  • Marketplace visibility — categorized apps surface in topic pages for discovery.

HTTP-Referer is required. Without it, no app page is created and your usage never appears in any leaderboard.

How it works

The HTTP-Referer identifier

HTTP-Referer identifies your app's URL and is the primary identifier for rankings. Your normalized Referer URL becomes the app's unique identifier:

  • The host is lowercased and the path is dropped — https://myapp.com/playground and https://myapp.com/docs attribute to the same app https://myapp.com.
  • The scheme is preserved — https://myapp.com and http://myapp.com are different apps.
  • The port is preserved when non-default — https://myapp.com:8443 is a distinct app.

GitHub Actions

GitHub Actions is attributed as its own app, not as generic github.com traffic — a workflow step that calls AnyRouter won't be grouped with gists, GitHub Apps, or docs pages that happen to share the host.

If you run AnyRouter from a workflow, send the run's repository in the ref parameter of the same header:

HTTP-Referer: https://github.com/features/actions?ref=https://github.com/<owner>/<repo>

Both repositories land on the same GitHub Actions app record, and its app page then breaks the usage down per repository. A GitHub Actions app with per-repository usage is more useful than one app record per repository.

  • ref is only honored for a GitHub Actions referer.
  • Only https://github.com/<owner>/<repo> is accepted — a ref pointing anywhere else is ignored, never stored.
  • Repo names are matched case-insensitively, the way GitHub itself does.
  • Repository names are shown publicly on the app page. To keep a private repository's name out of that breakdown, enable Hide repository names on public app pages under Dashboard → Privacy — your usage then counts toward an anonymized "Private repo" row instead, and the toggle hides already-recorded rows too.

Localhost / loopback URLs. Apps on localhost, 127.0.0.1, ::1, or any *.localhost host must also send X-AnyRouter-Title to be tracked — otherwise different developers on the same local port would collapse into one shared app. With a title, the local app is registered under local://<title-slug>.

Optional headers

HeaderPurpose
X-AnyRouter-TitleSets your app's display name in rankings and analytics. Without it, your Referer host is used.
X-TitleThe OpenRouter display-name header, read as a fallback for X-AnyRouter-Title so apps migrating from OpenRouter keep attribution with no changes. If both are sent, X-AnyRouter-Title wins.
X-AnyRouter-SourceFree-form platform/channel id (web-app, desktop, vscode-extension). Used for filtering in the dashboard. Not part of the dedup key. Spelling doesn't matter — Claude Code, claude-code and claude_code are recorded as the same app.
X-AnyRouter-AppAlias for X-AnyRouter-Source, for tools that already send this name. X-AnyRouter-Source wins when both are present.
X-AnyRouter-VersionYour app's version string, for comparing usage across releases. Semver (1.2.3) recommended.
X-AnyRouter-CategoriesComma-separated marketplace categories — up to 2 per request. Lowercase, hyphen-separated, each ≤30 chars. Unrecognized values are silently ignored.

Categories are merged with whatever your app has accumulated across requests, capped at 10 total. You don't need to resend the full list each time — one or two new categories on a single request is enough to add them.

Category catalog

GroupCategoryFor
Codingcli-agentTerminal-based coding assistants
ide-extensionEditor / IDE integrations
cloud-agentCloud-hosted coding agents
programming-appProgramming apps
native-app-builderMobile and desktop app builders
Creativecreative-writingCreative writing tools
video-genVideo generation apps
image-genImage generation apps
Productivitywriting-assistantAI-powered writing tools
general-chatGeneral chat apps
personal-agentPersonal AI agents
EntertainmentroleplayRoleplay apps and character chat
gameGaming and interactive entertainment

Only recognized categories are accepted; unrecognized values are silently dropped. If your app doesn't fit, email support@anyrouter.dev and we'll evaluate adding it.

Get your app listed

Listing is opt-in, and it has to be deliberate: send both headers on your requests.

HTTP-Referer: https://yourapp.com
X-Title: Your App

X-Title is the same display-name header OpenRouter uses, so an app migrating from OpenRouter keeps its listing with no changes. X-AnyRouter-Title works too and wins if both are sent. A browser's automatic Referer never counts, and neither does a title guessed from your User-Agent.

An app shows in a model's Top apps strip (last 7 days) when it meets all of these:

  • Only requests that sent HTTP-Referer and X-Title (or X-AnyRouter-Title) count. Each request counts on its own: one caller sending both headers does not list a host for everyone else who uses it. Requests that sent only one of them, including traffic recorded before you added both, never count.
  • It made at least 50 such requests to that model in the window.
  • Those requests came from at least 5 different users, so a small team's app is never named.
  • Its host is a public domain name. Localhost, IP addresses, and internal hostnames (.local, .internal, …) are never listed.

Apps without a logo are shown by their origin (for example yourapp.com), not by the title you send. To get your display name, logo, and a link to your app page, email support@anyrouter.dev to be added to the curated registry.

The same rules decide whether an uncurated app's page (/app?id=yourapp.com) shows usage: until your app meets them, its page looks the same as an app that has never been seen.

What is public: the app's origin or curated name, its logo if curated, and its share of the listed apps' tokens. Prompts, completions, API keys, account details, and request counts are never shown. The list refreshes about once an hour.

Hide a workspace from public listings

To keep a workspace's traffic out of every public app surface (the rankings page, app pages, and the Top apps strip on model pages), a workspace owner or admin can turn on Hide this workspace from public app listings under Dashboard → Privacy. It applies to traffic already recorded too, and hidden requests no longer count toward any app's listing thresholds. Rankings and app pages update within minutes. Model pages are cached, so the change can take up to an hour to show there. Your own dashboard analytics are not affected.

Configure

Add the attribution headers to your existing request. HTTP-Referer is required; the rest are optional display metadata.

// TypeScript / JavaScript
fetch('https://anyrouter.dev/api/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk-ar-your-key',
    'Content-Type': 'application/json',
    // Required for attribution
    'HTTP-Referer': 'https://myapp.com',
    // Optional display metadata
    'X-AnyRouter-Title': 'My AI Assistant',
    'X-AnyRouter-Source': 'web-app',
    'X-AnyRouter-Version': '1.0.0',
    'X-AnyRouter-Categories': 'general-chat,personal-agent',
  },
  body: JSON.stringify({
    model: 'google/gemma-4-26b-a4b-it',
    messages: [{ role: 'user', content: 'Hello, world!' }],
  }),
});
# Python
import requests

response = requests.post(
    url='https://anyrouter.dev/api/v1/chat/completions',
    headers={
        'Authorization': 'Bearer sk-ar-your-key',
        'Content-Type': 'application/json',
        # Required for attribution
        'HTTP-Referer': 'https://myapp.com',
        # Optional display metadata
        'X-AnyRouter-Title': 'My AI Assistant',
        'X-AnyRouter-Source': 'web-app',
        'X-AnyRouter-Version': '1.0.0',
        'X-AnyRouter-Categories': 'general-chat,personal-agent',
    },
    json={
        'model': 'google/gemma-4-26b-a4b-it',
        'messages': [{'role': 'user', 'content': 'Hello, world!'}],
    },
)
# cURL
curl https://anyrouter.dev/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-ar-your-key" \
  -H "HTTP-Referer: https://myapp.com" \
  -H "X-AnyRouter-Title: My AI Assistant" \
  -H "X-AnyRouter-Source: web-app" \
  -H "X-AnyRouter-Version: 1.0.0" \
  -H "X-AnyRouter-Categories: general-chat,personal-agent" \
  -d '{
    "model": "google/gemma-4-26b-a4b-it",
    "messages": [
      { "role": "user", "content": "Hello, world!" }
    ]
  }'

Best practices

  • Always send HTTP-Referer — without it the request is unattributed and your app is invisible to rankings.
  • Pin the Referer to your canonical origin (https://yourapp.com), not a deep page URL — paths are dropped anyway, but a stable origin makes attribution predictable.
  • Send X-AnyRouter-Title for a friendly display name; otherwise the host is shown.
  • Send X-AnyRouter-Categories to surface in marketplace topic pages.
  • For local development, include X-AnyRouter-Title so your loopback app doesn't collide with other developers'.
  • Use semver for versions — useful for comparing rollouts.

Frequently asked questions

On the main rankings page (daily/weekly/monthly, sorted by token consumption) and in the "Top apps" strip of each model page it uses, once it meets the listing thresholds.

Yes. If you migrated (e.g. myapp.com → myapp.io), email support@anyrouter.dev with both URLs and we'll merge them into one canonical record. The same address handles splitting an entry if you need the inverse.

No. Attribution headers carry identity only — they don't expose anything about your request payloads. Your app's Referer, title, and chosen categories are publicly visible in rankings; the prompts and completions are not.