The event
One event per billable request, emitted after the response has been sent and the usage record written. Schemaaireserve.trace.v1.
Fields
Versioning. Additive changes (a new nullable field) keep
aireserve.trace.v1. A
removed or re-typed field ships as aireserve.trace.v2 with a new schema string, so a
consumer that pins on schema is never surprised. Parse unknown fields leniently.
Test events. The portal’s Send test event button pushes a synthetic event through the
destination’s real sender so you can confirm wiring without waiting for traffic. It is
recognizable and filterable: model.served is aireserve-test-model, request_id starts
with test_, event_id is the zero UUID, attribution.feature is trace-export-test, and
cost is 0. Nothing bills or reconciles against it.
Destinations
An organization can have up to 10 destinations of any mix. Each destination gets every event for the organization; filtering is done on your side.OpenTelemetry collector (OTLP/HTTP)
Point it at any OTLP/HTTP endpoint — the OpenTelemetry Collector, Honeycomb, Grafana Tempo, Datadog APM through the Datadog Agent, and so on. The gateway appends/v1/traces
to the endpoint you give it (or uses it unchanged if it already ends in /v1/traces) and
sends OTLP JSON built by the OpenTelemetry SDK, so the wire format is exactly what any
OTLP-compliant backend expects.
One client span per event:
- Name:
<media kind or text> <served model>, the GenAI semantic-convention{operation} {model}shape —text claude-sonnet-5,image gpt-image-2. - Trace id: the caller’s own trace id when they sent a
traceparentheader, so the span lands inside your application’s trace. Otherwise derived deterministically from the request id. - Span id: derived from
event_id, so a redelivered batch re-exports the same span and collectors dedupe it. - Start / end:
occurred_at - latency_mstooccurred_at. - Status:
OKon success;ERRORwitherror.reasonas the message otherwise. - Resource:
service.name = aireserve-gateway. Scope:aireserve-trace-export. - Attributes: every non-null leaf of the event flattened under
aireserve.plus the GenAI semantic-convention aliases LLM views key on.
aireserve.<path>
(null fields are omitted). Error events add error.type = <error.reason>.
A minimal Collector receiver that accepts it:
collector-config.yaml
Webhook
Any HTTPS endpoint you run. The gateway POSTs a JSON batch and signs it with the destination’s secret so your receiver can prove the batch came from AI Reserve and was not replayed.
The request:
eventsholds up to 100 events in the order they settled on that gateway instance.batch_id(also inX-AIReserve-Delivery) is stable across retries of the same batch, and the body is byte-identical across retries — only the signature’stchanges. Dedupe onbatch_id, or on each event’sevent_idif you flatten batches.- Respond with any
2xxas fast as you can and process asynchronously. A send that takes more than 10 seconds counts as a failure and is retried.
Verify the signature
X-AIReserve-Signature is t=<unix seconds>,v1=<hex HMAC-SHA256> where the MAC is
computed over the string <t>.<raw request body> with the destination’s secret. Verify
against the raw bytes you received (before any JSON parsing), compare in constant time,
and reject timestamps more than five minutes from your clock to defeat replays. During a
secret rotation the header can carry more than one v1= entry; accept the batch if any of
them matches.
Datadog Logs
Sends straight to your Datadog account’s log intake on your API key — no agent or pipeline needed. One log entry per event, with the whole event nested underaireserve so
facets such as @aireserve.model.served and @aireserve.cost.charged_usd work immediately.
The request:
statusisinfofor successful requests anderrorfor failed ones; error entries readaireserve <model> error <reason> (<fault>).timestampis the settle instant in epoch milliseconds, so entries land at the time the request happened rather than when the batch was delivered.- Useful starting queries:
source:aireserve @aireserve.status:error,source:aireserve @aireserve.attribution.end_customer_id:acme-eu, or a measure over@aireserve.cost.charged_usdgrouped by@aireserve.model.served.
Delivery
Export happens after the response. Each gateway instance pushes the settled event onto an in-memory queue and returns; everything else — batching, sending, retrying, pausing — runs in the background, so a slow or failing destination never slows or fails a request.
Delivery is at least once: a batch can arrive twice if your endpoint accepted it but the
acknowledgement was lost. Ordering is per gateway instance, not global. Dedupe on
event_id (or the OTLP span id, which derives from it).
Health
The portal shows live health for every destination: last successful delivery, last failure and its reason (an HTTP status or a short transport reason, never a response body), failures in the last 24 hours, events dropped, and events delivered. A destination with a tripped breaker shows when it will retry. Send test event bypasses the queue and the breaker so you can check a fix immediately.Security
- Secrets (bearer tokens, webhook secrets, Datadog API keys) are encrypted at rest with AES-256-GCM in the same envelope scheme that protects BYOK provider keys, decrypted only inside the gateway at the moment of sending, and shown in the portal only as their last 4 characters. They are never written to logs, error records or audit entries.
- Destination URLs must be HTTPS (loopback
http://is allowed for a local collector during development). Redirects are not followed, and response bodies are never read. - Destinations must be public hosts. Private, loopback, link-local and cloud-metadata
addresses, and internal-only names (
localhost,*.internal,*.local), are refused when you save, and the host is resolved again on every send so a name that later points at a private address is refused too and shows as a failed delivery. - Adding, editing, pausing, testing and removing destinations are admin-only actions, recorded in the internal audit log and on your organization’s Activity page.
- Events carry ids and measurements only. The payload type is guarded against content-shaped
fields (
prompt,messages,content,tool_calls,headers,error_message, …) by a compile-time check and a unit test, and the event builder reads a fixed allow-list of usage metadata rather than copying it.
Set it up
1
Open Trace Export
In the portal, go to Observe › Trace Export (admins
only). From the platform admin console the same page is under the client’s
Observability section.
2
Add a destination
Choose OpenTelemetry collector, Webhook or Datadog Logs, give it a name, and
paste the endpoint and secret. Settings are validated before they are saved.
3
Send a test event
Use Send test event on the new destination and look for model
aireserve-test-model
on the receiving side. A refusal is reported with the HTTP status so you can fix the URL
or secret in place.4
Watch it deliver
Real traffic starts flowing within about a minute. The row shows last success, failures
in the last 24 hours, dropped and delivered counts. Pause a destination with the toggle
at any time; events during a pause are not queued.
v1 manages destinations in the portal only. A public API for destinations, per-destination
filters (by model, key or team) and an S3/GCS batch sink are on the roadmap; tell us which
you need first.