Spans

spans

Methods

Create A Span ->
post/v5/spans

Create a single span and return the persisted span.

Use this for one-off span ingestion; to write many spans in one request use POST /v5/spans/batch. When id is omitted the server generates a UUID. Depending on per-account server configuration the span is persisted to Postgres, to the ClickHouse-backed tracing service, or both. end_timestamp must not precede start_timestamp, which is rejected with a 422. When the tracing service is the primary store, its 400, 413 and 422 rejections keep that status and detail, as does a 403 when the request carried its own API key, and every other failure returns a 503 with a Retry-After header.

Credential redaction: values in the free-form input, output, metadata, and expected objects, and in name, that are credential-shaped (bearer/JWT, API keys, connection-string passwords) or under a credential-named key are replaced with [REDACTED:credential] before the span is persisted, so the stored and returned span reflects the redacted value (EY 12.3).

Response fields
Request example
200Example
Get A Span ->
Deprecated
get/v5/spans/{span_id}

Retrieve a single span by its id.

The span is read from Postgres or, for accounts migrated to the ClickHouse-backed tracing service, from that service — with automatic fallback to Postgres on error unless the account is in strict mode, where a tracing-service failure surfaces as a 503. Access is authorized against the span's parent trace, so a span in a trace the caller cannot read is rejected; an unknown id returns 404. input_tokens and output_tokens carry the token usage the span's producer reported at ingest, and are absent both for a span that reported none and for every span served from Postgres.

Update A Span ->
patch/v5/spans/{span_id}

Partially update a span's mutable fields and return the updated span.

Only the provided fields among name, end timestamp, output, metadata, and status are changed. This endpoint is available only for accounts still backed solely by Postgres: once an account begins dual-writing to the ClickHouse-backed tracing service — which is upsert-only and has no partial-update operation — PATCH returns 501 and PUT /v5/spans/batch must be used instead. Updates are authorized against the span's parent trace, and an unknown id returns 404.

Credential redaction: values in the free-form input, output, metadata, and expected objects, and in name, that are credential-shaped (bearer/JWT, API keys, connection-string passwords) or under a credential-named key are replaced with [REDACTED:credential] before the span is persisted, so the stored and returned span reflects the redacted value (EY 12.3).

Create Spans In A Batch ->
post/v5/spans/batch

Create multiple spans (up to 1000) in a single request and return the created spans.

Prefer this over repeated POST /v5/spans calls when ingesting many spans at once; use PUT /v5/spans/batch instead when a span with the same id may already exist, since this endpoint inserts new spans rather than overwriting. A batch larger than 1000 spans is rejected with a validation error. Each item follows the same id-generation and per-account dual-write rules as the single-span create, including that end_timestamp must not precede start_timestamp, which rejects the request with a 422. When the tracing service is the primary store, its 400, 413 and 422 rejections keep that status and detail, as does a 403 when the request carried its own API key, and every other failure returns a 503 with a Retry-After header.

Credential redaction: values in the free-form input, output, metadata, and expected objects, and in name, that are credential-shaped (bearer/JWT, API keys, connection-string passwords) or under a credential-named key are replaced with [REDACTED:credential] before the span is persisted, so the stored and returned span reflects the redacted value (EY 12.3).

Upsert Spans In A Batch ->
put/v5/spans/batch

Insert or replace multiple spans (up to 1000) in a single request.

Use this for idempotent ingestion when spans may already exist, unlike POST /v5/spans/batch, which only inserts. Items without an id are assigned a generated UUID. Postgres treats id as global and collapses repeated ids to the last occurrence. The ClickHouse-backed tracing service keys spans by trace_id and id; it retains cross-trace ID collisions, and for a repeated pair keeps a completed span over an in-progress one, otherwise the later occurrence wins. In dual-write phases each store applies its own rule, and the primary store determines the returned list. A batch larger than 1000 spans is rejected with a validation error, as is any item whose end_timestamp precedes its start_timestamp, which returns a 422. When the tracing service is the primary store, its 400, 413 and 422 rejections keep that status and detail, as does a 403 when the request carried its own API key, and every other failure returns a 503 with a Retry-After header.

Credential redaction: values in the free-form input, output, metadata, and expected objects, and in name, that are credential-shaped (bearer/JWT, API keys, connection-string passwords) or under a credential-named key are replaced with [REDACTED:credential] before the span is persisted, so the stored and returned span reflects the redacted value (EY 12.3).

Search Spans -> CursorPage<>
post/v5/spans/search

Search and list spans matching a set of filters, returning a keyset-paginated page.

Filters in the request body include trace and span ids, names, statuses, types, free-text search, metadata, duration bounds, and more, scoped to an optional time window. Results are keyset-paginated on indexed columns rather than offset-paginated, and total is not computed (it is always 0); use the pagination cursors to page through results. Reads route to Postgres or the ClickHouse-backed tracing service per account (with Postgres fallback outside strict mode), and results are narrowed to traces the caller is authorized to read — a filter that resolves to no authorized traces yields an empty page rather than an error. A reversed time window (from_ts after to_ts) is rejected with 422, as is a request whose combined trace_ids, span_ids, excluded_span_ids, excluded_trace_ids, and parent_ids count exceeds 10000. sort_by accepts start_timestamp, duration_ms, input_tokens and output_tokens; the token counts are read from usage reported at ingest, and a span whose producer reported none sorts as zero, so it lands last descending and first ascending. The two token sorts are rejected for an account whose spans are read from Postgres, which stores no token count to order by. Any other unsupported sort falls back to timestamp order there.

Domain types

APIListSpan = { items, object }
Span = { id, account_id, name, 19 more... }
SpanBatchCreate = { items }
SpanCreate = { name, start_timestamp, trace_id, 14 more... }
SpanStatus = "SUCCESS" | "ERROR" | "CANCELED"
SpanType = "TEXT_INPUT" | "TEXT_OUTPUT" | "COMPLETION_INPUT" | 23 more...