Skip to main content
New: LLM Observability is now GA

Ingest endpoints and errors

Every ingest path, every status code the receiver returns, the rate limits, and the size caps — the page to open when a request is being rejected.

Before you start

Reference for the ingest surface. If a request is being rejected and you want to know why, start with status codes.

Endpoints

Over HTTP, on port 4000 by default:

  • POST /v1/logs — OTLP logs
  • POST /v1/metrics — OTLP metrics
  • POST /v1/traces — OTLP traces
  • POST /api/v1/prom/write — Prometheus remote-write
  • GET /health — liveness; always returns 200 if the process is up
  • GET /readyz — readiness; 200 when the pipeline is reachable, 503 when not
  • GET /metrics — the receiver's own Prometheus metrics

Over gRPC, on port 4317: the standard OTLP logs, metrics, and trace services. Both transports accept the same dashboard-issued key and enforce the same rate limits, quotas, and per-signal entitlements — the only difference is that gRPC metadata keys are lower-case, so the header is x-license-key. See Send data with OpenTelemetry.

The ports above are what the receiver itself binds. The base URL you actually export is shown on Get Started in the dashboard: a hosted deployment and a self-hosted one behind the bundled nginx (which serves OTLP under /otlp and strips the prefix) do not have the same one.

/health is a static check on the process only; it does not test dependencies. Use /readyz if you want a check that fails when the pipeline behind the receiver is unreachable. Wiring a load balancer to /health expecting it to drain an unhealthy receiver will not do what you want.

Authentication

Send your license key one of two ways:

http
X-License-Key: oiq_4f3c2b1a9e8d7c6b5a4f3e2d1c0b9a8e
http
Authorization: Bearer oiq_4f3c2b1a9e8d7c6b5a4f3e2d1c0b9a8e

X-License-Key takes precedence if both are present. Header names are case-insensitive; the key value is not.

Status codes

202 Accepted — the batch was published to the pipeline. This is success. It acknowledges receipt, not storage; data becomes queryable a few seconds later.

400 Bad Request — the payload did not decode or failed validation. Causes: malformed protobuf, a body that does not match the declared content type, or a payload that decodes but violates the OTLP schema. Rejected payloads are copied to a dead-letter queue, so they are recoverable by an operator.

401 Unauthorized — one of:

  • No key supplied — the message names both accepted headers.
  • Malformed key — not oiq_-prefixed, or shorter than 20 characters.
  • Invalid or revoked key.

403 Forbidden — the key is valid but the request is not allowed: the signal is not enabled for your account, or the source address is not permitted.

413 Payload Too Large — the body exceeded a size cap. See limits.

429 Too Many Requests — a rate limit was hit. A Retry-After header gives the wait in seconds.

500 / 502 / 503 — the receiver could not publish to the pipeline. These are retryable; OpenTelemetry SDKs and Prometheus remote-write both retry with backoff.

Rate limits

Three limits apply to authenticated HTTP ingest:

  • 200 requests per second per account, with a burst allowance of 400. Exceeding it returns 429 with Retry-After: 1.
  • 10,000 requests per minute per account. Exceeding it returns 429 with Retry-After: 60.
  • A global per-key limit, which also returns 429.

The per-second limit does not apply to Prometheus remote-write; the per-minute limit does.

These are limits on requests, not on records. Batching is therefore the correct response to hitting them — an SDK exporting 500 spans in one request uses one of your 200 per second, not 500. If you are being rate-limited, look at your exporter's batch settings before asking for a limit increase.

Limits and caps

General ingest:

  • 50 MB maximum request body.

Prometheus remote-write, which has its own tighter caps:

  • 8 MB compressed body
  • 64 MB decompressed
  • 10,000 timeseries per request
  • 100,000 total samples per request
  • 128 labels per series
  • 1,024 bytes per label name or value

Exceeding the decompressed cap returns 413; exceeding the series, sample, or label caps returns 400.

Encodings

OTLP/HTTP accepts:

  • application/json
  • application/x-protobuf
  • application/octet-stream — treated as protobuf

Request bodies may be gzip, deflate, or brotli compressed. An unsupported Content-Encoding returns 415; a body that fails to decompress returns 400.

Prometheus remote-write is the exception: it expects snappy-compressed protobuf and has HTTP-level decompression disabled, so gzip on top of it will fail.

Next steps