# Statuses and webhooks

Beta
Smart Collections is currently in Beta. Some contracts on this page are still being confirmed with our engineering team, so treat them as provisional and expect refinements before general availability, including:

- Webhook payloads and event codes
- API reference updates for the Collection Instructions, Payment Authorization, and Charge endpoints
- Field names and documentation improvements (terminology, diagrams)


Contact your Belvo account manager to join the Beta program.

This page is the reference for the object statuses and webhooks used across both phases of Smart Collections. For the step-by-step flow, see Phase 1 and Phase 2.

## Statuses

### Collection Instruction

| Status  | Meaning |
|  --- | --- |
| `PROCESSING` | Created. Belvo is monitoring (or has finished monitoring) its items. An instruction stays `PROCESSING` until you cancel it; check each item's status to see how monitoring ended. |
| `CANCELLED` | You cancelled the instruction. Any items that were still being monitored were cancelled too. |


### Collection Instruction item

Only `CHARGE_SETTLED` sends a webhook. To read the status of any item, get the instruction's details.


```mermaid
stateDiagram-v2
    [*] --> PENDING
    PENDING --> PROCESSING: a balance check starts
    PROCESSING --> PENDING: not enough funds yet
    PROCESSING --> CHARGE_SETTLED: enough funds, webhook sent
    PROCESSING --> POLICY_EXPIRED: no collection window left
    PROCESSING --> CHARGE_REJECTED: the account can't be read
    PENDING --> COMPLETED: you mark it complete
    PENDING --> CANCELLED: you cancel it
    PROCESSING --> CANCELLED: you cancel it
```

| Status  | Meaning |
|  --- | --- |
| `PENDING` | Waiting for the next scheduled balance check. |
| `PROCESSING` | A balance check is in progress. |
| `CHARGE_SETTLED` | The balance covered the item's `amount` and Belvo sent you `item_ready_to_charge`. Monitoring stops. Despite its name, this status does **not** mean a Charge was made: you create the Charge yourself in Phase 2. |
| `POLICY_EXPIRED` | All of the item's collection windows ended without enough balance. **No webhook is sent.** |
| `CHARGE_REJECTED` | Belvo couldn't read the balance of any of the user's accounts (for example, the data consent is no longer valid). **No webhook is sent.** |
| `FAILED` | An internal error stopped monitoring. **No webhook is sent.** |
| `COMPLETED` | You marked the item as complete (you collected it outside Belvo), so Belvo stopped monitoring it. |
| `CANCELLED` | You cancelled the item (or its whole instruction). |


### Payment Authorization and Charge

Phase 2 uses Smart Transfers Payment Authorizations and Charges. For their statuses, see the Smart Transfers statuses reference.

## Webhooks

Smart Collections uses **two webhook channels**. You must configure an endpoint on each.

| Channel  | Phase  | Events  | Versioning |
|  --- | --- | --- | --- |
| Aggregation (`COLLECTIONS`) | Phase 1 | `item_ready_to_charge` | None (aggregation webhooks are unversioned) |
| Payments | Phase 2 | `PAYMENT_AUTHORIZATION`, `CHARGE` | `Payments-BR.V2` |


### Phase 1: `item_ready_to_charge` (Aggregation)

Sent once, when the balance of one of the user's accounts covers an item's `amount`. The item moves to `CHARGE_SETTLED` and Belvo stops monitoring it.


```json item_ready_to_charge webhook
{
  "webhook_id": "e29b41d4a7164a4fae1112b8c9d3f5a2",
  "webhook_type": "COLLECTIONS",
  "webhook_code": "item_ready_to_charge",
  "process_type": null,
  "link_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", // [!code warning]
  "external_id": null,
  "data": {
    "item_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "external_id": "inv-2026-001",
    "amount": "150.50"
  }
}
```

| Field  | Description |
|  --- | --- |
| `webhook_id` | A unique ID for this webhook delivery. Use it to detect and discard duplicate deliveries. |
| `webhook_type` | Always `COLLECTIONS` for this event. |
| `webhook_code` | Always `item_ready_to_charge` for this event. |
| `process_type` | Always `null` for this event. |
| `link_id` | The `id` of the OFDA Link this Collection Instruction monitors. |
| `external_id` | Always `null` for this event. Use `data.external_id` instead. |
| `data.item_id` | The `id` of the Collection Instruction item whose balance condition was met. |
| `data.external_id` | The `external_id` you set on that item, or `null` if you didn't set one. |
| `data.amount` | The item's `amount`: what you should collect in Phase 2, as a string. |


Identifies the item, not the account or the policy
The payload tells you which **item** matched, but not which of the user's accounts had the balance, nor which `collection_policy` window was open. To charge a specific account, see Phase 2.

See Aggregation Webhooks for the general Aggregation webhook envelope.

No webhook when monitoring ends without funds
Items that end in `POLICY_EXPIRED`, `CHARGE_REJECTED`, or `FAILED` don't trigger a webhook. Track your items' last `end_date` and reconcile any that never produced an `item_ready_to_charge`.

### Phase 2: `PAYMENT_AUTHORIZATION` and `CHARGE` (Payments)

These are standard `Payments-BR.V2` webhooks. They only tell you that a resource changed, so you `GET` the resource to read its status:


```json Payments V2 webhook
{
  "schema_version": "2.0.0",
  "resource": "CHARGE",
  "resource_id": "0d3ffb69-f83b-456e-ad8e-208d0998d71d",
  "resource_version": "V2",
  "timestamp": "2026-10-16T15:00:07Z"
}
```

For the payload format and how to fetch full details, see Payments Webhooks (Brazil).

### Webhook reliability

- **Separate settings per channel:** `COLLECTIONS` webhooks are configured separately from Payments webhooks in the Belvo dashboard, each with its own URL and optional Bearer token.
- **Authentication:** Belvo doesn't sign webhooks (no HMAC). Restrict your endpoint with an IP allowlist of Belvo's IPs, and optionally set a Bearer token.
- **Retries:** `item_ready_to_charge` is retried up to three times only when Belvo can't connect to your endpoint, so make sure your endpoint is reachable and responds quickly. For Payments webhook retries, see Payments Webhooks (Brazil).
- **Ordering:** webhooks can arrive out of order or very close together. Because Payments webhooks don't carry the status, doing a `GET` per webhook keeps your view of the status correct.
- **Recovering missed events:** there is no event replay. Run a recurring task that checks authorizations and Charges that aren't yet in a final status, and Collection Instruction items you're still waiting on.