Skip to content

Sending Traces

Mibo accepts traces on a single endpoint, POST /public/traces, with two supported request shapes. Both produce the same canonical trace internally — pick whichever fits your stack.

Both paths are first-class. Neither is a workaround for the other.

You’re on…Use
A service emitting OTel via the Anthropic / OpenAI / Traceloop / OpenLLMetry SDKsOTLP
n8n self-hosted ≥ 2.19 with N8N_OTEL_TRACING_ENABLED=trueOTLP
n8n Cloud (no host-level OTel)Your API — see Send traces from n8n for all options
Flowise self-hosted with native OTel enabledOTLP
Flowise Cloud (no host-level OTel)Your API via the Flowise template
Anything else with an HTTP endpoint — LangChain agents, your own code, scripts, curlYour API

If you can choose OTLP, it usually wins — your existing exporter is already batched, retried, and instrumented. Your API exists so users on managed hosts (n8n Cloud, Flowise Cloud, anything where you can’t touch host env vars) get the same first-class trace ingestion.

  • Endpoint: POST https://api.mibo-ai.com/public/traces
  • Auth: x-api-key header. See API Keys & Trace Routing.
  • Identity: x-request-id HTTP header. Present → upserts the trace with that id. Absent → server-generated UUID, always creates a new trace.
  • Agent resolution: if the API key is scoped to a single agent, that agent is used. Otherwise the request must carry platformId (top level) or metadata.mibo.platform_id (Your API) / mibo.platform_id resource attribute (OTLP).
  • Canonical span model: spans with span_id, parent_span_id, name, attributes, optional timing and status. span.name is always the user-facing display label of the step.
OTLPYour API
Body shaperesourceSpans[].scopeSpans[].spans[] (OTel envelope){ spans: [...] } (flat)
Attributes encodingOTel key/value list ({ key, value: { stringValue: "..." } })Plain JSON object
BatchingMulti-POST: server merges by traceId/span_idOne POST per trace; create-or-replace by externalId
Best forLong-lived processes, SDK-instrumented servicesSynchronous flows, short scripts, managed-host integrations

The runner reads the same attributes on both paths — gen_ai.response.text, gen_ai.usage.input_tokens, gen_ai.tool.name, http.response.status_code, and the rest of the GenAI / HTTP semconv keys. Your assertions don’t change.

Whichever path you send on, these are the attributes assertions look up. Emit what you have; missing data surfaces as missing instrumentation in the dashboard rather than silent pass/fail.

AttributeWhat it powers
gen_ai.response.textSemantic assertions, response_regex, default text extraction
gen_ai.output.messagesSame as above when present (preferred over response.text)
gen_ai.usage.input_tokens / output_tokens / reasoning.output_tokenstoken_limit
gen_ai.tool.name + gen_ai.tool.call.argumentstool_call (the span becomes a child tool call of its parent)
http.response.status_codehttp_status
Span namenode_call (case-insensitive substring match)
Root span start/end_time_unix_nanoresponse_time.max_ms

See Assertion Reference for the full mapping.