OpenTelemetry (OTLP)
Point your OpenTelemetry exporter at Obsivara — gen_ai.* attributes are mapped automatically to LLM cost and token tracking.
415 Unsupported Media Type. Set Content-Type: application/json on every request.Endpoint
POST https://api.obsivara.com/ingest/otlp/v1/tracesAuth: Authorization: Bearer obs_live_YOUR_KEY (scope: ingest:write).
Use with an OTel SDK exporter
Most OpenTelemetry SDKs read the exporter endpoint and headers from environment variables. Set these two variables and your existing traces will flow to Obsivara automatically:
# Set your OTel SDK exporter to point at Obsivara
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.obsivara.com/ingest/otlp
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer obs_live_YOUR_KEY"The exporter will send to /ingest/otlp/v1/traces automatically. No code changes needed.
Minimal JSON payload
If you are constructing OTLP JSON directly, here is a minimal payload with all fields Obsivara reads:
{
"resourceSpans": [
{
"resource": {
"attributes": [
{ "key": "obsivara.asset_id", "value": { "stringValue": "support-agent" } },
{ "key": "service.name", "value": { "stringValue": "support-agent" } }
]
},
"scopeSpans": [
{
"scope": { "name": "my-app" },
"spans": [
{
"traceId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"spanId": "a1b2c3d4e5f6a1b2",
"name": "llm-chat",
"kind": 3,
"startTimeUnixNano": "1720000000000000000",
"endTimeUnixNano": "1720000001240000000",
"attributes": [
{ "key": "gen_ai.system", "value": { "stringValue": "openai" } },
{ "key": "gen_ai.request.model", "value": { "stringValue": "gpt-4o" } },
{ "key": "gen_ai.usage.prompt_tokens", "value": { "intValue": "312" } },
{ "key": "gen_ai.usage.output_tokens", "value": { "intValue": "87" } },
{ "key": "gen_ai.usage.cost", "value": { "doubleValue": 0.0048 } }
]
}
]
}
]
}
]
}curl -X POST https://api.obsivara.com/ingest/otlp/v1/traces \
-H "Authorization: Bearer obs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d @payload.jsonAttribute mapping
Obsivara maps the following OpenTelemetry semantic conventions to its internal event model:
| OTel attribute | Obsivara field |
|---|---|
gen_ai.system / llm.vendor | provider |
gen_ai.request.model / llm.request.model | model |
gen_ai.usage.prompt_tokens / llm.usage.prompt_tokens | promptTokens |
gen_ai.usage.output_tokens / llm.usage.completion_tokens | completionTokens |
gen_ai.usage.cost | costUsd |
obsivara.asset_id (resource attribute) | assetId |
Auto-detection
Spans are classified as llm_call events automatically when any of the following are true:
- The span has a
gen_ai.*orllm.*attribute - The span name contains
"llm"or"chat"(case-insensitive)
All other spans are recorded as generic span events and associated with the same trace.
Setting the asset ID
Set the obsivara.asset_id resource attribute on your OTel resource to attribute all spans from that resource to the named asset in Obsivara. This is the recommended approach for SDK-based exporters.
service.name is also captured but is separate from the Obsivara asset. Always set obsivara.asset_id explicitly.Troubleshooting
- 415 Unsupported Media Type — you are sending protobuf. Switch to the JSON OTLP format.
- 401 — missing or malformed Bearer token in the
Authorizationheader. - 403 — key exists but lacks
ingest:writescope. Re-create the key. - No data in dashboard — check that
obsivara.asset_idis set on the resource; otherwise the asset will appear as"unknown".
See Errors & troubleshooting → for the full error reference.