Build
Streaming
Server-sent events, unbuffered end to end. The last chunk before [DONE] tells you exactly what the request cost.
curl -N https://api.minirouter.sh/v1/chat/completions \
-H "Authorization: Bearer $MINIROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "meta/llama-3.3-70b",
"messages": [{"role":"user","content":"ping"}],
"stream": true
}'Set "stream": true and read SSE chunks until data: [DONE]. Chunks arrive as the model generates them.
The cost trailer
The final chunk before [DONE] carries the usage object, including usage.cost, the exact USD charge:
data: {"id":"chatcmpl-...","choices":[{"delta":{},"finish_reason":"stop","index":0}],
"usage":{"prompt_tokens":12480,"completion_tokens":902,
"total_tokens":13382,"cost":0.0412}}
data: [DONE]Non-streaming responses carry the same field and the x-minirouter-cost-usd header. Streaming responses include these headers:
| Header | Meaning |
|---|---|
| x-minirouter-provider | The upstream that actually served it. |
| x-minirouter-ttft-ms | Time to first token, in milliseconds. |
| x-minirouter-balance-usd | Your available balance at the start of the stream, after its hold. Read the final charge in usage.cost in the last usage chunk. |
Aborting a stream
When your client closes the socket we abort the upstream immediately. You are charged for the tokens generated before the abort. A stream the upstream kills before 50 output tokens is written off entirely.
Mid-stream exhaustion
If your balance reaches $0 mid-stream, the stream ends with an OpenAI-shaped error chunk, then [DONE], then a clean close. Never a silent socket close:
data: {"error":{"message":"Insufficient credits: this response stopped because
your balance reached $0. You were charged $0.0031 for the tokens
delivered. Top up at https://minirouter.sh/dashboard/billing",
"type":"invalid_request_error","code":"insufficient_credits"}}
data: [DONE]Details under insufficient_credits. The x-minirouter-balance-usd header is on every response so your tooling can warn first.
Retries and the first byte
Before the first content byte we retry on another upstream automatically. After it, we cannot. See failover.