Live request-log tail
GET /api/v1/logs/tail opens a Server-Sent Events (SSE) connection that streams every API request handled for your tenant, sub-second after each response completes. It is the data source behind the Live tail toggle on the developer Request Logs page, and you can consume it directly from your own tooling.
The stream excludes health, readiness, and metrics probes, as well as the tail endpoint itself.
Base path: /api/v1/logs/tail
Authentication: API key (X-API-Key) or session JWT. The caller must hold the owner, admin, or developer role.
Using the SDKs
Prefer the typed client, but this page’s endpoint has no helper yet — the genericrequest() keeps auth/retries and the { data, meta } envelope identical:
Connect
EventSource, which cannot set request headers, so pass your credential as the token query parameter instead. A dv_-prefixed value is promoted to X-API-Key; any other value is treated as a bearer JWT. When you call from a server you can send the X-API-Key or Authorization header directly and omit token.
Frames
After connecting, the server sends, in order:- An
event: connectedhandshake frame withdata: {"type":"connected", ...}. - A backfill of up to the most recent ~100 request rows.
- New rows live, as each request completes.
: heartbeat) are sent every 30 seconds to keep the connection open. Each request row arrives as a named log frame — listen with addEventListener("log", …), not onmessage, because EventSource only routes named frames to a matching listener.
Each log frame’s data: line is one JSON object:
Adding fields is backwards-compatible — ignore keys you don’t recognize, and drop any row missing a required field.
Resume after a disconnect
Every frame carries anid (a stream cursor). To resume without losing rows, reconnect with the Last-Event-ID request header set to the last id you received — browser EventSource does this automatically. From a client that can’t set the header, pass the same value as the lastEventId query parameter:
Consume from Node.js
Server-side consumers — log forwarders, ETL jobs, on-call bots — authenticate with theX-API-Key header (or an Authorization bearer header). Never send token as a query parameter from server code: a URL ends up in access logs and proxy history, and a credential in it is exposed. If your server library parses named SSE events, use the named event (addEventListener("log", …)), not a generic message handler — the rows arrive as event: log frames, so an onmessage-style handler never sees them.
- eventsource
- Manual parse (fetch)
Consume from Python
Same rules as Node: header auth, namedlog events, a persisted cursor. sseclient dispatches each frame’s event: field to callbacks you register per name — register log, not message. With requests you iterate lines and track the fields yourself:
- sseclient
- requests
Last-Event-ID on reconnect — the server replays the rows you missed.
Limits and errors
On
429 or 503 from a server-side consumer, back off before retrying instead of reconnecting in a tight loop:
- Node.js
- Python