Write: post a payload
Get an ingest key from the dashboard — see Create a key.202 with an empty body, before the write happens. That is the contract: nothing makes your server wait on our database.
A
202 does not mean every item was accepted. Invalid items are dropped silently and the batch still succeeds — see Ingest for why.Read: the overview
Reads take a Supabase access token, not an ingest key. The dashboard holds one in the browser; grab it from your session to try this by hand.from and to for the last 30 days ending today. See Date ranges.
What the overview returns
Narrow to a tool
400 — the filter is built by a URL, and URLs are edited by hand.
Every metric route takes clients as well, because tool_hours is keyed by client — ?tools=search_orders&clients=cursor is one tool as read by one model. Blanks and duplicates are dropped rather than rejected, since a filter built by a URL is a URL edited by hand, and unknown selects calls that arrived without a client name.
Under a tool filter, sessions, calls_per_session and cost_per_session_usd come back null: a session belongs to the server, not to a tool. A client filter narrows everything, sessions included. See The overview.
Then
Insights
GET /v1/mcps/{id}/insights — what is wrong, with numbers.Errors
The shape every failure comes back in.