Docs
Sending logs
Three ways in, all authenticated with an event key, all landing on one timeline beside your runs and nodes.
Everything Obsevo observes — log lines, run outcomes and node executions — shares one timeline in Log explorer, filterable by record type, severity, workflow, source, environment and any attribute in the payload.
Log lines get in three ways. All are authenticated with an event key (Settings → Instances → the instance → Event keys) and all land on that key's instance.
| Path | For |
|---|---|
POST /ingest/logs | the n8n-nodes-obsevo community node |
POST /ingest/logs/raw | anything that can post JSON |
POST /v1/logs | OpenTelemetry exporters (OTLP/HTTP, JSON and protobuf) |
The instance is derived from the key, so there is no field in any of these payloads for saying which instance a line belongs to.
The raw endpoint
It takes whatever shape you already have — a single object, an array,
{ "logs": [...] } (records and items also work as the wrapper key), or
newline-delimited JSON.
curl -X POST https://ingest.example.com/ingest/logs/raw \
-H 'authorization: Bearer obse_…' \
-H 'content-type: application/json' \
-d '{"message":"card declined","level":"error","orderId":"A-1"}'The message, the level and the timestamp are worked out server-side, so a payload written for pino, Datadog, GCP, OTel or syslog lands correctly without being reshaped first — see the field precedence reference.
Newline-delimited JSON is detected by content rather than by content-type, on
the grounds that a sender posting NDJSON with application/json is wrong about
the header but right about the intent. An unparseable line is skipped rather than
failing the batch: one bad line in a thousand should not lose the other 999.
OpenTelemetry
Point an exporter at /v1/logs. No encoding override is needed — protobuf is
accepted as well as JSON.
exporters:
otlphttp:
logs_endpoint: https://ingest.example.com/v1/logs
headers:
authorization: Bearer obse_…Set n8n.execution.id (an OTLP attribute) or executionId (raw JSON) to
correlate a line with an n8n run. The explorer then shows it beside that run and
its nodes.
The response is the OTLP spec's { "partialSuccess": {} } rather than Obsevo's
usual shape, because an exporter reads partialSuccess and will retry forever
against anything else.
Limits and refusals
| Response | Meaning |
|---|---|
202 { "accepted": n } | Accepted for processing |
413 batch_too_large | More than 200 records in one batch |
429 rate_limited | Over the per-instance log budget. retry-after: 60 |
400 invalid_payload | The batch failed validation; the body names the offending paths |
Logs have their own rate budget, separate from business events and from agent pushes. A workflow that emits one KPI event per run may well log a line per item, and sharing a limiter would throttle normal use the moment someone turned logging on.
Values under credential-shaped keys are redacted on arrival, and env is never
read from the payload — it comes from the instance the event key belongs to.