Docs
Status
OverviewQuickstartSetup promptsThe core loopAuthenticationOverviewModelsThe waterfallPlansAdding modelsData controlsKYCOpenAI compatibilityEmbeddingsAnthropic APIErrorsIntegrate the gatewayCost APIRequest log APIAccount APICoding agentsSwitch gatewaysCredits & billingSpend & intelligenceSpend APITelemetryBecome a providerProvider guideAPI reference

Get started

  • Overview
  • Quickstart
  • Setup prompts
  • The core loop
  • Authentication

Guides

  • Overview
  • Models
  • The waterfall
  • Plans
  • Adding models
  • Data controls
  • KYC
  • OpenAI compatibility
  • Embeddings
  • Anthropic API
  • Errors

Integrations

  • Integrate the gateway
  • Cost API
  • Request log API
  • Account API
  • Coding agents
  • Switch gateways

Billing & usage

  • Credits & billing
  • Spend & intelligence
  • Spend API
  • Telemetry

Providers

  • Become a provider
  • Provider guide

Reference

  • API reference

Integrations

Request log API

List and filter your organization's requests, read one with its prompt and response, and read latency and spend. These are the reads behind Observability, and any key of your organization can call them.

Access

Send any xpl_ key of your organization as Authorization: Bearer. Every route here is a GET under https://api-pr-1072.preview.experientiallabs.ai/api and reads only that key's organization. Get its id from GET /api/whoami; another organization's id answers 404.

Any key of your organization can read prompt and response bodies when prompt capture is on. Give a key only to code or agents you would let read your traffic. A key bound to a customer plan cannot call these routes.
RouteReturns
GET /api/whoamiYour key's organization: org_id, org_slug, org_name.
GET /api/orgs/{org_id}/usage/requestsOne page of requests, newest first, and next_cursor.
GET /api/orgs/{org_id}/usage/requests/{request_id}One request. With include_body=true, its captured prompt and response as body.
GET /api/orgs/{org_id}/usage/requests/{request_id}/promptThe captured prompt and response alone; 404 when nothing was captured.
GET /api/orgs/{org_id}/usage/requests/{request_id}/attemptsEvery provider dispatch of the request (retries and fallbacks), at most 256.
GET /api/orgs/{org_id}/usage/timeseriesRequests, errors, tokens and cost per time bucket, model and lane.
GET /api/orgs/{org_id}/usage/latencyp50 and p95 latency and time to first token over the window.
GET /api/orgs/{org_id}/usage/by-providerThe same totals per provider.
GET /api/orgs/{org_id}/usage/by-labelThe same totals per end-user label.
GET /api/orgs/{org_id}/telemetry-settingscapture_prompt_content: whether prompts and responses are stored.

Reads with a key are limited per organization: about 10 per second with short bursts, and a few at a time. Over the limit, a read answers 429 with Retry-After. Signed-in dashboard use is not counted.

Let an agent read it

The quickest way to use this API is the agent prompt. In Observability, choose Copy agent prompt at the top right of the Requests table. Paste the prompt into your coding agent and replace the key placeholder with one of your keys. The agent then answers questions such as "why did requests fail today?" or "what did request X send?" with links back to each request. The same prompt is on Setup prompts.

List requests

GET /api/orgs/{org_id}/usage/requests returns newest first. All parameters are optional and combine with AND.

ParameterMeaning
window24h, 7d (default) or 30d, ending now.
start, endAn exact range instead of window (ISO 8601; start inclusive, end exclusive).
modelOne model slug.
api_key_idOne API key's requests.
attribution_labelOne end user: the safety_identifier (or user) your request sent.
laneplatform (paid with credits) or byok (your own provider key).
statuserror (anything not completed) or one of completed, failed, cancelled, incomplete, expired_before_dispatch, unknown_after_crash.
failure_classOne error class, as a row's failure_class shows it.
conversationOne conversation: the hex handle a row shows as conversation_group.
cache_hits_onlytrue: only requests with recorded cached input tokens.
sortcost, latency or tokens (largest first) or oldest. Default: newest first. Not combinable with failure_class or conversation.
limit1 to 200 rows per page (default 50). Out of range answers 422.

Pagination

The response is {requests, next_cursor}. While next_cursor is not null, send the same query again with cursor_ts, cursor_id and cursor_after set from its ts, id and after. A sorted page also returns value and before; send them as cursor_value and cursor_before. The cursor freezes the window, so pages do not shift while new requests arrive.

GET /api/orgs/{org_id}/usage/requests
curl "https://api-pr-1072.preview.experientiallabs.ai/api/orgs/$ORG_ID/usage/requests?window=24h&status=error&limit=50" \
-H "Authorization: Bearer $EXPLABS_API_KEY"

Fields

FieldMeaning
request_id · created_atThe request id (the x-request-id response header) and when it settled.
model · provider · laneThe model slug, the provider that served it, and whose money it rode. provider and lane are null when nothing was dispatched.
api_key_id · key_labelThe key that made the request (null when that key was deleted).
status · failure_class · error_messageTerminal status and, for a request that did not complete, the sanitized reason.
incomplete_reasonWhy an incomplete request stopped (max_tokens or the engine's reason).
latency_ms · ttft_msTotal latency and time to first token, in milliseconds.
input_tokens · cached_input_tokens · output_tokens · reasoning_tokensToken counts. Cached input is part of input; reasoning is part of output.
real_cost_usd · cost_usd · estimated_cost_usd · free_usd · pricing_knownreal_cost_usd is what the call cost, whoever paid: charged credits (cost_usd) plus the estimate for your own provider key (estimated_cost_usd). A free promotional request carries its list value in free_usd. With pricing_known false, 0 means unpriced, not free.
attempt_countProvider dispatches; 0 means it failed before any dispatch.
tools_usedDistinct tool names the request called (names only).
prompt_group · conversation_groupShort handles: same agent configuration, same conversation.
attribution_labelThe end-user label your request sent, or null.
body (one request only)With include_body=true: messages, request (tools and settings), response and wire_request. null when nothing was captured.

Read one request

GET /api/orgs/{org_id}/usage/requests/{request_id} returns the list row for one request. Add include_body=true to inline its captured prompt and response as body: messages, request (tools, tool choice and sampling settings), response (the JSON body, or the stream's frames) and wire_request (the request as the gateway received it, with secrets removed from headers). body is null when the request was not captured.

The request id is the x-request-id header of the response you received. A request appears here once it settles, shortly after the response ends.

GET /api/orgs/{org_id}/usage/requests/{request_id}
curl "https://api-pr-1072.preview.experientiallabs.ai/api/orgs/$ORG_ID/usage/requests/$REQUEST_ID?include_body=true" \
-H "Authorization: Bearer $EXPLABS_API_KEY"

GET .../usage/requests/{request_id}/attempts lists every provider dispatch of the request in order: provider, lane, state, failure_class, error_message, timestamps and tokens. Read it when a request retried or fell back to another provider.

When prompts and responses are stored

  • Bodies are stored only while your organization's prompt capture is on. Read it with GET /api/orgs/{org_id}/telemetry-settings (capture_prompt_content).
  • Requests routed under zero data retention are never stored, even with capture on.
  • A prompt whose response never arrived is kept for two hours, then removed.
  • Requests served on your own provider key or a connected Claude or ChatGPT plan follow the capture setting like any other request.

Everything else on this page (model, tokens, cost, latency, status, errors) is recorded for every request, whatever the capture setting. See Data controls.

Latency and spend rollups

These read the whole window, not a page of rows. Each takes window (24h, 7d or 30d). timeseries, latency and by-provider also filter by model, api_key_id and lane. A 24h window buckets hourly; 7d and 30d bucket daily. timeseries?compare=true adds the previous period's totals.

For exact grouped reports over any dates, use the Spend API (provisioning key). For a full export of settled requests, use POST /api/v1/usage/exports on the Cost API.

Errors and common mistakes

  • 401: the key is wrong or revoked.
  • 404 on every route: the org_id in the path is not your key's organization. Use the one from /api/whoami.
  • 404 on one request: it belongs to another organization, or it has not settled yet. Retry after a few seconds.
  • 400: an unknown status, window or lane, a start after end, or a cursor sent with a different query. The error names the parameter. An unknown status is refused rather than returning an empty list.
  • 422: limit outside 1 to 200, or a sort too broad to read over its filters (sort_too_broad); narrow the window.
  • 429: your organization's keys sent too many reads at once, or the rollups are busy. Wait the Retry-After seconds and retry. For more than a few pages of requests, use the usage export instead of paging the log.
  • body is null: capture is off, the request was routed under zero data retention, or its prompt expired before a response arrived.
PreviousCost APINextAccount API