# Track OpenRouter costs with Broadcast and Veqen

OpenRouter's Broadcast destination can send model usage directly to Veqen. The connection uses the standard OpenTelemetry JSON endpoint, so there is no separate Veqen plug-in to install in OpenRouter.

## Configure the destination

Create an **ingest** key in [Veqen API keys](https://veqen-app.com/app/settings/keys). In OpenRouter, open your workspace's Observability settings and add an **OpenTelemetry Collector** destination.

```text
Endpoint: https://veqen-app.com/v1/otlp/v1/traces
```

Set Headers to this JSON, replacing the placeholder privately:

```json
{"Authorization":"Bearer <your-veqen-ingest-key>"}
```

Enable **Privacy Mode** to exclude prompt and completion content. Leave optional identity and request-context metadata disabled unless you need those fields and have approved their export. Use an API-key filter when only one application should be recorded. Review the filters before saving: an unfiltered destination can send all workspace traffic. Follow [OpenRouter's destination instructions](https://openrouter.ai/docs/guides/features/broadcast/otel-collector) for the current settings interface.

## Test before enabling ongoing traffic

Use **Test Connection**, then **Send Trace**. In Veqen, verify that a call appears in the intended organization. A transport success alone is insufficient: the ledger should show a model and token counts.

Our verification on October 22, 2026 used OpenRouter's built-in synthetic trace with Privacy Mode enabled and an ingest key restricted to an isolated Veqen organization. One `gpt-4-turbo` event appeared with 50 input and 100 output tokens. Veqen calculated $0.0035 from its price book. This was a synthetic delivery test, not a paid model request or invoice reconciliation.

The destination supports OTLP/HTTP JSON. Veqen rejects protobuf with `415`, rejects invalid credentials with `401`, and reports invalid records or plan-limit drops in an OTLP partial-success response. It keeps valid records from the same batch.

## Attribute costs to customers and features

Use pseudonymous allocation fields in your OpenRouter request:

```json
{
  "model": "openai/gpt-4o",
  "messages": [{"role":"user","content":"Your application request"}],
  "user": "user-17",
  "trace": {
    "customer": "customer-42",
    "feature": "support",
    "project": "customer-app",
    "environment": "production"
  }
}
```

Veqen maps the exported `trace.metadata.*` allocation fields and `user.id`. It records only spans containing GenAI usage. Replayed exports of the same trace/span identifier and timestamp are deduplicated within the organization. Do not also wrap these requests with a Veqen SDK recorder: those independently generated events have different identifiers.

## Understand what the total means

The adapter prices token usage with Veqen's current price book or your custom rates. It understands separate cache reads and five-minute/one-hour cache writes. It does **not** yet import OpenRouter's complete billed-cost allocation, BYOK fees, tool charges, credits or refunds. Treat the displayed amount as an inference estimate, not your OpenRouter balance.

Veqen discards prompts, responses, arbitrary metadata and raw provider usage objects. Keep Privacy Mode enabled so content is removed before transmission too. A successful tracing integration records completed work; it cannot block a model call before it happens. See [OpenTelemetry](/docs/opentelemetry), [cost per customer](/guides/cost-per-customer), and [budgets](/docs/budgets) for the separate accounting and enforcement paths.
