OpenRouter Integration
Send AI traces from OpenRouter (opens in a new tab) to TracePath with no code changes. OpenRouter's built-in observability feature exports OTLP traces for every LLM call, giving you visibility into costs, token usage, latency and conversations.
This integration works today. It is pure OTLP over HTTP into the TracePath ingest endpoint — there is no SDK to install and nothing to add to your application.
How it works
- OpenRouter routes your AI calls to the model provider you selected.
- Observability broadcasts traces: OpenRouter sends an OTLP span for each completion,
carrying
gen_ai.*attributes. - TracePath stores them: model, tokens, costs, duration and conversation content appear on the AI Traces pages.
Setup
1. Get your project token
AI tracing works with any TracePath project. If you do not have one yet, create a project at app.tracepath.dev (opens in a new tab) and select OpenTelemetry as the framework. Open the project's Connection page and copy its token.
2. Configure OpenRouter observability
- Go to OpenRouter Settings → Observability (opens in a new tab).
- Enable Broadcast.
- Click Add Destination next to OpenTelemetry Collector.
- Fill in the connection details:
| Field | Value |
|---|---|
| Name | TracePath, or any label you like |
| Endpoint | https://ingest.tracepath.dev/api/otel/v1/traces |
| Headers | {"Authorization": "Bearer YOUR_PROJECT_TOKEN"} |
Replace YOUR_PROJECT_TOKEN with the token from step 1. The endpoint is the same OTLP trace
endpoint every other TracePath integration posts to, so nothing about it is OpenRouter-specific.
- Click Test Connection. OpenRouter only saves the destination if the test passes, which makes this the fastest way to confirm the token is right.
- Click Add to save.
3. Verify in TracePath
Make an API request through OpenRouter, then open your TracePath dashboard and go to AI Traces. The call appears within a few seconds.
If it does not, the two likely causes are a token from the wrong project and a quota wall:
ingest answers 503 with a Retry-After header once an organization has used its monthly
ingest allowance. See Billing for the per-plan allowances.
Configuration options
OpenRouter offers several settings on the destination itself.
Privacy mode
Excludes prompt and completion content from the traces. Only metadata — model, tokens, cost, duration — is sent. Enable it if conversation content should not leave OpenRouter.
Sampling rate
What fraction of traces is broadcast. 1 captures every call; lower it to reduce volume,
which also reduces what counts against your ingest allowance.
API key filter
Restricts broadcasting to calls made with specific OpenRouter API keys. Useful when several environments share one OpenRouter organization and you want each pointed at its own TracePath project.
End-user and conversation attribution
Two request-level fields unlock the Conversations and Users analytics. Pass them on every chat completion request:
{
"model": "anthropic/claude-sonnet-4",
"messages": [{ "role": "user", "content": "Summarize this ticket." }],
"user": "account-8a41",
"session_id": "thread-129af3"
}user(up to 128 characters) identifies the end user of your product and becomes theuser.idattribute on the trace. Use a stable customer identifier — your internal account id, a tenant id — and keep it identical across all of that user's conversations, or the per-user medians on the Users page become meaningless. Leave it out and every call attributes to your OpenRouter account itself, which makes your whole customer base look like one user. If PII must stay out of telemetry, send an internal id or a hash.session_id(up to 256 characters, also accepted as thex-session-idheader) groups requests into one conversation on the Conversations page. Use your chat or thread id, stable for the life of the conversation.
TracePath resolves a call's conversation in that order: an explicit gen_ai.conversation.id
attribute first, then session.id on the span, then session.id on the resource, then the
distributed trace id. Calls that end up with no conversation id are excluded from conversation
analytics, and user analytics additionally require a non-empty user id.
What gets captured
Every OpenRouter completion produces a trace with:
| Field | Source attribute | Example |
|---|---|---|
| Model | gen_ai.request.model | openai/gpt-4-turbo |
| Response model | gen_ai.response.model | openai/gpt-4-turbo-2024-04-09 |
| Provider | gen_ai.system | openai |
| Operation | gen_ai.operation.name | chat |
| Input tokens | gen_ai.usage.input_tokens | 50 |
| Output tokens | gen_ai.usage.output_tokens | 100 |
| Cached tokens | gen_ai.usage.input_tokens.cached | 20 |
| Reasoning tokens | gen_ai.usage.output_tokens.reasoning | 10 |
| Input cost | gen_ai.usage.input_cost | 0.005 |
| Output cost | gen_ai.usage.output_cost | 0.015 |
| Total cost | gen_ai.usage.total_cost | 0.020 |
| Finish reason | gen_ai.response.finish_reason | stop |
| Prompt | gen_ai.prompt | Full messages JSON |
| Completion | gen_ai.completion | Full response JSON |
| User | user.id | The user field from your request; falls back to your OpenRouter account id |
| Conversation | session.id | The session_id field from your request |
| Trace name | trace.name | Set it with trace_name inside the request's trace object |
Any other key you pass in the request's trace object — and any gen_ai.* attribute outside
the list above, gen_ai.request.temperature included — arrives as metadata and shows up in
the metadata list on the call detail page rather than as a dedicated column.
Tool calls are parsed out of the completion payload, so the number of tool calls and the tool names appear on the conversation without any extra configuration.
Next steps
- AI Tracing: how AI traces are stored, grouped and queried
- OpenTelemetry: sending traces from your own instrumented application