Observations API v2#
Endpoint: GET /api/public/v2/observations
The v2 observations API is a ClickHouse-backed endpoint that queries the events table instead of the Postgres observations table. It introduces three capabilities not present in v1:
- Field groups — request only a subset of fields to reduce payload size and query cost
- Advanced filters — a structured
filterJSON parameter for complex predicate logic parentObservationIdfilter — hierarchical querying for child observations within a trace
The route handler lives at web/src/pages/api/public/v2/observations/index.ts. The endpoint is currently gated behind the LANGFUSE_ENABLE_EVENTS_TABLE_V2_APIS=true environment variable .
Pagination: v2 uses cursor-based pagination instead of v1's page/offset model. The cursor encodes (lastStartTimeTo, lastTraceId, lastId) as a base64 JSON string . The default page size is 50, maximum is 1000 .
Field Group System#
The fields query parameter accepts a comma-separated list of field group names. Omitting fields defaults to ["core", "basic"] .
| Group | Fields included |
|---|---|
core | id, traceId, startTime, endTime, projectId, parentObservationId, type — always included |
basic | name, level, statusMessage, version, environment, bookmarked, public, userId, sessionId |
time | completionStartTime, createdAt, updatedAt |
io | input, output |
metadata | metadata |
model | providedModelName, internalModelId, modelParameters |
usage | usageDetails, costDetails, totalCost |
prompt | promptId, promptName, promptVersion |
metrics | latency, timeToFirstToken |
The OBSERVATION_FIELD_GROUPS constant is the source of truth for valid group names; the query schema validates and filters any unrecognized values .
Performance note: When io or metadata (with expandMetadata) are requested, the query switches to a CTE-based split strategy: it first filters/orders/limits on events_core (truncated, fast), then fetches full I/O from events_full only for the matched rows. This avoids a full-table scan on the large events_full table . The model group also triggers a conditional Postgres lookup for pricing data; if model is not in the requested groups, that lookup is skipped .
Metadata expansion: Pass expandMetadata=key1,key2 alongside fields=metadata to receive full (non-truncated) values for specific metadata keys .
I/O format: v2 always returns input/output as raw strings. The parseIoAsJson=true option is retired and rejected with an error if supplied .
Filtering#
Simple filters#
These query parameters map directly to ClickHouse column predicates :
| Parameter | Type | Description |
|---|---|---|
traceId | string | Exact match on trace ID |
parentObservationId | string | Match on parent span ID — use to fetch children of a given observation |
userId | string | User associated with the trace |
name | string | Observation name |
type | enum | GENERATION, SPAN, EVENT, AGENT, TOOL, CHAIN, RETRIEVER, EVALUATOR, EMBEDDING, GUARDRAIL |
level | enum | DEBUG, DEFAULT, WARNING, ERROR |
version | string | Observation version |
environment | string or string[] | Environment tag |
fromStartTime / toStartTime | ISO datetime | Time range on startTime |
Advanced filters#
The filter parameter accepts a JSON-serialized array of singleFilter predicates — the same filter schema used by the Langfuse UI. This enables arbitrary combinations of operators (equals, contains, greater-than, etc.) on any indexed column. The array is URL-encoded as a JSON string.
Filters are mapped to ClickHouse column names via PUBLIC_API_EVENTS_COLUMN_MAPPING. If any filter references a traces column, the query automatically joins a traces CTE built from eventsTracesAggregation .
parentObservationId for hierarchical queries#
parentObservationId maps to parent_span_id in the events table . Passing a non-null value fetches all direct children of a given observation within the project. The API normalizes empty strings from ClickHouse back to null in responses for consistency with v1 .
Key Source Files#
| File | Purpose |
|---|---|
web/src/pages/api/public/v2/observations/index.ts | Route handler — validates query, calls repository, encodes cursor |
web/src/features/public-api/types/observations.ts | Zod schemas: GetObservationsV2Query, GetObservationsV2Response, APIObservationV2, cursor encode/decode |
packages/shared/src/server/repositories/events.ts | getObservationsV2FromEventsTableForPublicApi — ClickHouse query assembly, field group selection, CTE split logic, OBSERVATION_FIELD_GROUPS constant |