Invoice lifecycle

Every bill follows the same path.

ingest → extract → risk → policy → approve → pay timing → payment intent → settle → reconcile

How an invoice arrives

ChannelWhere
UploadInbox, PDF or JSON
Partner APIPOST /api/v1/invoices
CSVPOST /api/v1/invoices/bulk or Inbox
ERPOdoo from Connectors, or POST /api/v1/erp/ingest (odoo, sap, dynamics)
EmailMailbox connector or POST /api/ingest/mailbox
SFTPDrop folder polled by the worker
FIRS e-invoicePOST /api/v1/einvoice/firs
Vendor portalInvite link on the vendor record
WhatsAppCloud API webhook, when configured

sync: true on an API ingest runs extraction, risk, and policy in the request. Omit it and the worker runs the pipeline from the invoice-pipeline queue.

Writes should send Idempotency-Key. Reusing a key with the same body returns the original response. Reusing it with a different body returns 409.

Statuses

StatusMeaning
receivedStored, pipeline not finished
extractingExtraction in progress
needs_reviewA hard risk or policy hold needs a person
pending_approvalWaiting on one or two approvers
approvedCleared to pay on the recommended date
payment_queuedA payment intent exists and settlement is in flight
payment_sentThe rail accepted the payment
reconciledA settlement row is tied to the invoice
settledClosed through accounting sync where that path is used
payment_failedThe rail or a pay-time guard rejected the attempt
rejectedAn approver rejected the bill
duplicate_suspectedDuplicate controls stopped automatic approval

Open invoices on Home and Cash are bills that still need a payment decision: received, extracting, needs_review, pending_approval, and approved. A bill leaves that count when a payment intent is created.

Risk

Hard risks block automatic approval and block pay until they are cleared.

CodeTypical cause
new_vendorVendor has not been verified. Approval sets isNew to false.
bank_detail_change / arc_address_changePayment destination changed
duplicate_invoice, duplicate_document_checksum, fuzzy_duplicateSame bill or a near match
contract_requiredPolicy requires a purchase order and none is present. Holds for review; after approval, pay is allowed. Pay-time guards ignore a leftover row when the bill is approved or the policy no longer requires a PO
destination_not_allowlistedArc address is not on the organization allowlist
address_screen_failedOptional address screener denied the destination, or live mode could not reach it
low_confidenceExtraction confidence is under the policy floor

Policy

Rules live on a versioned approval policy, edited under Controls. If no policy is published:

  • Organizations in simulated mode use mid-market defaults (auto-approve up to 50,000 in the policy currency, or 5,000 USDC, confidence floor 0.60, purchase order not required).
  • Switching payment mode to live publishes PayablesAI Strict when nothing is published yet: auto-approve up to 25,000 / 5,000 USDC, confidence floor 0.75, purchase order required, new-vendor and duplicate holds on.

Decisions:

DecisionResult
auto_approveInvoice becomes approved
single_approvalOne approver
dual_controlTwo different approvers
holdStays in review
reject_duplicateDuplicate path

An approver cannot decide twice on the same request. The API picks an eligible admin or approver when approver_email is omitted.

Pay timing

After approval, Custara sets recommendedPayDate.

  • An early-pay discount is taken when cash covers it.
  • If a discount exists but cash is tight, the date moves to the due date.
  • If the organization sets target days payable (0–365), the date is the issue date plus that many days, never later than the due date, and never before today.
  • Otherwise the date is the due date.

Autopay, on by default, pays approved invoices for vendors that are not new, on the recommended date, when no hard risk remains. Amounts above the policy ceiling still need a human approval before the status becomes approved. The system actor that runs autopay does not require MFA.

Pay uses the open residual, not only the header total. A smaller amount is a partial payment. Open vendor credits must be applied or waived before pay. Settlement of a naira (or other fiat) bill uses a live FX quote at pay time — Circle CPN when the account has the NGN corridor, otherwise Coinbase spot. Custara does not hardcode a naira rate. If no feed responds, pay is blocked.