Wire envelope spec
The three SDKs (Python, Node, Go) send the exact same JSON envelope to
POST /api/v1/ai/ingest with Authorization: Bearer aiv_.... You can
also POST directly without an SDK; the envelope is the contract.
Endpoint
POST /api/v1/ai/ingestHost: api.monsys.aiAuthorization: Bearer aiv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxContent-Type: application/jsonTop-level envelope
{ "trace_id": "uuid", // client-generated UUIDv4 (required) "root_op": "rag.chat", // free-text label (required) "status": "ok" | "error" | "partial", // (required) "started_at": "2026-05-12T09:50:00Z", // RFC3339 (required) "ended_at": "2026-05-12T09:50:01Z", // RFC3339 (optional) "user_session_hash": "", // SHA256 of session id, optional "sampling_decision": "full", // "full" | "head" | "summary" "spans": [ ... ] // 1..N spans (required)}Span
{ "span_id": "uuid", // UUIDv4 (required) "parent_span_id": "uuid", // "" for root span "op": "openai.chat", // free-text (required) "provider": "openai", // canonical provider name "model": "gpt-4o-mini", // model id "started_at": "2026-05-12T09:50:00.001Z", "ended_at": "2026-05-12T09:50:00.987Z", "status": "ok", // "ok" | "error" | "refused" | "partial" "input_tokens": 42, "output_tokens": 17,
"prompt": "...", // raw — redacted on the hub "completion": "...", // raw — redacted on the hub "system_msg": "...", "tool_io": "...", // tool call or function result
"attributes": { ... }, // optional top-level metadata "events": [ { ... }, ... ] // optional event stream}Canonical provider names
| Provider | provider value |
|---|---|
| OpenAI | openai |
| Anthropic Claude | anthropic |
| Google Gemini | google |
| Mistral AI | mistral |
| Azure OpenAI | azure |
| Local (Ollama) | ollama |
Other providers are accepted but get no pricing lookup (cost = 0).
Pricing lookup
On ingest the hub looks up ai_model_pricing by (provider, model).
Match is exact — new models not in the table get
total_cost_micro_eur = 0. Request an update via
info@be-hosted.be (pricing changelog page — coming soon).
The pricing row used is pinned per span via a pricing_snapshot_id
FK — backfilling prices does not change historical costs.
Response
{ "received": true, "trace_id": "uuid", "spans": 3, "pii_hits": 1, "total_cost_micro_eur": 603290}HTTP status:
200— processed (see body)401— token invalid or revoked403— tenant hasai_observability_enabled = false400— invalid envelope (seeerrorin body)5xx— hub-side error; the SDK does not retry (failures are silent)
Example curl
curl -X POST https://api.monsys.ai/api/v1/ai/ingest \ -H "Authorization: Bearer aiv_xxxx" \ -H "Content-Type: application/json" \ -d '{ "trace_id": "0e2216d5-7b6d-448a-924c-c7a08b1a7e4a", "root_op": "manual_test", "status": "ok", "started_at": "2026-05-12T09:50:00Z", "ended_at": "2026-05-12T09:50:01Z", "sampling_decision": "full", "spans": [{ "span_id": "a1b2c3d4-e5f6-4789-9abc-def012345678", "parent_span_id": "", "op": "openai.chat", "provider": "openai", "model": "gpt-4o-mini", "started_at": "2026-05-12T09:50:00.001Z", "ended_at": "2026-05-12T09:50:00.987Z", "status": "ok", "input_tokens": 22, "output_tokens": 12, "prompt": "My IBAN is BE68 5390 0754 7034.", "completion": "I cannot help with banking details.", "attributes": {}, "events": [] }] }'OpenTelemetry GenAI compat
We map OTel GenAI semantic conventions onto this envelope internally, but don’t accept OTLP directly yet. Reason: OTLP/HTTP binary overhead is overkill for one-call-per-trace. If you have an OTel-only stack, write a thin adapter from OTel span → our envelope (see envelope-from-otel.md — coming soon).