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.
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
| Field | Required | Meaning |
|---|---|---|
event_id | yes | A UUID generated once per AI call. Reuse the same ID and fields on retries |
provider | yes | openai, openrouter, deepseek or anthropic |
model | yes | The model you called, spelled as the provider spells it |
input_tokens | yes | Total input including cache reads and writes; whole number |
output_tokens | yes | Whole number |
user | no | Your own id for the end user; recorded as unknown when missing |
feature | no | A short name for the feature; unknown when missing |
cost_usd | no | What the call cost you. Otherwise Hereling uses reference token rates when available |
cache_read_input_tokens | no | Cached reads, a subset of input_tokens |
cache_creation_input_tokens | no | Cache writes, a separate subset of input_tokens |
cache_creation_5m_input_tokens | no | Anthropic 5-minute writes; send both durations when using cache writes |
cache_creation_1h_input_tokens | no | Anthropic 1-hour writes; the two durations must sum to cache_creation_input_tokens |
duration_ms | no | How long the call took |
status_code | no | The 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"].
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?
| Proxy | Usage events | |
|---|---|---|
| Code to write | Change one address, add three headers | One POST after every AI call |
| Token counting | We read it from the provider's answer | You send the numbers |
| Works with any provider | Four providers today | Any provider you can name |
| Per-user limits and model switch | Yes | No — 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.