Observability & analytics
Every call the proxy forwards is already recorded in an invocation row — status, mode, timing, sizes, upstream status, and (when enabled) the request/response bodies. This is the read/analytics layer over that data: list and inspect individual invocations, or pull aggregate metrics per agent and over time, without bolting on an external observability stack.
Listing invocations
Section titled “Listing invocations”curl -H "Authorization: Bearer $TOKEN" \ "localhost:8080/v1/invocations?agent_id={id}&status=failed&limit=20"GET /v1/invocations is tenant-scoped, offset-paginated, and filterable by
agent_id, status (pending|running|succeeded|failed), mode
(transactional|streaming), error_class, model, settlement, and a
since/until RFC 3339 window. Bodies are never returned on the list
endpoint.
Fetching one invocation
Section titled “Fetching one invocation”curl -H "Authorization: Bearer $TOKEN" \ localhost:8080/v1/invocations/{id}GET /v1/invocations/{id} returns the full record, including
MCP method/tool and
payment/settlement fields when applicable. req_body / resp_body are
included only when body capture was on for that invocation (an
agent-level toggle, off by default) and the
caller’s token carries the invocations:read_body OAuth scope — metadata
reads don’t need it. When present, bodies are base64-encoded and capped at
1 MiB; body_captured reflects whether capture was on regardless of whether
the caller can read the bodies.
What gets captured
Section titled “What gets captured”Beyond the obvious (status, latency, sizes, upstream status), three fields are worth knowing about:
ttft_ms— time to first byte on the streaming path;nullfor transactional invocations or when no bytes streamed.error_class— a coarse failure taxonomy set by the proxy on failure:timeout,upstream_5xx,upstream_4xx,ssrf_blocked,credential_error,cancelled,internal.nullon success.model— caller-supplied only, via theX-Farcaster-Modelrequest header (see Routing & proxy). Farcaster proxies arbitrary upstream agents, not a known LLM wire format, so it does not parse bodies to infer a model. MCP is the one exception — see MCP-native transport.
Aggregate analytics
Section titled “Aggregate analytics”curl -H "Authorization: Bearer $TOKEN" \ "localhost:8080/v1/analytics?group_by=agent_id&bucket=day&since=2026-07-01T00:00:00Z"GET /v1/analytics aggregates the tenant’s invocations by agent_id and a
time bucket (hour or day), returning per-group count, error_rate,
by_error_class, and latency_ms / ttft_ms percentiles (p50/p95/p99). A
few things to know:
sinceis required — there is no default window; an unbounded query is rejected with400.- The
[since, until]range is capped at 31 days. A wider range is400. - The endpoint carries its own, tighter rate limit than the general
/v1limiter, since percentile aggregation is heavier than a row fetch — a429here doesn’t mean the rest of the API is throttled. - An empty window returns
200with an emptygroupsarray, not404. - In-flight (
pending/running) invocations count towardcountbut are excluded from latency percentiles.
Everything is tenant-scoped
Section titled “Everything is tenant-scoped”Every query in this surface filters tenant_id first — the same convention
as every other surface (see Auth & multi-tenancy).
An invocation ID belonging to another tenant returns 404, never 403, and
/v1/analytics only ever aggregates the caller’s own tenant.
Full reference
Section titled “Full reference”Every filter, field, and status code for /v1/invocations,
/v1/invocations/{id}, and /v1/analytics is in the
gateway /v1 REST reference, generated from the
gateway’s openapi.yaml.