Authentication
BillerAPI uses two authentication mechanisms depending on the type of operation.
Authentication Methods
Choose the right method for your use case
API Key (Bearer)
Server-to-server API calls using your bak_test_/bak_live_ API key.
Authorization: Bearer bak_test_…Access Tokens (Bearer)
Per-account tokens from the link token exchange, used for bill retrieval.
Authorization: Bearer <token>API Key
Use your API key for all server-to-server API calls: biller search, link token creation, webhook registration, and more. Send it as a Bearer token on every request — the key is self-contained, so no other header is needed.
Getting Your Key
- Sign up at the Client Portal to create a developer account
- Navigate to Dashboard → API Keys
- Copy your sandbox key, or generate a production key once you go live
Key Formats
| Environment | Key Prefix | Mode | Base URL |
|---|---|---|---|
| Sandbox | bak_test_* | test | https://sandbox.api.billerapi.com |
| Production | bak_live_* | live | https://api.billerapi.com |
The key prefix tells you which environment you're in at a glance. Client-secret response objects also carry a mode field (test or live) so sandbox vs production is visible on the wire.
Example: List billers with your API key
const response = await fetch('https://sandbox.api.billerapi.com/v1/billers', {
headers: {
'Authorization': `Bearer ${process.env.BILLERAPI_API_KEY}`,
},
});
const data = await response.json();Keep your key safe
One credential per environment
bak_test_ key for sandbox and a bak_live_ key for production. Do not combine keys with a separate client id or secret header.Access Tokens (Bearer)
Access tokens are scoped to a single linked account. You obtain them by exchanging the public token returned by Elements after a user completes the linking flow.
How to Get an Access Token
Create a link token
POST /v1/link-tokens with your API key
User completes Connect flow
Elements opens an iframe where the user links their biller account
Exchange the public token
POST /v1/link-tokens/exchange returns an access_token
Use the access token
Pass as Authorization: Bearer <access_token> for bill retrieval endpoints
Example: Fetch bills with an access token
const response = await fetch(
'https://sandbox.api.billerapi.com/v1/bills?account_link_id=link_123',
{
headers: {
'Authorization': `Bearer ${accessToken}`,
},
}
);
const bills = await response.json();Environments
Use the sandbox environment for development and testing. Switch to production when you're ready to go live.
| Environment | Base URL | Description |
|---|---|---|
| Sandbox | https://sandbox.api.billerapi.com | Test billers, deterministic data, no real accounts |
| Production | https://api.billerapi.com | Live billers, real account data |
Note
Error Handling
All errors return a consistent JSON response format.
{
"error_code": "UNAUTHORIZED",
"error_type": "auth",
"error_message": "Invalid client credentials.",
"docs_url": "https://docs.billerapi.com/errors/UNAUTHORIZED",
"request_id": "d94f5e2a-8c3b-4f1e-9a7d-6b2c1e0f8a34"
}Common Error Codes
| Status | Meaning | Action |
|---|---|---|
| 401 | Invalid or missing credentials | Check client ID/secret or refresh token |
| 403 | Insufficient permissions | Verify your account has the required scopes |
| 429 | Rate limit exceeded | Back off and retry after the Retry-After period |
| 500 | Internal server error | Retry with exponential backoff; contact support if persistent |
Rate Limits
BillerAPI enforces per-client rate limits. The exact per-endpoint thresholds are subject to change — do not hard-code specific numbers. When you exceed a limit the API returns 429 Too Many Requests with a Retry-After header (and a numeric retry_after field in the error body). Always honor it. See Rate Limits for the backoff strategy.
Security Best Practices
- ✓Store credentials in environment variables, never in source code
- ✓Rotate client secrets periodically via the dashboard
- ✓Use separate credentials for sandbox and production
- ✓Verify webhook signatures before processing events
- ✗Never expose client secrets in frontend code or public repositories
- ✗Never log full credentials — redact secrets in logs