Getting Started
Go from zero to retrieving bills in 6 steps with the official billerapi Node SDK. This guide uses the sandbox environment with test data — no real accounts needed.
Create a Developer Account
Sign up at the Client Portal to get access to the dashboard and API keys.
- Go to the Client Portal and click Sign Up
- Verify your email address
- Log in to access your developer dashboard
Get Sandbox Credentials
From your dashboard, navigate to API Keys and copy your sandbox key. It's a self-contained Bearer token, so it's the only credential you need.
Note
bak_test_ prefix (production keys use bak_live_). The SDK reads the prefix and targets the matching environment (https://sandbox.api.billerapi.com for sandbox) automatically — you never set a base URL.Install the SDK & List Billers
Install the SDK, then list available billers — the simplest call to verify your key works.
Install
npm install billerapiList billers
import { BillerApi } from 'billerapi';
// The SDK reads bak_test_ vs bak_live_ from the key and targets the
// matching environment automatically — no base URL required.
const billerapi = new BillerApi(process.env.BILLERAPI_API_KEY);
// List billers — the SDK auto-paginates, so you can iterate every page.
const billers = await billerapi.billers.list();
for await (const biller of billers) {
console.log(biller.id, biller.name);
}
// In sandbox you'll see 6 test billers: Sandbox Utility, Sandbox Power,
// Sandbox Gas, Sandbox Water, Sandbox Electric, Sandbox TelecomHTTP reference (no SDK)
curl https://sandbox.api.billerapi.com/v1/billers \
-H "Authorization: Bearer $BILLERAPI_API_KEY"Tip
Link a Test Account
Linking is a two-part flow: your server creates a link token, then the browser SDK handles the user experience and returns a public token you exchange server-side.
Server: Create a link token
// Server-side: create a link token for one of your users.
// client_id is inferred from your API key.
const { link_token } = await billerapi.links.createToken({
client_user_id: 'user_123',
biller_id: 'sb_electric',
consents: ['bills'],
});
// Send link_token to your frontend.HTTP reference (no SDK)
curl -X POST https://sandbox.api.billerapi.com/link/token/create \
-H "Authorization: Bearer $BILLERAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"client_user_id": "user_123",
"biller_id": "sb_electric",
"consents": ["bills"]
}'Client: Open the Connect flow
import { BillerApiElements } from 'billerapi-js';
const billerapi = new BillerApiElements({
clientId: 'your_client_id',
environment: 'sandbox',
});
const handler = billerapi.connect({
linkToken: linkToken, // from your server
onSuccess: async (publicToken, metadata) => {
console.log('Account linked!', metadata.institution_name);
// Exchange the public token on your server (next step).
const res = await fetch('/api/exchange-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ publicToken }),
});
const { access_token } = await res.json();
},
onExit: (error) => {
if (error) console.error('Error:', error.code);
},
});
handler.open();Sandbox test credentials
4242424242 with any username and password. This always succeeds. See the sandbox reference table below for other test scenarios.Server: Exchange the public token
// Server-side: exchange the public token for a durable link.
const { access_token, link_id, biller_id } = await billerapi.links.exchangeToken({
public_token: publicToken,
});
// Store access_token securely. Use link_id to fetch bills (next step).HTTP reference (no SDK)
curl -X POST https://sandbox.api.billerapi.com/link/exchange-public-token \
-H "Authorization: Bearer $BILLERAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "public_token": "public-sandbox-..." }'Retrieve Bills
Use the link_id from Step 4 to fetch bills for the linked account. Bills are scoped to your API key — you pass the link, not the access token.
Fetch bills
// Bills are scoped to your API key and filtered by the account link.
const bills = await billerapi.bills.list({ account_link_id: linkId });
for await (const bill of bills) {
console.log(bill.id, bill.merchant_name, bill.amount, bill.status);
}
// Sandbox returns a Sandbox Electric bill:
// Amount: $127.50 · Status: PENDING · Due: 15 days from nowHTTP reference (no SDK)
curl "https://sandbox.api.billerapi.com/v1/bills?account_link_id=$LINK_ID" \
-H "Authorization: Bearer $BILLERAPI_API_KEY"Listen for Webhooks
Register a webhook to receive real-time notifications when bills are created or updated.
Register a webhook endpoint
Register endpoints with the SDK (the signing secret is returned once — persist it immediately), or from the Client Portal under Developer → Webhooks.
const endpoint = await billerapi.webhookEndpoints.create({
url: 'https://your-server.com/webhooks/billerapi',
events: ['bill.created', 'bill.updated'],
});
// endpoint.secret (whsec_...) is shown ONCE — store it now.
console.log(endpoint.id, endpoint.secret);Verify incoming events
Verify and parse each event in one call with billerapi.webhooks.constructEvent(), which throws if the HMAC signature or timestamp doesn't check out.
// rawBody must be the raw request body string (not a parsed object).
try {
const event = billerapi.webhooks.constructEvent(
rawBody,
signatureHeader, // the signature header value from the request
process.env.BILLERAPI_WEBHOOK_SECRET,
);
if (event.type === 'bill.created') {
// handle the new bill
}
} catch {
// reject with 400 — signature or timestamp failed
}Note
Develop locally with the CLI
No public URL yet? Use the BillerAPI CLI to stream live sandbox events straight to your local server — each event arrives as an HMAC-signed POST, exactly like production.
# Authenticate the CLI with a sandbox key
billerapi login --env sandbox
# Forward live events to your local server (HMAC-signed)
billerapi listen --forward-to http://localhost:4242/webhooks
# In another terminal, fire a test event into the sandbox
billerapi trigger bill.createdSandbox Reference
Use these magic account numbers in the Connect flow to trigger specific scenarios.
| Account Number | Scenario | Behavior |
|---|---|---|
| 4242424242 | Success | Always succeeds. Returns a $127.50 pending bill. |
| 4000000001 | Auth Failure | Returns INVALID_CREDENTIALS error. |
| 4000000002 | Unavailable | Returns BILLER_UNAVAILABLE error. |
| 4000000003 | MFA Required | Prompts for MFA. Use code 123456. |
| 4000000004 | Locked | Returns ACCOUNT_LOCKED error. |
| 4000000005 | Past Due | Returns overdue bills ($245.00) with late fees. |
| 4000000006 | Auto-Pay | Returns a scheduled $89.99 bill with auto-pay enabled. |
| 4000000007 | Payment Plan | Returns 3 installments of $150.00 each. |
| 4000000008 | Multi-Account | Account discovery returns multiple accounts. |
Test Billers
| Biller ID | Name | Type |
|---|---|---|
| sb_utility | Sandbox Utility | Utility |
| sb_power | Sandbox Power | Utility |
| sb_gas | Sandbox Gas | Utility |
| sb_water | Sandbox Water | Utility |
| sb_electric | Sandbox Electric | Utility |
| sb_telecom | Sandbox Telecom | Telecom |