# Fase 1: Verificación de Saldo (API Directa)

Beta
Smart Collections está actualmente en Beta. Algunos contratos en esta página aún están siendo confirmados con nuestro equipo de ingeniería, por lo que deben considerarse provisionales y se esperan refinamientos antes de la disponibilidad general, incluyendo:

- Cargas útiles de webhook y códigos de eventos
- Actualizaciones de referencia de la API para los endpoints de Collection Instructions, Payment Authorization y Charge
- Nombres de campos y mejoras en la documentación (terminología, diagramas)


Contacta a tu gerente de cuenta de Belvo para unirte al programa Beta.

En la Fase 1 de Smart Collections, delegas el monitoreo de saldo a Belvo. Defines **Instrucciones de Cobro**, estableciendo los montos que deseas cobrar y las condiciones de saldo que deben cumplirse, y Belvo supervisa la cuenta vinculada en segundo plano. Cuando una cuenta tiene suficiente dinero, Belvo te notifica para que puedas cobrarlo en Fase 2.

Producto de Agregación
La verificación de saldo es parte del producto de **agregación** de Belvo: se basa en el consentimiento OFDA y los datos bancarios del Link del usuario.
Por lo tanto, debes completar primero los requisitos previos de Smart Collections, ya que necesitas un Link OFDA (`link_id`) para crear Instrucciones de Cobro y un endpoint de webhook para recibir eventos de saldo.

La Fase 1 cubre tres pasos: creas una Instrucción de Cobro, Belvo monitorea el saldo de la cuenta en relación con ella, y Belvo te envía un webhook una vez que hay suficientes fondos para cobrar.


```mermaid
sequenceDiagram
    participant Client as Your application
    participant Aggregation as Belvo Aggregation API

    Note over Client, Aggregation: 1. Create the Collection Instruction

    Client->>Aggregation: POST /api/collection-instructions/
    Aggregation-->>Client: 201 Created (instruction and item IDs)

    Note over Client, Aggregation: 2. Belvo monitors the balance

    loop Within your collection windows, until the balance is sufficient
        Aggregation->>Aggregation: Check whether the account balance covers the amount
    end

    Note over Client, Aggregation: 3. Belvo signals that funds are available

    Aggregation->>Client: Webhook: item_ready_to_charge
    Note over Client, Aggregation: Carries the item_id, your external_id, and the amount.<br/>Continue in Phase 2 to create the Charge.
```

## 1. Crear una Instrucción de Cobro

Una **Instrucción de Cobro** indica cuánto deseas cobrar a tu usuario (`link_id`) y durante qué período de tiempo. Belvo utiliza esta información para monitorear el saldo de la cuenta del enlace y, una vez que se cumple la condición de saldo, recibirás un evento de webhook indicando que puedes retirar fondos por un monto determinado.

Cada elemento de Instrucción de Cobro en el array `items` se refiere a una colección singular sobre la que deseas actuar. **La mayoría de las integraciones crean una Instrucción de Cobro por deuda**: un solo elemento que describe esa deuda, con una o más políticas de cobro. (Una instrucción puede contener múltiples elementos si deseas agrupar varias deudas en una sola llamada, pero el patrón común es un elemento por deuda).

Para crear una, realiza una solicitud POST Crear una instrucción de cobro:


```json Cuerpo de la Solicitud para Crear una Instrucción de Cobro
{
  "link_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "items": [
    {
      "amount": "150.50",
      "external_id": "inv-2026-001",
      "collection_policies": [
        {
          "start_date": "2026-11-01",
          "end_date": "2026-11-10",
          "amount": "150.50"
        },
        {
          "start_date": "2026-11-21",
          "end_date": "2026-11-30",
          "amount": "150.50"
        }
      ]
    }
  ]
}
```

Qué hace una política de cobro
Una política de cobro define una **ventana de tiempo** durante la cual Belvo verifica la cuenta. Agrega más de una política a un elemento para controlar *cuándo* ocurre el monitoreo. En el ejemplo anterior, Belvo verifica durante los primeros diez días de noviembre, hace una pausa y luego verifica nuevamente en los últimos diez días. **No se realizan verificaciones durante el intervalo** entre ventanas.

Tanto `start_date` como `end_date` son **inclusivos**, por lo que una ventana se extiende hasta el final de su `end_date`.

Belvo te notifica tan pronto como el saldo disponible de **cualquiera** de las cuentas del usuario sea mayor que el `amount` del elemento, y luego deja de monitorear ese elemento. Los saldos entre cuentas no se suman.

Las ventanas se evalúan en UTC
Las ventanas de cobro se ejecutan desde las 00:00 UTC en `start_date` hasta las 23:59:59 UTC en `end_date`, no en la hora local del pagador. En la hora de Brasilia, una ventana se abre a las 21:00 del día anterior a `start_date` y se cierra a las 20:59 en `end_date`.

Dentro de una ventana, Belvo verifica el saldo aproximadamente siete veces al día, en horarios variados. Un saldo que solo sea brevemente suficiente puede no ser detectado.

El saldo disponible incluye sobregiro
Belvo utiliza el saldo disponible de la cuenta según lo informado por el banco, que puede incluir un límite de sobregiro (*cheque especial*). Por lo tanto, un usuario puede activar `item_ready_to_charge` con menos dinero propio que el `amount` del elemento.

| Parámetro | Requerido | Descripción |
|  --- | --- | --- |
| `link_id` | true | El `id` del Enlace OFDA para el usuario cuyo saldo de cuenta deseas monitorear. Debe ser un Enlace activo que pertenezca a tu organización, de lo contrario, Belvo responde con `400 - Bad Request`. |
| `items` | true | Array de elementos, con al menos una entrada. Cada elemento es un monto que deseas cobrar, con una o más políticas de cobro. La mayoría de las Instrucciones de Cobro tienen exactamente **un** elemento, una deuda por instrucción. |
| `items[].amount` | true | El monto que deseas cobrar por este elemento, como una cadena. Belvo te notifica una vez que el saldo disponible de una de las cuentas del usuario sea mayor que este monto. |
| `items[].external_id` | opcional (fuertemente recomendado) | Tu propia referencia para este elemento. Belvo no vincula las Instrucciones de Cobro a la Autorización de Pago o Cargo que creas en la Fase 2, por lo que esta es la forma de vincular un webhook a tus registros. Establécelo a menos que tengas una razón para no hacerlo. Dado que la mayoría de las instrucciones contienen un elemento por deuda, esta es típicamente tu referencia para la deuda en su conjunto. |
| `items[].collection_policies` | true | Array de políticas, con al menos una entrada. Cada política define una ventana de tiempo (`start_date` a `end_date`) durante la cual Belvo verifica la cuenta. Usa varias políticas para controlar cuándo ocurre el monitoreo. |
| `items[].collection_policies[].start_date` | true | La primera fecha en la que Belvo verifica la cuenta, en formato `YYYY-MM-DD`. Inclusivo. |
| `items[].collection_policies[].end_date` | true | La última fecha en la que Belvo verifica la cuenta, en formato `YYYY-MM-DD`. Evaluado en UTC, ver la nota abajo. |
| `items[].collection_policies[].amount` | true | El monto para esta ventana, como una cadena. Establécelo al monto que deseas cobrar por el elemento. Ver la nota abajo. |


Establece el monto de cada política al monto del elemento
Cada política requiere un `amount`, pero hoy en día Belvo compara el saldo con el `amount` del **elemento** en cada ventana, y el `amount` de una política no tiene efecto. Establece el `amount` de cada política al mismo valor que el `amount` del elemento.


```json Respuesta de Creación de una Instrucción de Cobro (201 Created)
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", // [!code highlight]
  "link_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "PROCESSING",
  "created_at": "2026-10-25T14:22:10.123456Z",
  "updated_at": "2026-10-25T14:22:10.123456Z",
  "items": [
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", // [!code highlight]
      "amount": "150.50",
      "external_id": "inv-2026-001",
      "status": "PENDING",
      "created_at": "2026-10-25T14:22:10.234567Z",
      "updated_at": "2026-10-25T14:22:10.234567Z",
      "collection_policies": [
        {
          "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
          "start_date": "2026-11-01",
          "end_date": "2026-11-10",
          "amount": "150.50",
          "created_at": "2026-10-25T14:22:10.345678Z"
        },
        {
          "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
          "start_date": "2026-11-21",
          "end_date": "2026-11-30",
          "amount": "150.50",
          "created_at": "2026-10-25T14:22:10.345678Z"
        }
      ]
    }
  ]
}
```

La instrucción comienza en `PROCESSING` y cada elemento en `PENDING`. Consulta Estados y webhooks para el ciclo de vida completo.

Guarda los IDs de la instrucción y del elemento
Almacena el `id` de la instrucción y el `id` de cada elemento de esta respuesta. Necesitas el `id` de la instrucción para verificar o cancelar la instrucción, y necesitas ambos IDs para cancelar un solo elemento. Ningún endpoint resuelve un `id` de elemento de vuelta a su instrucción padre. Si pierdes un `id` de instrucción, puedes encontrarlo nuevamente listando tus instrucciones.

## 2. Escuchar el webhook `item_ready_to_charge`

Cuando se cumple la condición de saldo, Belvo envía un único webhook y deja de monitorear ese ítem. El ítem se mueve a `CHARGE_SETTLED`, lo que solo significa que el webhook fue enviado: aún no existe un Cargo.


```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",
  "external_id": null,
  "data": {
    "item_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "external_id": "inv-2026-001",
    "amount": "150.50"
  }
}
```

El payload identifica el ítem coincidente (`data.item_id`) y su `external_id`, junto con el `amount` a recolectar. Este es un webhook de **agregación**, por lo que no tiene versionado V1/V2. Para un desglose completo campo por campo, consulta Estados y webhooks.

Usa external_id para conectar las fases
Belvo no vincula una Instrucción de Cobro con la Autorización de Pago o Cargo que creas a continuación, así que utiliza `data.external_id` (o `data.item_id`) para correlacionar este webhook con el Cargo que activas en la Fase 2.

Cuando recibas `item_ready_to_charge`, procede a Fase 2 y carga `data.amount` contra la Autorización de Pago del usuario.

No se envía webhook si el saldo nunca es suficiente
Si ninguna de las ventanas de un ítem encuentra suficiente saldo para su `end_date`, el ítem se mueve a `POLICY_EXPIRED` **silenciosamente, sin que se envíe un webhook**. Lo mismo ocurre si Belvo no puede leer las cuentas del usuario (`CHARGE_REJECTED`). No esperes indefinidamente por `item_ready_to_charge`: rastrea el último `end_date` de tus ítems y concilia aquellos que nunca produjeron un Cargo de tu lado.

## Verifica el estado de tus ítems

Belvo solo envía un webhook cuando un ítem alcanza `CHARGE_SETTLED`. Para saber cómo terminó cualquier otro ítem, o para recuperarte si perdiste un webhook, obtén los detalles de la instrucción y lee el `status` de cada ítem:


```shell Get a Collection Instruction
curl --request GET 'https://api.belvo.com/api/collection-instructions/{instruction_id}/' \
  -u SECRET_ID:SECRET_PASSWORD
```

Belvo responde con `200 - OK` y el mismo objeto que recibiste cuando creaste la instrucción, con el `status` actual de cada ítem. Consulta Obtener los detalles de una instrucción de cobro. El `status` de la instrucción permanece `PROCESSING` hasta que la canceles, incluso después de que cada ítem alcance un estado final, por lo que siempre debes leer los estados de los ítems.

Para encontrar una instrucción cuando no tienes su `id`, realiza una solicitud GET Listar instrucciones de cobro:


```shell List Collection Instructions
curl --request GET 'https://api.belvo.com/api/collection-instructions/?created_after=2026-11-01&created_before=2026-12-01' \
  -u SECRET_ID:SECRET_PASSWORD
```

La respuesta es un array de resúmenes (`id`, `link_id`, `status` y marcas de tiempo) que **no incluye los ítems**. Obtén los detalles de una instrucción para verlos.

| Parámetro de consulta  | Descripción |
|  --- | --- |
| `status` | Devuelve solo instrucciones con este estado (`PROCESSING` o `CANCELLED`). |
| `created_after` | Devuelve solo instrucciones creadas en o después de esta fecha (`YYYY-MM-DD`), desde las 00:00 UTC. |
| `created_before` | Devuelve solo instrucciones creadas antes de esta fecha (`YYYY-MM-DD`). La fecha en sí está excluida. |


El filtro `consent_id` también está disponible, consulta la referencia de la API.

Mantén las solicitudes de lista pequeñas y no esperes un orden
La lista no está paginada y su orden no está garantizado. Siempre envía `created_after` y `created_before`, para que la respuesta solo cubra el período que deseas conciliar. Un valor de filtro que no sea válido, por ejemplo, un `status` desconocido o una fecha que no esté en formato `YYYY-MM-DD`, devuelve un `500 - Internal Server Error` genérico.

Con qué frecuencia verificar
Usa estas solicitudes para conciliar, no como tu señal principal: el webhook `item_ready_to_charge` es cómo te enteras de que un ítem está listo. Belvo verifica saldos aproximadamente siete veces al día, por lo que preguntar más a menudo no revela nada antes. Un buen momento para verificar un ítem es después de su último `end_date`, para encontrar ítems que terminaron como `POLICY_EXPIRED`, `CHARGE_REJECTED` o `FAILED`.

Un `instruction_id` que no existe o no pertenece a tu organización devuelve un `500 - Internal Server Error` genérico. Un `instruction_id` que no es un UUID devuelve `404 - Not Found`.

## Reintentar después de una colección detenida

El monitoreo de un ítem se detiene permanentemente una vez que Belvo envía `item_ready_to_charge`, o una vez que sus ventanas terminan sin fondos suficientes. Una Instrucción de Cobro **no** reanuda el monitoreo por sí sola, incluso después de que un Cargo que crees posteriormente sea rechazado. Para intentar cobrar nuevamente, crea una **nueva** Instrucción de Cobro. Reutilizar el mismo `external_id` en el nuevo ítem está permitido.

## Marcar un ítem como completado

Si recolectas el monto de un ítem de alguna otra manera antes de que Belvo encuentre suficiente saldo, por ejemplo, porque tu usuario te paga directamente, marca el ítem como completado. Belvo deja de monitorearlo, y el estado del ítem se convierte en `COMPLETED`, para que tus registros y los de Belvo coincidan en por qué terminó el monitoreo.

Realiza una solicitud PATCH Marcar un ítem de instrucción de cobro como completado, e identifica el ítem por su `id` o por el `external_id` que le diste:

Por item id

```shell Marcar un ítem como completado
curl --request PATCH 'https://api.belvo.com/api/items/complete/' \
  -u SECRET_ID:SECRET_PASSWORD \
  -H 'Content-Type: application/json' \
  --data '{
    "item_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
  }'
```

Por external_id

```shell Marcar un ítem como completado
curl --request PATCH 'https://api.belvo.com/api/items/complete/' \
  -u SECRET_ID:SECRET_PASSWORD \
  -H 'Content-Type: application/json' \
  --data '{
    "external_id": "inv-2026-001"
  }'
```

| Parámetro  | Requerido | Descripción |
|  --- | --- | --- |
| `item_id` | uno de los dos | El `id` del ítem, de la respuesta de Instrucción de Cobro. |
| `external_id` | uno de los dos | El `external_id` que estableciste en el ítem. Debe coincidir exactamente con un ítem en tu organización. |


Envía exactamente uno de `item_id` o `external_id`. Belvo responde con `200 - OK` y el ítem:


```json Response: 200 - OK
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "amount": "150.50",
  "external_id": "inv-2026-001",
  "status": "COMPLETED", // [!code highlight]
  "created_at": "2026-10-25T14:22:10.234567Z",
  "updated_at": "2026-11-05T09:12:44.104311Z",
  "collection_policies": [
    {
      "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "start_date": "2026-11-01",
      "end_date": "2026-11-10",
      "amount": "150.50",
      "created_at": "2026-10-25T14:22:10.345678Z"
    },
    {
      "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
      "start_date": "2026-11-21",
      "end_date": "2026-11-30",
      "amount": "150.50",
      "created_at": "2026-10-25T14:22:10.345678Z"
    }
  ]
}
```

Solo los ítems PENDING pueden ser completados
Solo puedes marcar un ítem como completado mientras su estado sea `PENDING`. Si una verificación de saldo está en progreso (`PROCESSING`), intenta de nuevo unos momentos después. Los ítems en cualquier otro estado no pueden ser completados.

Por el momento, cada solicitud rechazada (un ítem que no está `PENDING`, un `item_id` desconocido, o un `external_id` compartido por varios de tus ítems) devuelve un genérico `500 - Internal Server Error`. Usa el `id` del ítem cuando puedas, para evitar coincidencias ambiguas.

La diferencia con cancelar es la razón que registras: `COMPLETED` significa que el monto fue recolectado fuera de Belvo, y `CANCELLED` significa que ya no deseas recolectarlo.

## Cancelar una Instrucción de Cobro

Para detener el monitoreo de Belvo porque ya no deseas recolectar, por ejemplo, si la deuda fue renegociada o cancelada, cancela toda la instrucción o un solo ítem con un `PATCH`. (La cancelación es un `PATCH` en lugar de un `DELETE` para que Belvo mantenga un registro de auditoría).

| Acción | Endpoint | Comportamiento |
|  --- | --- | --- |
| Cancelar toda la instrucción | `PATCH /api/collection-instructions/{instruction_id}/` | Cancela cada ítem que aún esté `PENDING` o `PROCESSING`, y establece la instrucción como `CANCELLED`. Devuelve la instrucción. |
| Cancelar un solo ítem | `PATCH /api/collection-instructions/{instruction_id}/items/{item_id}/` | Solo mientras el ítem esté `PENDING` o `PROCESSING`. Devuelve el ítem, ahora `CANCELLED`. |


Ninguna solicitud lleva un cuerpo. Consulta Cancelar una instrucción de cobro y Cancelar un ítem de instrucción de cobro. Belvo responde con `200 - OK`.

Ten en cuenta estos puntos:

- **La cancelación no se puede deshacer.** Para monitorear nuevamente, crea una nueva Instrucción de Cobro.
- **Los estados finales permanecen como están.** Los ítems que ya alcanzaron un estado final, como `CHARGE_SETTLED` o `COMPLETED`, mantienen su estado cuando cancelas su instrucción.
- **Cancelar un ítem no cambia su instrucción.** La instrucción permanece `PROCESSING`, incluso si cancelaste su último ítem activo.
- **Cancelar la misma instrucción dos veces es seguro.** Belvo responde con `200 - OK` nuevamente.


Las solicitudes rechazadas devuelven un genérico 500
Belvo devuelve un genérico `500 - Internal Server Error` cuando la instrucción o el ítem no existen, no pertenecen a tu organización, o no están en un estado que permita la cancelación (para un ítem, `PENDING` o `PROCESSING`). Un ítem que no pertenece a la instrucción en la ruta es rechazado de la misma manera. Un ID que no es un UUID devuelve `404 - Not Found`. Verifica el estado de un ítem con Obtener una Instrucción de Cobro antes de cancelarlo.