Spans
spans
Methods
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 the
legacy trace store, to the 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. A span whose parent
belongs to another trace is rejected with 409 before either store is written. The
parent is looked up in Postgres, so that check ends once the account's spans stop
being written there. Which writes the tracing service rejects depends in part on
its storage engine: on Postgres deployments a NUL byte or invalid UTF-8 inside
trace_id, id, parent_id or group_id rejects the span with a 400
naming the field, because replacing the byte would change the identity the
response echoes; a NUL byte or invalid UTF-8 in any other field is replaced with
U+FFFD and the span is persisted. ClickHouse deployments store the bytes verbatim.
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).
Retrieve a single span by its id.
The span is read from the legacy trace store or, for accounts migrated to the
tracing service, from that service — with automatic fallback to the legacy
trace store 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 the legacy trace store, which keeps no token counts.
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 served solely by the legacy trace store: once an account begins dual-writing to the 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 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. A batch that forms a cycle,
or a span whose parent belongs to another trace, is rejected with 409 before either
store is written. A parent outside the batch is looked up in Postgres, so that part
of the check ends once the account's spans stop being written there. Postgres
rejects an id that already exists, while the tracing service treats the write
as an upsert. Which writes the tracing service rejects depends in part on its
storage engine: on Postgres deployments a NUL byte or invalid UTF-8 inside
trace_id, id, parent_id or group_id fails the whole batch with a 400
naming the field, because replacing the byte would change the identity the
response echoes; a NUL byte or invalid UTF-8 in any other field is replaced with
U+FFFD and the span is persisted. ClickHouse deployments store the bytes verbatim.
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).
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. The legacy trace store treats id as global and collapses
repeated ids to the last occurrence. The 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. A batch that forms a cycle, or a span whose parent
belongs to another trace, is rejected with 409 before either store is written. A
parent outside the batch is looked up in Postgres, so that part of the check ends
once the account's spans stop being written there. Which writes the tracing
service rejects depends in part on its storage engine: on Postgres deployments a
NUL byte or invalid UTF-8 inside trace_id, id, parent_id or group_id
fails the whole batch with a 400 naming the field, because replacing the byte would
change the identity the response echoes; a NUL byte or invalid UTF-8 in any other
field is replaced with U+FFFD and the span is persisted. ClickHouse deployments
store the bytes verbatim.
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 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 the legacy trace
store or the tracing service per account (with fallback to the legacy trace
store 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 still served by the legacy trace store, which keeps no token count
to order by. Any other unsupported sort falls back to timestamp order there.
Spans sharing a sort key are ordered by trace_id and id bytewise on both
tracing-service engines. Text search tokenization, indexed-prefix, word-length,
locale and metadata-bytes behavior differs between Postgres and ClickHouse
deployments of the tracing service as the search_texts field describes.
x-project-id narrows the result to traces whose root span carries that project,
when PROJECT_SCOPED_SPAN_LISTING is on for the account. An account the tracing service
serves holds no project placement, so a request carrying the header is rejected with
422 there.
Domain types