---
url: /docs/payables.md
description: >-
  Register a bill, an invoice, a boleto, or a PIX code, then pay it with the
  standard payout flow.
---

A payable is a bill you register: an invoice, a boleto, or a PIX code. Once it exists, you pay it exactly like any other payout: quote it, then execute the payout.

That is what separates a payable from a bank account payout. A bank account payout has no amount until you quote it, because you decide who gets paid and how much. A payable's amount instead comes from what you registered (line items, taxes, discount), or, for a boleto, from what the rail resolves at quote time.

A payable is its own transaction, prefixed `pb_`, and belongs to a [customer](/docs/overview).

## What you can register

A payable needs exactly one destination:

| Destination | Field(s) | Payable today? |
| --- | --- | --- |
| Boleto | `boleto_barcode`: 47-digit linha digitável or 44-digit barcode not starting with 8 | Yes |
| Utility / tax bill (arrecadação) | `boleto_barcode`: 48-digit linha digitável or 44-digit barcode starting with 8 | Yes |
| PIX code | `pix_qrcode`: EMV copia e cola payload | Yes |
| US bank account (invoice) | `bank_account`: the same object `POST /customers/{customer_id}/bank-accounts` takes, `type` `ach` or `wire` | Yes |

Utility and tax bills go in the same `boleto_barcode` field; the kind of bill is detected from the code itself and confirmed at registration. Unlike a boleto, an arrecadação code carries its amount in the barcode (it never accrues interest between quote and payment) and has no due date or registered payer.

On top of a destination, a payable can carry a full invoice shape: `from`/`to` parties (`legal_name`, address fields, `tax_id`), `line_items` (`name`, `quantity`, `price`), a `note`, `discount`, and `taxes`. Invoices increasingly look like this: a line-itemized bill with a boleto or PIX code attached, not just a bare code.

Code payables (boleto, arrecadação, PIX) must be in `BRL`. Invoice payables paid to a bank account must be in `USD`. EVM networks only, for now.

## Register a payable

Registration is one `POST /instances/{instance_id}/payables` call whatever the destination. The two shapes have their own pages:

* [Boleto and PIX payables](/docs/payable-boleto-pix): send the code, the rail resolves the rest.
* [Invoice payables](/docs/payable-invoice): send the vendor's bank details and line items, optionally prefilled by reading the PDF with AI.

Both can [attach the original document](/docs/payable-invoice#attach-the-document).

## List payables

```bash [cURL]
curl --url 'https://api.blindpay.com/v1/instances/in_000000000000/payables?status=draft&customer_id=re_000000000000' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

Filter by `status` or `customer_id`. Pass `limit`, `starting_after`, or `ending_before` for cursor pagination; omit them and you get the full array back instead of a paginated envelope.

## Retrieve a payable

```bash [cURL]
curl --url https://api.blindpay.com/v1/instances/in_000000000000/payables/pb_000000000000 \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

## Delete a payable

A `draft` payable (no payout executing it yet) can be deleted:

```bash [cURL]
curl --request DELETE \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payables/pb_000000000000 \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

The payable moves to the terminal `canceled` status, a `payable.update` event fires, and the same code can be registered again afterwards. Once any payout exists for the payable the delete is rejected with `payable_not_cancelable`.

There is no update endpoint and no separate quote/pay/reprice/receipt endpoint for payables: paying one is a normal payout.

## Amount semantics

`amount` on a payable is derived: the sum of `line_items[].price × line_items[].quantity`, plus `taxes`, minus `discount`, all in cents. That is what the invoice says is owed.

For a boleto, that derived `amount` is not necessarily what gets charged. Registering the barcode stamps the amount the provider resolves right then as a single line item, so a payable created from a code always carries a real `amount`. The provider re-resolves it at quote time, and the number can move: fines, interest, or a discount that only applies on certain days. The quote's `receiver_amount` is what actually gets paid.

Quote an overdue boleto twice on different days and you can get two different amounts, because interest keeps accruing. Always pay against a fresh quote rather than a cached figure.

PIX and invoice-with-bank-details payables use the declared `amount` as-is; there is no rail-side recalculation for those.

### Minimum

A payable is held to the same minimum as a payout: the bill must be worth at least 10.00 USD on the paying side. Registration converts the amount and rejects anything under it with `LIMITS_AMOUNT_OUT_OF_RANGE`, so a bill that could never be paid never becomes a draft.

The quote enforces the same floor against the rate and fees of the moment, so a bill sitting a few cents above it can still be rejected later if the rate moves.

## Status lifecycle

```
draft ─┬─→ canceled (DELETE)
       └─→ processing ─┬─→ completed
                       └─→ back to draft (attempt failed or was refunded)
```

A payable has four statuses, and they describe the bill, not the payment attempt:

| Status | Meaning |
| --- | --- |
| `draft` | Registered, no payout executing it. Quotable. A failed or refunded attempt returns the payable here. |
| `processing` | A payout is executing it, including while that payout is held for review or being refunded. |
| `completed` | Paid. Terminal, never regresses. |
| `canceled` | A draft was deleted. Terminal; the code can be registered again. |

The attempt's own lifecycle (compliance hold, release, failure reason, refund) lives on the payout, reachable through the payable's `payout_id`. To retry after a failed attempt, just quote the same payable again.

## Dedupe

Registering the same `boleto_barcode` or `pix_qrcode` twice for the same instance is rejected with `duplicate_payable`: each code has exactly one payable. If a payment attempt fails or is refunded, do not register the code again. Quote the same payable again and pay it.

## How to pay one

Paying a payable is the standard payout flow, not a dedicated endpoint: create a quote with `payable_id`, then execute the payout.

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/quotes \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "payable_id": "pb_000000000000",
  "network": "sepolia",
  "token": "USDB"
}'
```

Exactly one of `bank_account_id` or `payable_id` is accepted. With `payable_id`, do not send `request_amount` or `currency_type`: the amount comes from the payable (re-resolved from the rail for a boleto). Save the quote's `id`, then execute the payout the normal way:

```bash [cURL]
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payouts/evm \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "quote_id": "qu_000000000000",
  "sender_wallet_address": "YOUR_WALLET_ADDRESS"
}'
```

**Advanced:**

The quote response carries the same `contract` object a bank account quote does, with the ERC-20 address, ABI, and decimal-adjusted amount to approve, when the funding wallet is external. See [Payable with EVM](/docs/payable-evm) and [Payable with managed wallet](/docs/payable-managed-wallet) for the full walk-throughs.

Quotes expire 5 minutes after creation, same as any other quote. To reprice a payable, whether the quote expired or the amount changed, just create a new quote for the same `payable_id`.

## The payout behind a payable

Executing a payable creates a regular payout. It shows up in the payouts list and retrieve like any other payout, with `payable_id` set instead of a bank account; the payable's `payout_id` points back at it. Both objects describe the same single payment.

## Webhooks

Payables emit their own events, and the payload is the same shape the payable endpoints return:

* `payable.new`: the payable was registered (status `draft`).
* `payable.update`: the bill changed; a payout claimed it (`processing`), the attempt failed or was refunded (back to `draft`, payable again), or a draft was deleted (`canceled`). A draft-return payload carries the attempt's `payout_id` and `last_attempt_status` (`failed` or `refunded`), so it is never mistaken for a never-attempted payable.
* `payable.complete`: the payable was paid (status `completed`).

The payout emits its normal `payout.new`/`payout.update`/`payout.complete` events, carrying `payable_id`. The mid-flight detail (compliance hold, release, failure reason, refund) arrives only there; the payable stays `processing` through all of it. One paid bill produces both streams: correlate them through `payable_id`/`payout_id` and never count a `payout.complete` and its `payable.complete` as two payments.

## Related

* [Boleto and PIX payables](/docs/payable-boleto-pix): register a bill from its code
* [Invoice payables](/docs/payable-invoice): register a bill paid to a US bank account
* [Payouts](/docs/payouts): the flow that actually pays a payable

**Advanced:**

- [Payable with EVM](/docs/payable-evm): pay from an external wallet
- [Payable with managed wallet](/docs/payable-managed-wallet): pay from a BlindPay-custodied wallet
