Request Logs
GET /logs?range=<range>&after=<ts>&after_id=<id>&errors=<bool>&limit=<n>Returns the full per-request log for your organization, ordered newest-first.
You can also retrieve and inspect the same logs in the console under Analytics → Logs. Use the console for interactive troubleshooting and the API for programmatic retrieval or export.
Query parameters
Section titled “Query parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
range | string | No | 15m, 1h, 6h, 24h, 7days, 30days. Default: 24h. |
after | RFC3339 | No | Pagination cursor — timestamp of the last row of the previous page. |
after_id | string | No | Pagination cursor — request_id of the last row, breaks timestamp ties. |
errors | boolean | No | If true, only non-2xx requests. |
endpoint | string | No | Only requests to this /v1 path, e.g. /v1/responses. |
content_logged | boolean | No | If true, only requests where capture was attempted (see below). The page is then ordered by request_at. |
limit | integer | No | Page size. Capped at 100. Default: 50. |
Response
Section titled “Response”{ "data": [ { "id": "...", "model": "...", "api_key": "sk-...abcd", "status_code": 200, "ttft_ms": 210, "latency_ms": 420, "input_tokens": 123, "output_tokens": 45, "cached_tokens": 64, "cost": "0.00420000", "currency": "usd", "created_at": "2026-05-18 12:34:56.123456+00", "request_at": "2026-05-18 12:34:55.901234+00", "endpoint": "/v1/chat/completions", "content_logged": true } ], "has_more": true, "next_after": "2026-05-18 12:34:55.654321+00", "next_after_id": "..."}cost is denominated in currency — the org’s billing currency (usd or jpy); it is never a bare USD figure. When has_more is false, you’ve reached the end of the available range.
cached_tokens is the portion of input_tokens that was billed at the discounted cached input rate — a repeated prompt prefix. It is 0 when there was no cache hit and null on models without a cached rate.
request_at is when the request was received; created_at is when the row was settled, a moment later. Rows are ordered and paged by created_at, or by request_at when content_logged=true; next_after always carries the matching value, so pass it back unchanged. endpoint is the /v1 path, and content_logged says whether capture was attempted for this request — not that storage necessarily succeeded. A rare miss surfaces as unavailable in the detail response, never as content_logged: false (see Content logging).
Pagination
Section titled “Pagination”Pass next_after and next_after_id from the previous page as after and after_id. Using after alone is unsafe — multiple requests can share a millisecond timestamp.
API key or JWT + X-Org-ID. See Authentication.
Retrieve one request (with content)
Section titled “Retrieve one request (with content)”GET /logs/{id}Returns one request’s metadata plus its captured content (the request body and the response), when content logging is enabled for your organization (see Content logging). Use the id from the list, or the X-Request-ID header returned on every /v1 response.
{ "id": "...", "state": "ready", "metadata": { "model": "...", "endpoint": "/v1/chat/completions", "api_key": "sk-...abcd", "status_code": 200, "input_tokens": 123, "output_tokens": 45, "cost": "0.00420000", "currency": "usd", "request_at": "2026-05-18 12:34:56.123456+00", "created_at": "2026-05-18 12:34:58.000000+00" }, "content": { "endpoint": "/v1/chat/completions", "streamed": false, "capturedAt": "2026-05-18T12:34:56.123Z", "responseId": "chatcmpl_...", "request": "{ ...the request you sent... }", "response": "{ ...the response... }", "error": null, "truncated": false }}request and response are stored as text — a JSON string for a non-streamed response, and the captured SSE event stream for a streamed one — so you parse them client-side. The stored values retain the endpoint’s native shape (/v1/messages uses the Anthropic shape, for example), but they are processed for safe storage and are not guaranteed to be byte-for-byte identical to the original wire content. Inline-media placeholders and size truncation are described below.
For streamed responses, inline-media replacement is applied only to JSON payloads in the stored copy’s data: events. The SSE framing and non-media events remain parseable in their original form, and the live stream delivered to your client is never modified by request logging.
As a general rule, each captured log record is limited to 10 MiB (approximately 10 MB) across the request, response, and envelope metadata. Content beyond that limit is truncated rather than rejected: truncated is true, and the stored text includes a truncation marker. Inline base64 media is replaced with an omitted:<media-type>;bytes=<n> placeholder before the size limit is applied.
For a failed request, response is the error body you received and error carries its message plus status — the upstream status when there was one, otherwise the status you received. The upstream body itself is never stored.
Client-supplied request ids must match [A-Za-z0-9._:@=+-]{1,36}. If your X-Request-ID is outside that shape, the service replaces it with a generated id; use the X-Request-ID returned in the response to retrieve the metadata and content.
content may be absent; state says why, so the response is never an error unless the id is unknown:
| State | Meaning |
|---|---|
ready | Metadata and content are both present. |
processing | The request just completed; metadata is still settling. |
not_logged | Content logging was off for this request. |
expired | Older than 30 days — the content has been deleted. |
unavailable | Content was expected but is missing. |
A 404 is returned only when neither metadata nor content exists.
Delete stored content
Section titled “Delete stored content”DELETE /logsOrganization admins only. Starts deleting every stored request/response body for your organization and returns 202 { "accepted": true }; the purge finishes in the background within a few minutes. Metadata rows are kept, and affected requests then open as unavailable. Deleting does not change the logging switch: while logging is on, requests made after the purge are captured again. Turning logging off first is not a clean cut either, since capture can continue for up to about a minute after the switch (see Content logging).
Content logging
Section titled “Content logging”Capturing request/response bodies is opt-in and off by default. Metadata (the list above) is always recorded; content (the actual prompts and responses) is stored only while content logging is on.
GET /logs/settingsPATCH /logs/settings { "log_content_enabled": true }GET returns { "log_content_enabled": <bool>, "available": <bool> } and reflects a PATCH immediately. When available is false, hide the content-capture control; deletion remains available. PATCH (organization admins only) toggles logging when available.
Organization admins can also turn content logging on or off in the console under Settings → Organizations → Request Logging. The switch is shown only when content capture is available in the current environment; when it is unavailable, the console still allows admins to delete previously stored content.