Obsivara — Complete Connect Guide (machine-readable) ===================================================== Purpose: Self-contained plain-text reference for wiring Obsivara into an AI agent or workflow. Fetch this file once; it contains every endpoint, payload, and error you need. HTML docs: https://doc.obsivara.com Dashboard: https://app.obsivara.com ------------------------------------------------------------------- SECTION 1: BASE URL & AUTHENTICATION ------------------------------------------------------------------- Base URL: https://api.obsivara.com Ingest routes mount at /ingest/* — there is NO /v1 prefix on ingest. Data API (read) routes are at /v1/*. Auth header (required on every request): Authorization: Bearer obs_live_YOUR_KEY API keys are created in the Obsivara dashboard at: Settings -> API Keys -> New key Required scope for sending events: ingest:write A missing/invalid token returns 401. A valid token that lacks ingest:write returns 403. Key notes: - Keys start with obs_live_ - The secret is shown only at creation — copy it immediately. - Deleting a key takes effect within ~5 minutes (server-side cache TTL). ------------------------------------------------------------------- SECTION 2: QUICKSTART — SIMPLEST WORKING CALL ------------------------------------------------------------------- The simplest way to send an event is a single curl to the generic webhook: curl -X POST https://api.obsivara.com/ingest/webhook/generic \ -H "Authorization: Bearer obs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -H "X-Obsivara-Asset-Id: my-first-agent" \ -d '{ "event": "run_started", "run_id": "demo-run-1", "asset_id": "my-first-agent", "name": "My first run", "input": "hello world" }' Expected response (HTTP 202): { "source": "generic", "accepted": 1, "rejected": 0, "errors": [] } Notes: - run_id can be any string. Non-UUID values are auto-hashed to a stable UUID server-side. - asset_id identifies the thing being monitored (agent name, workflow name, etc.). - You can also pass asset_id as a query parameter (?asset_id=) or via the X-Obsivara-Asset-Id header. Precedence: body > query param > header > "unknown". - n8n is an alias of generic — /ingest/webhook/n8n accepts the same payloads. ------------------------------------------------------------------- SECTION 3: RUN LIFECYCLE — THREE EVENTS ------------------------------------------------------------------- A full run consists of three events posted to: POST https://api.obsivara.com/ingest/webhook/generic Use the same run_id across all three calls to tie them into one run. The generic webhook uses snake_case field names (see Section 5 for batch/camelCase). Event 1 — run_started (marks the beginning of a run): { "event": "run_started", "run_id": "order-123", "asset_id": "support-agent", "name": "Support reply", "input": "where is my order?" } Full curl: curl -X POST https://api.obsivara.com/ingest/webhook/generic \ -H "Authorization: Bearer obs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event": "run_started", "run_id": "order-123", "asset_id": "support-agent", "name": "Support reply", "input": "where is my order?" }' Event 2 — llm_call (records a single LLM invocation): { "event": "llm_call", "run_id": "order-123", "provider": "openai", "model": "gpt-4o", "prompt_tokens": 312, "completion_tokens": 87, "total_tokens": 399, "cost_usd": 0.0048, "latency_ms": 1240 } Full curl: curl -X POST https://api.obsivara.com/ingest/webhook/generic \ -H "Authorization: Bearer obs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event": "llm_call", "run_id": "order-123", "provider": "openai", "model": "gpt-4o", "prompt_tokens": 312, "completion_tokens": 87, "total_tokens": 399, "cost_usd": 0.0048, "latency_ms": 1240 }' Event 3 — run_finished (marks the end of a run): { "event": "run_finished", "run_id": "order-123", "outcome": "success", "duration_ms": 3500, "total_cost_usd": 0.0048 } Full curl: curl -X POST https://api.obsivara.com/ingest/webhook/generic \ -H "Authorization: Bearer obs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event": "run_finished", "run_id": "order-123", "outcome": "success", "duration_ms": 3500, "total_cost_usd": 0.0048 }' ------------------------------------------------------------------- SECTION 4: KEY VERIFICATION ------------------------------------------------------------------- Send this test event first. HTTP 202 means the key is valid and has the right scope. curl -X POST https://api.obsivara.com/ingest/webhook/generic \ -H "Authorization: Bearer obs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event": "run_started", "run_id": "verify-key-1", "asset_id": "my-agent", "name": "Key verification run", "input": "ping" }' Expected: { "source": "generic", "accepted": 1, "rejected": 0, "errors": [] } 202 — key works. Proceed to instrument your workflow. 401 — bad or missing key. Check: Authorization: Bearer obs_live_... 403 — key exists but lacks ingest:write scope. Create a new key with that scope. ------------------------------------------------------------------- SECTION 5: BATCH INGEST — /ingest/batch ------------------------------------------------------------------- Endpoint: POST https://api.obsivara.com/ingest/batch Max: 1,000 events per request. Exceeding this returns 413. Response: HTTP 202 with { "accepted": N, "rejected": M, "errors": [...] } The batch endpoint uses camelCase field names (unlike the generic webhook which uses snake_case). Wrap all events in a top-level "events" array: POST https://api.obsivara.com/ingest/batch Authorization: Bearer obs_live_YOUR_KEY Content-Type: application/json { "events": [ { "type": "run_start", "data": { "name": "Support reply", "assetId": "support-agent", "input": "where is my order?" } }, { "type": "llm_call", "data": { "runId": "550e8400-e29b-41d4-a716-446655440000", "provider": "openai", "model": "gpt-4o", "promptTokens": 312, "completionTokens": 87, "totalTokens": 399, "costUsd": 0.0048, "latencyMs": 1240 } }, { "type": "run_end", "data": { "runId": "550e8400-e29b-41d4-a716-446655440000", "status": "success", "durationMs": 3500 } } ] } llm_call required fields (camelCase, for /ingest/batch): runId UUID — must be a valid UUID from a preceding run_start provider string — model provider (e.g. openai, anthropic) model string — model name (e.g. gpt-4o, claude-3-5-sonnet) promptTokens number — input token count completionTokens number — output token count totalTokens number — sum of prompt + completion tokens costUsd number — cost of this call in USD latencyMs number — latency in milliseconds llm_call optional fields: prompt string — full prompt text completion string — full completion text temperature number — sampling temperature promptVersion string — prompt version identifier metadata object — arbitrary key-value metadata Partial batch success: if some events are invalid the batch still returns 202, but rejected > 0 and errors lists per-index failures. Do not resubmit accepted events. Example partial response: HTTP/1.1 202 Accepted { "accepted": 2, "rejected": 1, "errors": [{ "index": 1, "error": "runId must be a valid UUID" }] } ------------------------------------------------------------------- SECTION 6: OPENTELEMETRY (OTLP) ------------------------------------------------------------------- Endpoint: POST https://api.obsivara.com/ingest/otlp/v1/traces Format: JSON only. Protobuf bodies return 415. Auth: Authorization: Bearer obs_live_YOUR_KEY Point any standard OTel SDK exporter at: OTEL_EXPORTER_OTLP_ENDPOINT=https://api.obsivara.com/ingest/otlp Use the obsivara.asset_id resource attribute to set asset attribution. Obsivara auto-detects spans with gen_ai.* / llm.* attributes, or span names containing "llm" or "chat", and maps them to llm_call events. Relevant attributes: obsivara.asset_id — resource attribute; sets the asset gen_ai.system — e.g. openai gen_ai.request.model — model name gen_ai.usage.prompt_tokens gen_ai.usage.output_tokens gen_ai.usage.cost ------------------------------------------------------------------- SECTION 7: ERROR REFERENCE ------------------------------------------------------------------- Status Message Cause Fix ------ ------- ----- --- 401 Missing Bearer token No Authorization header sent Add Authorization: Bearer obs_live_... to every request 401 Invalid API key Key is malformed, revoked, or gone Generate a new key at Settings -> API Keys 403 API key lacks the ingest:write scope Key exists but wrong scope Recreate the key with ingest:write (or *) scope 400 Invalid JSON body Body is not valid JSON Validate JSON; ensure Content-Type: application/json 400 events must be an array events field missing or not array Wrap events: { "events": [ ... ] } 400 Validation error Field fails schema validation Check details array; fix flagged fields (see event schema) 413 Max 1000 events per batch Batch > 1,000 events Split into multiple requests of <= 1,000 events each 429 Plan limit exceeded Workspace exhausted ingest quota Upgrade plan or contact support for a temporary quota lift Common validation errors: - runId is not a valid UUID — use run_start first to obtain one, or generate UUID v4 - A required numeric field (promptTokens, durationMs, etc.) is missing or is a string - status is not one of the accepted enum values (success / error / timeout for run_end) ------------------------------------------------------------------- SECTION 8: SCOPES REFERENCE ------------------------------------------------------------------- Scope Access Notes ingest:write Send events to /ingest/* Default for monitoring integrations read / read:all Read data from /v1/* Keys with only ingest:write are rejected (403) on /v1/* admin / * Full access Use only for trusted server-side integrations ------------------------------------------------------------------- SECTION 9: VERIFY — CONFIRM DATA LANDED ------------------------------------------------------------------- 1. Open https://app.obsivara.com 2. Find your asset_id on the inventory/health page. 3. Open a run to see the trace, token counts, and cost. Timing: runs and errors appear within approximately 1 minute of ingest. Health scores and recommendations are updated on a worker schedule and may lag slightly. ------------------------------------------------------------------- SECTION 10: EVENT SCHEMA SUMMARY ------------------------------------------------------------------- Generic webhook (/ingest/webhook/generic) uses snake_case. Batch API (/ingest/batch) uses camelCase inside each data object. Accepted event types: run_started / run_start — start of a run llm_call — single LLM invocation run_finished / run_end — end of a run tool_call — tool or function call within a run span — generic OpenTelemetry-compatible span error — standalone error event Unknown event values are stored as error rows, so spell them exactly. ------------------------------------------------------------------- FULL HTML DOCUMENTATION ------------------------------------------------------------------- https://doc.obsivara.com Overview: https://doc.obsivara.com/ Quickstart: https://doc.obsivara.com/quickstart Authentication: https://doc.obsivara.com/authentication Agent runbook: https://doc.obsivara.com/connect/agent Generic webhook: https://doc.obsivara.com/connect/webhook OTLP: https://doc.obsivara.com/connect/otlp n8n: https://doc.obsivara.com/connect/n8n Event schema: https://doc.obsivara.com/reference/events Errors: https://doc.obsivara.com/reference/errors Verify: https://doc.obsivara.com/verify