Import a bill from an unlinked account
Use Bill Imports when the customer has a bill document but has not connected that biller account. BillerAPI creates a normalized Bill after review. If the biller is supported, prompt the customer to connect so future bills arrive automatically.
No account connection is required
- 01
Create an import and receive a short-lived upload target
- 02
PUT the original document directly to the upload target
- 03
Complete the upload and wait for NEEDS_REVIEW or READY_TO_COMMIT
- 04
Review candidates and evidence; patch corrections when needed
- 05
Confirm with the expected draft and lifecycle versions
- 06
Store committed_bill_id and consume bill.created
Create and upload
import { createHash } from 'node:crypto';
import { readFile } from 'node:fs/promises';
const bytes = await readFile('utility-bill.pdf');
const sha256 = createHash('sha256').update(bytes).digest('hex');
const billImport = await billerapi.billImports.create({
client_user_id: 'user_123',
file_name: 'utility-bill.pdf',
media_type: 'application/pdf',
declared_bytes: bytes.length,
sha256,
});
await fetch(billImport.upload_target!.url, {
method: 'PUT', headers: billImport.upload_target!.headers, body: bytes,
});Review is a product boundary, not an error state
Confirm, then choose the honest next action
Branch on the committed Bill's payment route. The durable goal is to connect a supported account for future sync, not merely to unlock payment.
const result = await billerapi.billImports.confirm(importId, review);
const { bill } = result;
switch (bill.payment_route?.type) {
case 'ONBOARDED_LINKED':
return showConnectedBill(bill);
case 'ONBOARDED_CONNECTION_REQUIRED':
return showConnectAccount({
billerId: bill.biller?.biller_id ?? bill.payee?.canonical_biller_id,
billId: bill.id,
});
default:
return showExternalOnlyBill(bill);
}| API state | Primary action | What happens next |
|---|---|---|
| ONBOARDED_LINKED | View bill; schedule payment if eligible | Future bills continue to sync. |
| ONBOARDED_CONNECTION_REQUIRED | Connect account | Future bills and eligible biller messages flow through the connection. |
| EXTERNAL_ONLY | Track bill or mark paid externally | The biller cannot be connected yet; never imply automated payment. |