Bill Imports
Related guides: Import bill documents · Bills
Review-first lifecycle
Create → upload → complete upload → review → confirm. The API never silently commits uncertain extraction. Send expected_lifecycle_version and expected_draft_version on mutations to prevent stale writes.
/v1/bill_importsCreate an import and a time-limited direct upload target. Send an Idempotency-Key header.
Request body
| client_user_id*string | Your stable user identifier |
| file_name*string | Original display filename |
| media_type*string | PDF, JPEG, PNG, HEIC, or HEIF |
| declared_bytes*number | Source byte length |
| sha256*string | Lowercase SHA-256 digest |
const billImport = await billerapi.billImports.create({
client_user_id: 'user_123', file_name: 'bill.pdf',
media_type: 'application/pdf', declared_bytes: bytes.length, sha256,
});{
"id": "bimp_...",
"status": "CREATED",
"upload_target": { "url": "https://...", "method": "PUT", "headers": {}, "expires_at": "..." },
"lifecycle_version": 1
}/v1/bill_imports/{id}/complete_uploadTell BillerAPI the direct upload completed and begin secure scanning and extraction.
Request body
| client_user_id*string | Owning user identifier |
| expected_lifecycle_version*number | Version returned by the previous read |
| object_version*string | Upload object version |
| etag*string | Upload ETag |
| sha256*string | Uploaded source digest |
await billerapi.billImports.completeUpload(importId, {
client_user_id: 'user_123', expected_lifecycle_version: 1,
object_version, etag, sha256, bytes: bytes.length,
});/v1/bill_imports/{id}Read status, limits, extraction candidates, evidence, the review draft, duplicate candidates, and any retryable errors.
const billImport = await billerapi.billImports.retrieve(
importId, { client_user_id: 'user_123' },
);/v1/bill_imports/{id}/review_draftSet or clear reviewable values such as payee_name, total_amount, due_date_iso, service period, address, and line items.
await billerapi.billImports.updateReviewDraft(importId, {
contract_version: '1', client_user_id: 'user_123', expected_draft_version: 1,
changes: { due_date_iso: { operation: 'set', value: '2026-09-30' } },
});/v1/bill_imports/{id}/confirmConfirm the reviewed draft. A successful commit returns committed_bill_id; use that ID with the Bills API.
const committed = await billerapi.billImports.confirm(importId, {
contract_version: '1', client_user_id: 'user_123',
expected_lifecycle_version: 5, expected_draft_version: 2, final_changes: {},
});/v1/bill_imports/{id}Cancel an uncommitted import. Cancellation is safe to retry.
await billerapi.billImports.cancel(
importId, { client_user_id: 'user_123', expected_lifecycle_version: 5 },
);