Authentication & API keys
Every BatchRouter API request is authenticated with a secret API key sent as a bearer token. This page shows the key format, the two ways to create a key, how to verify your account, and how to rotate keys safely.
The Authorization header
Section titled “The Authorization header”Send your key in the Authorization header on every request to /v1 endpoints:
Authorization: Bearer br_live_xxxxxxxxxxxxxxxxxxxxxxxxNew production keys are prefixed br_live_. Legacy ob_live_ keys remain valid while active, so you don’t need to migrate existing integrations immediately.
Base URLs
Section titled “Base URLs”Point your requests at the right environment. Keys are scoped per environment — a production key works against production only.
| Environment | Base URL |
|---|---|
| Production | https://api.batchrouter.com |
| Test | https://test.api.batchrouter.com |
All public endpoints live under /v1 — for example https://api.batchrouter.com/v1/auth/account.
Create an API key
Section titled “Create an API key”You can create a key two ways: from the dashboard (or its API) for an existing org, or with a single agent-first call that needs no email. In both cases the key value is shown only once — store it immediately in your secret manager.
From the dashboard
Section titled “From the dashboard”If you have a BatchRouter account, create and name keys in the dashboard, or call the API while authenticated:
curl https://api.batchrouter.com/v1/auth/account/api-keys \ -H "Authorization: Bearer $BATCHROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production-worker", "expires_at": "2027-01-01T00:00:00Z" }'const res = await fetch('https://api.batchrouter.com/v1/auth/account/api-keys', { method: 'POST', headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'production-worker', expires_at: '2027-01-01T00:00:00Z', // optional; omit for a non-expiring key }),});
const { api_key, api_key_id } = await res.json();// api_key is shown once — persist it now.import osimport requests
res = requests.post( "https://api.batchrouter.com/v1/auth/account/api-keys", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"}, json={ "name": "production-worker", "expires_at": "2027-01-01T00:00:00Z", # optional; omit for a non-expiring key },)data = res.json()api_key = data["api_key"] # shown once — persist it nowBoth name and expires_at are optional. Omit expires_at for a non-expiring key. The response returns the secret once:
{ "api_key": "br_live_xxxxxxxxxxxxxxxxxxxxxxxx", "api_key_id": "key_abc123", "name": "production-worker", "expires_at": "2027-01-01T00:00:00Z"}Agent-first: register with no email
Section titled “Agent-first: register with no email”For automated onboarding and AI agents, POST /v1/auth/agent-register creates an org and issues an API key in a single unauthenticated call — no email or verification step. All body fields are optional.
curl https://api.batchrouter.com/v1/auth/agent-register \ -H "Content-Type: application/json" \ -d '{ "org_name": "Acme Batch Jobs", "agent_name": "ingest-pipeline" }'const res = await fetch('https://api.batchrouter.com/v1/auth/agent-register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ org_name: 'Acme Batch Jobs', // optional agent_name: 'ingest-pipeline', // optional — labels the key }),});
const { org_id, api_key } = await res.json();// api_key is shown once — persist it now.import requests
res = requests.post( "https://api.batchrouter.com/v1/auth/agent-register", json={ "org_name": "Acme Batch Jobs", # optional "agent_name": "ingest-pipeline", # optional — labels the key },)data = res.json()org_id = data["org_id"]api_key = data["api_key"] # shown once — persist it nowThe response gives you your new org ID and the key (shown once):
{ "org_id": "org_abc123", "api_key": "br_live_xxxxxxxxxxxxxxxxxxxxxxxx", "api_key_id": "key_def456"}Make an authenticated request
Section titled “Make an authenticated request”Once you have a key, verify it by fetching your account. GET /v1/auth/account returns your org, plan, credit balance, and members — a quick way to confirm the key works.
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}` },});
if (res.status === 401) throw new Error('Invalid or revoked API key');const account = await res.json();console.log(account.credit_balance);import osimport requests
res = requests.get( "https://api.batchrouter.com/v1/auth/account", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)res.raise_for_status() # 401 if the key is invalid or revokedaccount = res.json()print(account["credit_balance"])A successful call returns your org details and current credit balance:
{ "org_id": "org_abc123", "display_name": "Acme Batch Jobs", "plan": "free", "credit_balance": { "currency": "usd", "amount": "42.00" }, "members": []}Check credit_balance before submitting work — if it’s at zero, batch creation returns 402.
Rotate and revoke keys
Section titled “Rotate and revoke keys”Keys never need to be rotated on a fixed schedule, but rotate promptly if a key may have leaked. Create the replacement first so there’s no downtime, then revoke the old one.
-
Create a new key with
POST /v1/auth/account/api-keys(see above) and deploy it to your secrets store. -
Switch traffic to the new key and confirm requests still succeed (
GET /v1/auth/accountreturns200). -
Revoke the old key by its
api_key_id:Terminal window curl -X POST \https://api.batchrouter.com/v1/auth/account/api-keys/key_abc123/revoke \-H "Authorization: Bearer $BATCHROUTER_API_KEY"
Revoked and expired keys immediately return 401 on every request. To set an expiry up front, pass expires_at when you create the key; omit it for a non-expiring key.
Troubleshooting
Section titled “Troubleshooting”| Status | Meaning | Fix |
|---|---|---|
401 | Missing, malformed, invalid, revoked, or expired key | Check the Authorization: Bearer … header and that the key matches the environment’s base URL. |
403 | Authenticated, but not allowed for this action | Use a key whose org has access to the resource. |
402 | Insufficient credits | Add credits via the dashboard; verify with GET /v1/auth/account. |