Features / Observability

Every session, request by request. Exported where you already look.

Group requests with x-session-id, read each session’s timeline, export usage as CSV, stream logs to a webhook, Langfuse or OTLP, and cap a session’s spend.

What it does

Sessions from one header
x-session-id groups an agent’s requests; with model "auto" it also keeps one model for the session.
Timeline per session
Every request in order with model, tokens, cost, latency and outcome, in the API and the console.
Usage CSV
GET /v1/usage/export: up to 92 days per file, filterable by key.
Log export
Webhook, Langfuse or OTLP (Datadog, Honeycomb, Grafana), per key or for every key, with retries.
Session caps
Requests per hour and dollars per day per session, set on the key.
Loop guard
Stops an agent that repeats the same tool call or body over and over.

Pricing · live catalog, 2026-11-04

RequestDetailCharge
ticket-8812, request 11,800 in, 220 out on Claude Haiku 5.5$0.0001368
ticket-8812, request 22,600 in, 140 out on Claude Haiku 5.5$0.0001717
ticket-8812, request 33,100 in, 480 out on Claude Haiku 5.5$0.0002503
Session totalGET /v1/sessions/ticket-8812$0.0005587
Sessions, CSV export, log export, capsEvery organizationNo fee

Request example

curl · tag a session
curl https://api.uplinkswitch.com/v1/chat/completions \
  -H "Authorization: Bearer $UPLINK_API_KEY" \
  -H "x-session-id: ticket-8812" \
  -H "Content-Type: application/json" \
  -d '{"model": "claude-haiku-5-5", "messages": [{"role": "user", "content": "Plan the refund steps."}]}'
curl · session timeline and CSV
curl https://api.uplinkswitch.com/v1/sessions/ticket-8812 \
  -H "Authorization: Bearer $UPLINK_ADMIN_KEY"
# every request of the session in order: model, tokens, cost, latency, outcome, plus totals

curl "https://api.uplinkswitch.com/v1/usage/export?from=2026-10-01&to=2026-10-31" \
  -H "Authorization: Bearer $UPLINK_ADMIN_KEY" -o usage.csv
curl · caps on a key
curl -X PATCH https://api.uplinkswitch.com/v1/keys/KEY_ID \
  -H "Authorization: Bearer $UPLINK_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"session_max_requests": 600, "session_max_spend_usd": 5, "loop_guard": true}'
curl · export to Langfuse
curl https://api.uplinkswitch.com/v1/exports \
  -H "Authorization: Bearer $UPLINK_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "langfuse",
    "name": "production traces",
    "public_key": "pk-lf-...",
    "secret_key": "sk-lf-...",
    "host": "https://cloud.langfuse.com"
  }'
curl · export over OTLP
curl https://api.uplinkswitch.com/v1/exports \
  -H "Authorization: Bearer $UPLINK_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "otlp",
    "name": "honeycomb",
    "endpoint": "https://api.honeycomb.io",
    "headers": {"x-honeycomb-team": "YOUR_INGEST_KEY"}
  }'
  • Sessions, the CSV and exports take an admin key, created in the console; the console shows the same data under Usage.
  • Webhook deliveries carry x-uplink-timestamp and x-uplink-signature; the secret is shown once.

Questions

Send an x-session-id header of 1 to 128 visible characters. Without it, x-uplink-session, or a session_id or user field in the body, does the same. A hosted agent’s turns join <agent id>:<session> on their own.

GET /v1/sessions lists sessions newest first with their requests, models, keys, tokens, cost and failed requests. GET /v1/sessions/{id} gives every request of one session in order, up to 1,000, with model, tokens, cost, latency and outcome. The console shows the same timeline under Usage, Sessions.

To a webhook (JSON batches signed with HMAC-SHA256), to Langfuse as generations grouped by session, or to any OTLP/HTTP backend such as Datadog, Honeycomb or Grafana, where a session is one trace and each request a span with gen_ai attributes. Batches go out within about a minute and are retried three times.

Only when the destination has include_bodies on and the request’s key keeps bodies (retain_bodies). Otherwise an event carries the model, tokens, cost, latency and outcome, never the text.

session_max_requests limits requests per session per sliding hour, and session_max_spend_usd limits a session’s charges per UTC day; past either, requests get 429 session_cap. loop_guard refuses a session’s repeated identical tool call or body, more than 5 in 10 minutes, with 429 loop_detected. A runaway agent stops on its own.

One row per request: request_id, created_at, key_id, session_id, model, outcome, status, input, cache read, cache write and output tokens, charge_usd, latency_ms and refund_reason. Up to 92 days and 200,000 rows per file.