Control API budgets and retry safely
Understand Jevrouter project balances, key budgets, per-request cost ceilings, idempotency conflicts and how to recover from unknown API outcomes.
By Jevrouter · Updated
Use three distinct spending controls
A project balance is the money available to pay for requests. A key's monthly budget limits that key's use of the project balance. A request's jev.max_cost_usd caps the accepted generation quote. These controls solve different problems and should be configured together.
Monthly budgets use UTC calendar months and account for consumed plus reserved amounts. Concurrent requests can use available balance before earlier generations finish, so a budget check must include outstanding reservations.
- Scope each key to the model IDs its application actually needs.
- Set a hard output-token limit for chat calls.
- Set a per-request ceiling for jobs where an unexpectedly expensive request should fail.
- Separate unrelated workloads into different projects when they need independent balances and access.
A reservation is a maximum accepted quote
For text chat, the gateway uses a conservative input bound and maximum output to reserve funds. The final charge follows the provider usage receipt when available, or the documented token-pricing fallback for chat. Images require a valid provider cost receipt.
If you lower max_cost_usd below the reservation, the call is rejected before generation. Do not increase the ceiling blindly after a 402 response: first check model choice, input length, output cap and any image billing variants.
curl https://api.jevrouter.io/v1/chat/completions \
-H "Authorization: Bearer $JEVROUTER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_KEY" \
-d '{"model":"google/gemini-2.5-flash-lite","messages":[{"role":"user","content":"Reply with OK"}],"max_tokens":64,"jev":{"max_cost_usd":"0.01"}}'Record the request before deciding to retry
Use one idempotency key per intended generation. A repeated key receives HTTP 409 with the accepted request's status; it does not run the generation again or reproduce the answer. The key is retained for at least 24 hours and is scoped to the project and endpoint.
Preserve X-Jevrouter-Request-Id when you receive it. Request status is available using the original API key. If the key has expired or been revoked, inspect the request in the signed-in console instead.
curl "https://api.jevrouter.io/v1/requests/YOUR_REQUEST_ID" \
-H "Authorization: Bearer $JEVROUTER_API_KEY"Distinguish rejection, failure and unknown outcome
A validation rejection means the request needs correction. A completed failure can have a released reservation. An interrupted transport can leave an unknown upstream outcome; a new idempotency key would create a second intended generation, so inspect the first request before resubmitting.
After streamed content has started, retain the partial result and show the user what happened. Automatic cross-model retries can otherwise concatenate unrelated answers or duplicate billed work.
- 401/403: fix authentication or access.
- 400/402: fix request constraints or spending limits.
- 429: honor Retry-After and verify whether execution was accepted.
- 5xx or connection loss: inspect the request record and delivery state before scheduling a new call.
Models mentioned in this guide
Try it in your project.
Choose a model, create a scoped API key and inspect the result in Requests.
Open console ↗