Skip to main content

What a spend event is

A spend event is the record of one gateway request: the tokens by class, the cost, the virtual key, the end user and the metadata the request carried. LangWatch delivers spend events to your webhook endpoints and serves the same events over REST. Every request that reaches the gateway pipeline produces an event, including requests the gateway itself rejected for a budget breach, a guardrail, a rate limit, a routing policy rule or a missing end-user id. Those have status: "error" and a zero cost. A request rejected at authentication, for a disabled, revoked or unknown key, produces no event. Spend events, spend summaries and the webhook endpoints are an Enterprise capability. The routes need an organization API key with gatewaySpend:view; replay needs gatewaySpend:manage. A project API key on these routes gets HTTP 401 credential_class_mismatch. See RBAC.

Event lifecycle

An outcome that arrives after settlement is recorded as success or error. A success event is never downgraded. Event ids are stable: <gateway_request_id>:<completed|settled|admitted>. A retried or replayed delivery carries the same id, so you can dedupe on it. Recorded spend never changes: a budget reset moves a period boundary and leaves every event as it was.

The event payload

Webhook deliveries and the REST routes carry the same envelope: { "id", "type", "created", "schema_version": "1", "data" }. The data object: Cost is priced by LangWatch from the token counts and the model pricing, in the same way as the cost on a trace. Sum nano_usd for money; use total_usd for display.

Attribution: what the request carries

The gateway removes the X-LangWatch-* headers before it forwards the request to the provider. The user body field is forwarded unchanged. Every value is stored as sent, so keep personal data out of end-user ids and metadata; events are retained for 13 months.

Receive events by webhook

Create an endpoint under AI Gateway > Webhooks and subscribe it to gateway.request.completed and gateway.request.settled, or to gateway.*. Deliveries are POST requests with a { "batch": [ ...envelopes ] } body and these headers: Answer with a 2xx. A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours, then every 12 hours, up to 11 attempts. A Retry-After header on your response is honoured as a minimum. See Webhooks for endpoints, secrets and the delivery log. The same endpoints receive gateway.budget.threshold_crossed, gateway.budget.breached and the gateway.virtual_key.* lifecycle events. See Budgets and Virtual keys.

Read events over REST

The two list routes take from and to as epoch milliseconds, required, and a cursor from the previous page.
Both list routes take the same filters, repeatable: project_id, team_id, external_id, virtual_key_id, end_user_id, principal_user_id, model, provider_key, request_type, label, metadata as key:value, and status. The status filter also accepts confirmed for success and failed for error. Summaries exclude admitted from status and count only success and error events in their sums, with settled events in settled_count. A summary grouped by model or provider, or bucketed by time, is refused with gateway_spend_group_by_unstable when the window ends less than 30 minutes ago, because outcomes can still arrive. meta.settles_at says when the window is stable.

Reconcile with the SDKs

iterSummaries and iterate (iter_summaries and iterate in Python) fetch the pages for you. summariesPage and listPage (summaries_page and list_page) return one page with its cursor, for a reconciliation you checkpoint across runs. replay calls the replay route.

See events in the UI

AI Gateway > Billing Events lists one row per request over the last 24 hours, 7 days or 30 days, with filters on virtual key id, end user id, model and status.
The Billing Events page over the last 7 days with the Time, Request, Virtual key, End user, Model, Tokens, Cost and Status columns

The Billing Events list: confirmed requests with tokens and cost, refused requests as failed at zero cost, and a realtime session mint still admitted.

The list labels a success event confirmed, an error event failed and a settled event settled. A realtime session mint stays admitted until its outcome arrives, with zero tokens and zero cost, because the call it opened has not started yet. The Request column shows the start of the X-LangWatch-Gateway-Request-Id value. A served request shows the model the gateway resolved and the provider credential that answered; a refused request keeps the model name as the client sent it. The Tokens column shows input, output, cache read (cr), cache write (cw) and reasoning (rsn) counts. It omits every counter whose value is zero.
Also check: Budgets for per-end-user caps that use the same attribution, Webhooks for endpoint management, and the Metering and rebilling cookbook for a complete rebilling flow.
Last modified on September 13, 2026