HookGet Open dashboard

OpenAI → HookGet

HookGet reads OpenAI's reporting API on a schedule and turns it into normalised events on the same pipeline as everything else you deliver.

In short

  • Reads /v1/organization/usage/completions and /v1/organization/costs with an admin key, on your interval.
  • Each settled time bucket becomes an llm.usage_reported event per model: input/output/cached tokens and request count. Money arrives separately as one llm.cost_reported event per settled day.
  • Buckets are read only after ~90 minutes of settling — OpenAI keeps writing into the current one, and double-counting an hour is worse than lagging it.
  • Aggregates only: no prompts, no completions, nothing personal leaves your OpenAI account.

What it produces

Read from the APIBecomesData
A settled usage bucket, per modelllm.usage_reportedinput_tokens, output_tokens, cached_input_tokens, model_requests, total_tokens
A settled day of org spendllm.cost_reportedcost_usd — sum it and you have the bill

Set up

# Create an ADMIN key in the OpenAI console (organization settings), then:
curl -X POST https://api.hookget.com/v1/sources \
  -H "authorization: Bearer $HOOKGET_KEY" \
  -d '{"provider":"openai","secret":"<admin key>",
       "config":{"bucket_width":"1h"},"sync_interval_sec":900,
       "backfill_from":"2026-08-01T00:00:00Z"}'
# First sync runs immediately; backfill reaches up to 90 days
One scheduled sync of a pull source The scheduler claims a due source, fetches from the provider's API with the saved cursor, normalises the response into events, and stores them. Only when the sync succeeds does the cursor advance. A failure keeps the old cursor and retries with a growing backoff; after twenty consecutive failures the source pauses and reports its health. Due interval passed Fetch from the saved cursor Normalise dedupe on provider ids Stored, cursor advances only on success — never mid-failure Failure: old cursor kept backoff doubles · 20 strikes → paused, health says why
The two rules that make polling safe: the cursor advances only on success (a partial read never silently skips events — re-reads deduplicate for free), and a failing credential backs off and eventually pauses instead of hammering the provider in your name.

Stated plainly

This is the usage report, not a per-request stream: OpenAI exposes aggregates per time bucket, so one event is one (bucket, model) aggregate. Cost comes from a separate endpoint and is joined by day; an admin key without cost entitlement still reports tokens — losing usage because pricing failed would be the wrong trade.

Questions

What key does this need?

An organization admin key — the usage and costs APIs refuse ordinary API keys. It is stored encrypted (AES-256-GCM), used only by the sync worker, and no API route ever returns it.

Why is the last hour missing?

Deliberately. The most recent bucket is still filling on OpenAI's side; reading it now and again in five minutes would count the same tokens twice. Buckets are read once they are ~90 minutes settled.

What if my key is revoked?

The source records auth_failed health with the reason, backs off, and pauses after repeated failures rather than hammering OpenAI. Fixing the key and resuming clears the counter and re-reads from the saved cursor — nothing is skipped.