Auto top-up
Configure automatic credit top-ups so long-running BatchRouter pipelines never stall on insufficient credits, and review the charge-attempt history.
Auto top-up charges a saved card off-session to refill your credit balance whenever it drops below a threshold you set. Enable it so a long-running or unattended pipeline keeps dispatching instead of failing with 402 insufficient_credits partway through.
This page covers the three endpoints that manage it: read the config with GET /v1/billing/auto-topup, change it with PUT /v1/billing/auto-topup, and review the off-session charge history with GET /v1/billing/auto-topup/attempts.
Auto top-up is the automatic counterpart to buying credits by hand in the dashboard. There is no public billing-checkout endpoint — manual purchases happen in the dashboard, and auto top-up is the only programmatic way to add credits. See Credits and billing for how the balance works.
When to enable it
A batch is rejected with 402 at submit time if your balance can't fund it. For a single ad-hoc batch that's easy to handle by topping up manually. Auto top-up matters when you can't be in the loop:
- Long-running or chained pipelines that submit many batches over hours or days and would otherwise stall mid-run.
- Unattended / scheduled jobs (cron, agents, CI) where no human is watching the balance.
- Bursty workloads where spend is hard to predict ahead of time.
When enabled, the balance is refilled back up to a target you choose as soon as it falls below your threshold, so submits keep succeeding.
Configuration fields
The configuration object (auto_topup) uses these fields. Money values are returned as objects ({ "currency": "usd", "amount": "25.00" }); when you write them via PUT, you send plain USD-dollar numbers.
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether auto top-up is active. |
threshold | money | Balance that triggers a refill. |
target | money | Balance to refill up to. Must exceed threshold. |
payment_method_id | string | The saved card charged off-session. Must belong to your org. |
max_per_day | integer | null | Maximum auto top-ups per day; null means no cap. |
monthly_ceiling | money | null | Maximum total auto top-up spend per month; null means no cap. |
oncredit_exhausted | block | pause | What happens when credits still run out: hard-block new batches, or pause the org gracefully. |
configured | boolean | Read-only. Whether a config row exists yet. |
consecutive_failures | integer | Read-only, system-managed. Resets on a successful charge. |
paused_reason | string | null | Read-only, system-managed. Set when repeated failures auto-pause top-up. |
consecutive_failures and paused_reason are system-managed — you can read them but not set them. Repeated off-session charge failures will auto-pause top-up and populate paused_reason. Always confirm the exact set of writable fields against the API reference.
Read the current config
GET /v1/billing/auto-topup returns the org's auto top-up configuration under an auto_topup key. Reading is authorized with either a customer API key or a signed-in dashboard session.
curl https://api.batchrouter.com/v1/billing/auto-topup \
-H "Authorization: Bearer $BATCHROUTER_API_KEY"A representative response:
{
"auto_topup": {
"org_id": "org_...",
"configured": true,
"enabled": true,
"threshold": { "currency": "usd", "amount": "10.00" },
"target": { "currency": "usd", "amount": "50.00" },
"payment_method_id": "pm_...",
"max_per_day": 3,
"monthly_ceiling": { "currency": "usd", "amount": "500.00" },
"consecutive_failures": 0,
"paused_reason": null,
"oncredit_exhausted": "block"
}
}Update the config
PUT /v1/billing/auto-topup performs a partial merge: only the fields you send are changed; everything else is left as-is. Money fields are sent as plain USD-dollar numbers (e.g. 50 for $50.00).
Mutating the config requires a signed-in, email-based user session — an API key with no associated user is rejected with 403 user_session_required. In practice, configure auto top-up from the dashboard or a session-backed call, not from a bare br_live_… key.
Enabling auto top-up has hard prerequisites. The PUT will reject the change unless all of these hold:
-
Your account email is verified.
-
A
thresholdis set, and atargetgreater than the threshold is set. -
A saved
payment_method_idthat belongs to your org is set. -
The environment supports off-session charging. If it doesn't, you'll get
503 auto_topup_unavailable.
curl -X PUT https://api.batchrouter.com/v1/billing/auto-topup \
-H "Authorization: Bearer $BATCHROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"threshold": 10,
"target": 50,
"payment_method_id": "pm_...",
"max_per_day": 3,
"monthly_ceiling": 500
}'A successful PUT returns the merged config in the same { "auto_topup": { … } } shape as the GET. To turn auto top-up off, send { "enabled": false } — the rest of the config is retained.
Pair auto top-up with spending controls to bound how much it can spend. max_per_day and monthly_ceiling cap the refill activity itself, while spending controls cap your overall usage — together they give you an automatic safety net and a hard ceiling.
Review charge attempts
GET /v1/billing/auto-topup/attempts returns recent off-session charge attempts, newest first, under a data array. Use it to confirm a refill went through or to diagnose a failed charge. Pass an optional limit query parameter (1–200, default 50).
curl "https://api.batchrouter.com/v1/billing/auto-topup/attempts?limit=20" \
-H "Authorization: Bearer $BATCHROUTER_API_KEY"Each attempt records the trigger_balance (what the balance was when the refill fired), the amount charged, the payment_method_id, the Stripe payment intent, a status (pending, succeeded, requires_action, or failed), and a failure_code when the charge didn't go through. A successful attempt also carries a credited_transaction_id linking to the credit that landed on your balance. See the API reference for the full field list.
A failed attempt — or a card that needs authentication (requires_action) — leaves your balance unchanged, and repeated failures will auto-pause top-up (paused_reason is set). Watch this endpoint, or your delivery webhook, so a silently declining card doesn't surface as a surprise 402 on a later submit.