openapi: 3.2.0 info: title: Latitude Spans API version: v1 description: Open-source AI agent monitoring platform. Full observability into what's failing in production. Discover underlying issues, get alerts when something breaks and verify your fix worked. servers: - url: https://api.latitude.so description: Production servers: - url: https://api.latitude.so tags: - name: Spans paths: /v1/projects/{projectSlug}/spans/query: post: tags: - Spans x-fern-sdk-group-name: spans x-fern-sdk-method-name: query summary: Query spans across traces description: 'Returns a cursor-paginated page of spans across all traces in the project matching `filters` (and an optional time `range`). The span-grain, row-level complement to `queryAnalytics` with `stream: "spans"` (which returns aggregates): use this to drill from an aggregate into the individual spans behind it — e.g. every failing `search_docs` tool span, or the slowest embedding calls.' security: - ApiKeyAuth: [] operationId: querySpans parameters: - schema: type: string description: Project slug (human-readable identifier) required: true description: Project slug (human-readable identifier) name: projectSlug in: path requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/QuerySpansBody' responses: '200': description: Page of spans content: application/json: schema: $ref: '#/components/schemas/QuerySpans' '400': description: Validation error content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/Error' components: schemas: SpanRowFilterSet: type: object additionalProperties: type: array items: $ref: '#/components/schemas/FilterCondition' description: Structured filter set over span row fields. `gtePercentile` is not supported — use absolute thresholds or a percentile metric. QuerySpansBody: type: object properties: filters: allOf: - $ref: '#/components/schemas/SpanRowFilterSet' - description: Row-local span filter set (same DSL as `listTraces`) over span fields — `operation`, `toolName`, `model`, `provider`, `sessionId`, `traceId`, `tags`, `status` (`error`/`ok`/`unset`), `duration`, `cost`, `tokensInput`/`tokensOutput`. `gtePercentile` is not supported — use absolute thresholds or a percentile metric. orderBy: type: object properties: field: type: string enum: - startTime - duration - cost default: startTime description: Sort key. direction: type: string enum: - asc - desc default: desc description: Sort direction. description: Sort order. Defaults to newest first (`startTime` desc); use `duration`/`cost` desc for top-N slowest/costliest. range: type: object properties: fromIso: type: string format: date-time example: '2026-06-23T00:00:00Z' description: Inclusive lower bound (ISO-8601). toIso: type: string format: date-time example: '2026-06-30T00:00:00Z' description: Upper bound (ISO-8601). Must be after `fromIso`. required: - fromIso - toIso description: Restrict to spans whose `startTime` falls in this window. cursor: type: string description: Opaque cursor from a previous response's `nextCursor`. Omit on the first page. limit: type: integer minimum: 1 maximum: 200 default: 50 description: Page size. Defaults to 50; max 200. Error: type: object properties: error: type: string required: - error FilterCondition: type: object properties: op: type: string enum: - eq - neq - gt - gte - lt - lte - in - notIn - contains - notContains - gtePercentile description: Comparison operator applied to the field's value (e.g. `eq`, `neq`, `in`). The full operator list lives in the API reference. value: anyOf: - type: string - type: number - type: boolean - type: array items: anyOf: - type: string - type: number description: Right-hand value compared against the field. Arrays are required for `in` / `notIn`-style operators. required: - op - value QuerySpans: type: object properties: items: type: array items: $ref: '#/components/schemas/Span' description: Matching spans across traces, newest first. Rows exclude per-message LLM content — use a span point-lookup for the payload. nextCursor: type: string nullable: true description: Cursor for the next page, or `null` when there are no more spans. hasMore: type: boolean description: Whether more spans match beyond this page. required: - items - nextCursor - hasMore Span: type: object properties: organizationId: type: string description: Organization that owns this span. projectId: type: string description: Project this span belongs to. traceId: type: string description: Identifier of the trace this span belongs to. spanId: type: string description: Stable span identifier within the trace. parentSpanId: type: string nullable: true description: Identifier of the parent span. `null` for root spans. sessionId: type: string nullable: true description: Conversation/session identifier set by the SDK. `null` when absent. userId: type: string nullable: true description: End-user identifier set by the SDK. `null` when absent. simulationId: type: string nullable: true description: CUID of the simulation that produced this span. `null` when not a simulation. apiKeyId: type: string nullable: true description: Latitude API key used to ingest the span. `null` when ingested without an API key. startTime: type: string description: ISO-8601 timestamp at which the span started. endTime: type: string description: ISO-8601 timestamp at which the span ended. name: type: string description: Span name (e.g. the entry-point function or route). serviceName: type: string description: OpenTelemetry `service.name` of the emitting service. kind: type: string enum: - unspecified - internal - server - client - producer - consumer description: OpenTelemetry span kind. statusCode: type: string enum: - unset - ok - error description: OpenTelemetry span status code. statusMessage: type: string description: OpenTelemetry status message. Empty when not set. traceFlags: type: number description: OpenTelemetry trace flags bitfield. traceState: type: string description: OpenTelemetry trace state (vendor-specific propagation). Empty when not set. errorType: type: string nullable: true description: Error class/type label when the span errored. `null` for successful spans. tags: type: array items: type: string description: Free-form tags attached at ingest time. operation: type: string description: GenAI operation category (e.g. `"chat"`, `"embeddings"`, `"execute_tool"`, `"invoke_agent"`) or a custom string for non-GenAI spans. provider: type: string nullable: true description: LLM provider id. `null` for non-LLM spans. model: type: string nullable: true description: Model id as requested. `null` for non-LLM spans. responseModel: type: string nullable: true description: Model id reported by the provider's response. `null` for non-LLM spans. tokensInput: type: number description: Input tokens consumed by this span. tokensOutput: type: number description: Output tokens produced by this span. tokensCacheRead: type: number description: Tokens served from the provider's prompt cache. tokensCacheCreate: type: number description: Tokens written to the provider's prompt cache. tokensReasoning: type: number description: Reasoning tokens reported by the model. costInputMicrocents: type: number description: Cost of input tokens in microcents (100,000,000 per USD). costOutputMicrocents: type: number description: Cost of output tokens in microcents (100,000,000 per USD). costTotalMicrocents: type: number description: Total cost in microcents (100,000,000 per USD). costIsEstimated: type: boolean description: '`true` when the cost was derived from public pricing tables instead of the provider''s bill.' costSource: type: string enum: - provider_reported - user_reported - estimated - unpriced - no_tokens - unknown description: 'Where the cost came from. `provider_reported`: the instrumentation sent it. `user_reported`: you sent it with `latitude.cost.source` set to `user`. `estimated`: priced from public model pricing. `unpriced`: tokens were reported but no pricing matched, so the cost is 0 but not free. `no_tokens`: nothing to price. `unknown`: ingested before cost sources were tracked, so a 0 cannot be read as free.' timeToFirstTokenNs: type: number description: Nanoseconds from the start of the span to its first emitted token. `0` if not measured. isStreaming: type: boolean description: '`true` when the span was produced by a streaming LLM call.' responseId: type: string nullable: true description: Response identifier returned by the LLM. `null` when the provider didn't return one. finishReasons: type: array items: type: string description: Per-choice finish reasons reported by the LLM provider. scopeName: type: string description: OpenTelemetry instrumentation scope name. Empty when not set. scopeVersion: type: string description: OpenTelemetry instrumentation scope version. Empty when not set. retentionDays: type: integer minimum: 0 exclusiveMinimum: true description: Per-span retention override in days. Omitted when the project default applies. ingestedAt: type: string description: ISO-8601 timestamp at which Latitude received this span. required: - organizationId - projectId - traceId - spanId - parentSpanId - sessionId - userId - simulationId - apiKeyId - startTime - endTime - name - serviceName - kind - statusCode - statusMessage - traceFlags - traceState - errorType - tags - operation - provider - model - responseModel - tokensInput - tokensOutput - tokensCacheRead - tokensCacheCreate - tokensReasoning - costInputMicrocents - costOutputMicrocents - costTotalMicrocents - costIsEstimated - costSource - timeToFirstTokenNs - isStreaming - responseId - finishReasons - scopeName - scopeVersion - ingestedAt securitySchemes: ApiKeyAuth: type: http scheme: bearer bearerFormat: API key description: 'Organization-scoped API key, sent as `Authorization: Bearer `.' x-fern-bearer: name: apiKey env: LATITUDE_API_KEY