Credits & billing
BatchRouter runs on prepaid credits. You buy credits up front, every batch reserves credits when it’s created, and the reservation is settled from the batch’s actual provider usage plus the BatchRouter fee. There’s no invoicing and no surprise overage bill — if your balance can’t cover a batch, the create call is rejected before any provider work starts.
This page covers how to check your balance, how to add credits, how reservation and settlement work,
and the endpoints for usage receipts, per-batch billing receipts, and the fee schedule. All requests
use your base URL plus /v1 and a Bearer br_live_… API key.
Check your credit balance
Section titled “Check your credit balance”Your current balance is returned by GET /v1/auth/account as the credit_balance field, a money
object with a currency ("usd") and a decimal-string amount:
{ "org_id": "org_…", "plan": "…", "credit_balance": { "currency": "usd", "amount": "42.50" }}curl https://api.batchrouter.com/v1/auth/account \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/auth/account", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const account = await res.json();console.log(account.credit_balance); // { currency: "usd", amount: "42.50" }import os, requests
res = requests.get( "https://api.batchrouter.com/v1/auth/account", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)print(res.json()["credit_balance"]) # {'currency': 'usd', 'amount': '42.50'}Buy credits
Section titled “Buy credits”Credits are purchased in the dashboard at batchrouter.com/app/billing. There is no public billing-checkout endpoint — the API never charges a card directly, so funding always happens through the dashboard (or via auto top-up, which BatchRouter triggers on your behalf when your balance runs low).
After a purchase clears, the new balance is reflected in GET /v1/auth/account.
How credits are reserved and settled
Section titled “How credits are reserved and settled”Pricing is quote-driven, and money only moves at two points:
-
Quote (free).
POST /v1/quotes/modelreturns a cost estimate with the selected provider lanes and aquote_id. Creating a quote is free — no credits are touched. See Quotes & pricing for the request shape. -
Create — credits reserved. When you
POST /v1/batcheswith thatquote_id, BatchRouter checks your balance against the quoted total and reserves that amount. If the balance is too low, the create call returns402and nothing is dispatched. -
Run. The batch executes across its provider lanes.
-
Complete — credits settled. When the batch reaches a terminal state, the reservation is settled from actual token usage plus the BatchRouter fee. If the batch used less than quoted, the unused portion of the reservation is released back to your balance.
So the quote is a ceiling: you’re charged for what actually ran, never more than the reservation, and any difference is returned. Cancelled or failed work that never reached a provider doesn’t consume credits — but work already dispatched to a provider isn’t refunded.
Usage receipts
Section titled “Usage receipts”GET /v1/usage returns your quote-lane billing receipts — one per batch — with the customer-safe
provider subtotal, BatchRouter fee, and total. The raw provider cost breakdown is omitted. Results are
paginated.
| Query param | Description |
|---|---|
batch_id | Filter to a single batch. |
limit | Page size, 1–100 (default 50). |
cursor | Pagination cursor from a previous response. |
The response is { "data": [ … ], "next_cursor": "…" }; follow next_cursor until it’s null. Each
item includes the batch id, the product (model or workflow), the quoted vs. final settled price, and
the per-lane breakdown — see the API reference for every field.
curl "https://api.batchrouter.com/v1/usage?limit=50" \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/usage?limit=50", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const { data, next_cursor } = await res.json();for (const receipt of data) console.log(receipt.batch_id, receipt.pricing.final_settled_price);import os, requests
res = requests.get( "https://api.batchrouter.com/v1/usage", params={"limit": 50}, headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)body = res.json()for receipt in body["data"]: print(receipt["batch_id"], receipt["pricing"]["final_settled_price"])Per-batch billing receipt
Section titled “Per-batch billing receipt”For a single completed batch, GET /v1/batches/{batchId}/billing-receipt returns the finalized
settlement: the provider subtotal, the BatchRouter fee, the final settled price, and the credit
movement for that batch.
Key money fields (each a { currency, amount } object):
| Field | Meaning |
|---|---|
provider_subtotal | What the provider lanes cost. |
batchrouter_fee | The BatchRouter fee on top. |
final_settled_price | Total charged for the batch. |
credit_reserved | Credits held at create time. |
credit_charged | Credits actually consumed at settlement. |
credit_released | Reservation returned because actual usage was lower. |
The receipt also includes the provider_lanes that ran and any rejected_lanes, each carrying its
quote-time routing/rejection receipt. See the API reference for
the complete schema.
curl https://api.batchrouter.com/v1/batches/bat_123/billing-receipt \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch( "https://api.batchrouter.com/v1/batches/bat_123/billing-receipt", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` } },);const receipt = await res.json();console.log(receipt.final_settled_price, receipt.credit_released);import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches/bat_123/billing-receipt", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)receipt = res.json()print(receipt["final_settled_price"], receipt["credit_released"])Fee schedule
Section titled “Fee schedule”GET /v1/pricing/fees returns the current BatchRouter fee policy, so you can show or sanity-check fees
before quoting. Fields:
| Field | Meaning |
|---|---|
default_margin_bps | Standard batch fee in basis points (e.g. 500 = 5%). |
workflow_margin_bps | Workflow-product fee in basis points. |
margin_floor_bps | Minimum margin floor. |
control_plane_fee_per_lane_usd | Minimum per-lane control-plane fee (decimal string). |
source | active_policy or defaults. |
updated_at | When the active policy last changed (or null). |
This endpoint is unauthenticated-friendly, but sending your key is harmless. The actual fee on any given batch always comes from its quote — the schedule is the policy, the quote is the price.
curl https://api.batchrouter.com/v1/pricing/fees \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/pricing/fees", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const { fee_schedule } = await res.json();console.log(fee_schedule.default_margin_bps); // e.g. 500 → 5%import os, requests
res = requests.get( "https://api.batchrouter.com/v1/pricing/fees", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)fee_schedule = res.json()["fee_schedule"]print(fee_schedule["default_margin_bps"]) # e.g. 500 -> 5%