Skip to main content

Reference: Ingest API (advanced, bring your own OTLP)

The agent's loopback auth-proxy signs and forwards everything automatically. This page documents the raw ingest endpoints and HMAC scheme for the case where you want to send telemetry to AtherOps from a system that cannot run the agent. If you send directly, you handle signing yourself.

Authentication: HMAC-SHA256

Every ingest request is authenticated with three headers. The signature is computed over a fixed message built from the request timestamp, method, and the backend request path.

Message format

msg = "<unix_ts>" + "\n" + "<METHOD>" + "\n" + "<path>"
  • <unix_ts>: the request time as Unix seconds (string, e.g. 1748000000).
  • <METHOD>: the HTTP method, e.g. POST.
  • <path>: the request path as the backend sees it, e.g. /ingest, /ingest/traces, /ingest/logs/otlp.

Headers

HeaderValue
X-Timestamp<unix_ts> (the same value used in msg).
X-Key-Hashhex( sha256( rawKey ) ) (lookup index; identifies the key without sending it)
X-Signaturehex( hmac_sha256( rawKey, msg ) ).
  • rawKey is your API key. The raw key is never sent (only its SHA-256 hash and the signature go over the wire).
  • The backend recomputes the signature over the path it receives, so the signed path must equal the actual request path.
  • The timestamp must be within ±5 minutes of the server's clock, or the request is rejected with 401.

Any missing/invalid header, an unknown key hash, or a bad signature returns HTTP 401.

Endpoints

EndpointMethodBodyNotes
/ingestPOSTPrometheus exposition textMetrics → VictoriaMetrics.
/ingest/tracesPOSTOTLP/JSON (ExportTraceServiceRequest)Spans → ClickHouse.
/ingest/logs/otlpPOSTOTLP/JSON (ExportLogsServiceRequest)Logs → ClickHouse.

Bodies are limited to 32 MiB. An empty/zero-record body returns 204 without storing anything.

Responses

StatusMeaning
204 No ContentAccepted (and stored, if non-empty).
400 Bad RequestUnreadable body or invalid OTLP payload.
401 UnauthorizedMissing/invalid auth headers, unknown key, bad signature, or stale timestamp.
502 Bad GatewayStorage backend (VictoriaMetrics / ClickHouse) failed.

Tenant identity is server-derived (you cannot set it)

For every endpoint, the tenant (org_id) and host identity (host_id, node name) are derived server-side from the key lookup, never from your payload.

For the OTLP logs endpoint specifically, any attribute named org_id, host_id, instance, or node in your resource or record attributes is dropped before storage. You cannot spoof another tenant. See Multi-tenant isolation.

Get a query token

The /query/traces and /query/logs endpoints authenticate with the JWT from your AtherOps web session, not an agent API key. To get that token from the command line, call the login endpoint:

ATHEROPS_JWT=$(curl -s -X POST https://api.atherops.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"your-password"}' \
| jq -r .token)
export ATHEROPS_JWT

The token is a short-lived session JWT. If a query returns 401 Unauthorized, log in again to get a fresh one.

Query your traces back

Ingest is HMAC-signed (above). Reading stored spans uses a different endpoint and a different auth scheme: it is authenticated with the JWT from your logged-in AtherOps web session, and is scoped to your org by that token's claims (you cannot read another tenant's spans).

EndpointMethodAuthReturns
/query/tracesGETAuthorization: Bearer <JWT>JSON array of spans for your org, newest first.
curl -s \
-H "Authorization: Bearer $ATHEROPS_JWT" \
"https://api.atherops.com/query/traces?service=api&limit=50"

Query parameters (all optional):

ParamDefaultMeaning
service(all)Filter by service name.
errorfalsetrue returns only error spans.
trace_id(none)Return all spans for one trace (hex trace ID).
start1 hour agoRange start, RFC3339 (e.g. 2026-05-27T10:00:00Z).
endnowRange end, RFC3339.
limit100Max rows (capped at 500).

Each span object includes Timestamp, TraceID, SpanID, ParentSpanID, Service, Operation, DurationMs, StatusCode, Error, and Attributes.

StatusMeaning
200 OKJSON array of spans (may be empty [] if none match).
401 UnauthorizedMissing/invalid bearer token.
405 Method Not AllowedUse GET.
502 Bad GatewayStorage backend query failed.

This release has no in-product trace view. The query API above is how you confirm and read spans today. See scope.

OTLP logs field mapping

When you POST to /ingest/logs/otlp, fields map as follows:

OTLP fieldStored asNotes
log record body (string value)message
severityTextlevellowercased; if empty, mapped from severityNumber; else info
resource attr service.namesourcefalls back to unknown
timeUnixNanotimestampfalls back to observedTimeUnixNano, then now
other resource + record attributeslabelsrecord attrs win on key clash; reserved keys dropped

See also