AI calls as usage events

If you would rather not route your AI calls through the proxy, keep calling your provider directly and tell us the numbers afterwards. Same key, same dashboard, same charts.

The request

Use a Usage only key, as for the proxy. MCP read only and MCP management keys cannot send events and return 403 insufficient_key_permissions. Keep the key on your server, never in browser or mobile code.

One POST per AI call, from your server, after the call finished. Generate one UUID for that call, save it with the numbers, and reuse it for every delivery attempt. It costs your user nothing: send it in the background and do not make anyone wait for our answer.

request
POST https://api.hereling.com/events/usage
x-hereling-key: hl_live_…
content-type: application/json

{
  "event_id": "6f281b76-0c60-4ce9-9078-726e37198128",
  "user": "user_42",
  "feature": "summary",
  "provider": "openai",
  "model": "gpt-4o-mini",
  "input_tokens": 1200,
  "output_tokens": 300,
  "cost_usd": 0.00036,
  "duration_ms": 950,
  "status_code": 200
}

The fields

FieldRequiredMeaning
event_idyesA UUID generated once per AI call. Reuse the same ID and fields on retries
provideryesopenai, openrouter, deepseek or anthropic
modelyesThe model you called, spelled as the provider spells it
input_tokensyesTotal input including cache reads and writes; whole number
output_tokensyesWhole number
usernoYour own id for the end user; recorded as unknown when missing
featurenoA short name for the feature; unknown when missing
cost_usdnoWhat the call cost you. Otherwise Hereling uses reference token rates when available
cache_read_input_tokensnoCached reads, a subset of input_tokens
cache_creation_input_tokensnoCache writes, a separate subset of input_tokens
cache_creation_5m_input_tokensnoAnthropic 5-minute writes; send both durations when using cache writes
cache_creation_1h_input_tokensnoAnthropic 1-hour writes; the two durations must sum to cache_creation_input_tokens
duration_msnoHow long the call took
status_codenoThe provider's HTTP status

Counts and duration must fit a whole number from 0 to 2,147,483,647; a single call's cost must not exceed $999,999.99999999. Send cache counts whenever applicable. For Anthropic, add ordinary input, cache reads and cache writes to get input_tokens. Missing cache rates or write durations leave cost unknown. Use your provider's actual cost_usd for images, audio, server tools, special tariffs or other charges beyond text tokens. Reference pricing assumes the token breakdown you send is complete.

Use the same user value you put on payments, so revenue and cost meet on the same person. See revenue webhooks.

The answer

200 with { "ok": true, "event_id": "…", "status": "recorded" } means the record is saved. A duplicate with the same ID and fields returns the same result without charging quota or adding cost again. 202 with status: "queued" means the numbers are stored durably for automatic retry, but are not yet in the report. Unknown fields are dropped and listed inignored, for example "ignored": ["messages"].

There is no field for prompts or answers, on purpose. If you send one, it is thrown away before anything is written down, and the reply tells you it was.

On the free plan, after 10,000 recorded requests in a calendar month, new events return429 monthly_request_limit. The event is not recorded. This is not success: surface the recording gap in your integration. The same rejected ID remains rejected; do not give it a new ID to bypass the limit. Upgrade to record future calls. New calls in the next month have new IDs.

For a timeout or 503 service_unavailable, retry the same event with exponential backoff. A different payload with an existing ID returns 409 event_id_conflict. Never retry the AI provider call just because delivery to Hereling failed. Keep a durable numeric outbox on your server; Hereling cannot recover an event it never received. Old integrations must add event_idbefore this version is deployed; missing or invalid IDs return 400 invalid_event.

Errors use the same shape as the proxy, with the code invalid_event and a message naming the field that is wrong.

Proxy or events?

ProxyUsage events
Code to writeChange one address, add three headersOne POST after every AI call
Token countingWe read it from the provider's answerYou send the numbers
Works with any providerFour providers todayAny provider you can name
Per-user limits and model switchYesNo — those need the proxy

You can use both in one project: the proxy for the calls it supports, events for anything else. Rows from either path land in the same tables.

Traffic limits

Usage events accept at most 64 KiB per request and 120 requests per project per 60-second window, shared across all project keys. Uploads must finish within 15 seconds. A rejected oversized body returns HTTP 413; a traffic rejection returns HTTP 429 with Retry-After. This traffic limit is separate from the monthly recording quota.