DATIUSDocs

Ingestion API

A single, high-throughput endpoint for sending telemetry — POST /api/v1/ingest. Authenticated by a workspace-scoped API key (see Authentication), not a session token, since ingestion clients are external services and SDKs rather than signed-in browser users. Already instrumenting with OpenTelemetry? See OpenTelemetry for that ingestion path instead.

Single event

Shell
curl -X POST https://datius.io/api/v1/ingest \
-H "X-API-Key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"signalKey": "order_completed",
"value": 149.99,
"timestamp": "2026-09-15T18:04:00.000Z",
"tags": { "currency": "USD", "customerTier": "gold" }
}'

Batching

The same endpoint also accepts a JSON array of up to 500 payloads in one request. Batches are all-or-nothing: if any payload fails validation, the entire request is rejected and nothing is queued.

JSON
[
{ "signalKey": "order_completed", "value": 149.99 },
{ "signalKey": "queue_wait_time", "value": 3400, "tags": { "region": "us-east" } }
]

Payload fields

  • signalKey (string, required) — must match an active signal in the workspace the API key is scoped to.
  • value (number, required) — the measurement itself. Its meaning depends on the signal's data type (a raw count, a currency amount, a duration in the signal's configured unit, etc.).
  • timestamp (ISO 8601 string, optional) — defaults to the ingestion server's current time if omitted.
  • tags (object, optional) — string, number, or boolean values keyed by tag name. Validated against the signal's tag schema, if one is configured — see Signal Schemas & Tags.

Response

A 201 Created response returns the number of events accepted:

JSON
{ "accepted": 1 }

Errors and retries

Every error means nothing from the request was stored. Some are worth retrying and some aren't:

  • 400 Bad Request — a payload targeted an unknown or inactive signal, or failed tag schema validation.
  • 401 Unauthorized — missing, invalid, or expired API key.
  • 403 Forbidden — the API key is missing the signals:emit scope, or isn't scoped to a workspace.
  • 402 Payment Required — the organization has used its plan's monthly event allowance. Retrying won't help until the plan changes or the month turns over.
  • 413 Payload Too Large — the body is over the size limit. Send smaller batches.
  • 429 Too Many Requests — this API key is sending faster than its rate limit. Wait for the number of seconds in the Retry-After header, then send the same request again.
  • 503 Service Unavailable — Datius is catching up on its ingest queue or is briefly unavailable. Wait for Retry-After and send the same request again.

Don't retry a 4xx other than 429; the same request will fail the same way. The SDK follows these rules for you. For common causes, see Troubleshooting.

Processing model

Each event is validated synchronously against its resolved workspace's signal and tag schema before being queued for asynchronous storage as partitioned Parquet files, which dashboards, Live Telemetry, and Reports query directly via embedded DuckDB — no separate ETL step.

For application code, the @datius-io/node SDK wraps this endpoint with in-memory buffering, automatic batching, and retry/backoff, so you rarely need to call it directly from a hot path.

Try it

Explore this endpoint's full request/response schema, or generate a real test key against one of your workspaces, on the API Reference page.