# Introduction

In this article we provide you with a detailed overview of entity states and their transitions within Belvo's Direct Debit payments product. Each entity reports its current state in the `status` field. In the diagrams, blue states are in progress, green states are usable or successful, red states failed, gray states ended, and purple states have a chargeback. For each entity, the transitions table lists every arrow in the diagram and what triggers it, and the states table describes each state.

## Payment methods

A **payment method** is the bank account (CLABE) or debit card that Belvo debits for payment requests. Its initial state depends on your payment configuration: `pending_validation` when penny validation is enabled, and `active` otherwise.


```mermaid
%%{init: {"flowchart": {"curve": "step", "nodeSpacing": 36, "rankSpacing": 80, "padding": 18}, "themeVariables": {"fontFamily": "arial", "fontSize": "14px", "lineColor": "#94A3B8", "edgeLabelBackground": "#FFFFFF", "textColor": "#475569"}}}%%
flowchart LR
    classDef ddsStart fill:#1F2937,stroke:#1F2937,color:#1F2937
    classDef ddsProgress fill:#EEF4FB,stroke:#2F6DB5,stroke-width:2px,color:#2F6DB5,font-family:monospace,font-weight:700
    classDef ddsUsable fill:#E8F5EC,stroke:#2E7D4F,stroke-width:2px,color:#1E6B3F,font-family:monospace,font-weight:700
    classDef ddsFailed fill:#B42318,stroke:#B42318,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsEnded fill:#6B7280,stroke:#6B7280,color:#FFFFFF,font-family:monospace,font-weight:700

    start(( )):::ddsStart
    start -- "Penny validation on" --> pending_validation(pending_validation):::ddsProgress
    start -- "Penny validation off" --> active(active):::ddsUsable
    pending_validation -- "CEP owner matches" --> active
    active -- "You deactivate" --> inactive(inactive):::ddsEnded
    active -- "Belvo cancels" --> canceled(canceled):::ddsEnded
    pending_validation -- "Belvo cancels" --> canceled
    active -- "Bank invalidates<br/>the account" --> error(error):::ddsFailed
    pending_validation -- "CEP mismatch or<br/>penny not sent" --> error
```

### Payment method transitions

| From  | To  | Trigger |
|  --- | --- | --- |
| (new) | `pending_validation` | You create the payment method and penny validation is enabled in your payment configuration. |
| (new) | `active` | You create the payment method and penny validation is not enabled. |
| `pending_validation` | `active` | The owner information in the CEP matches the customer. |
| `pending_validation` | `error` | The owner information in the CEP does not match the customer, or Belvo cannot send the penny (`failedReason`: `account_validation_failed`). If the penny carries a verification code, Belvo also rejects the consent. See Penny validation with a verification code. |
| `pending_validation` | `canceled` | Belvo cancels the payment method. |
| `active` | `error` | The financial institution returns a debit response that invalidates the account (for example, the account is closed). For the codes that have this effect, see Bank errors. |
| `active` | `inactive` | You make a Deactivate a payment method call. This is only possible when no payment request for the payment method is `processing`. |
| `active` | `canceled` | Belvo cancels the payment method. |


### Payment method states

| State  | Description |
|  --- | --- |
| `pending_validation` | Penny validation is in progress. Belvo sent a penny (one centavo) through SPEI to the account and compares the owner data in the CEP (*Comprobante Electrónico de Pago*) with the customer's `documentType` and `documentNumber`. For more information, see Penny validation. |
| `active` | The payment method is confirmed and you can use it in payment requests. You receive the `payment_method_registration_successful` webhook. |
| `error` | End state. Penny validation was not successful, or the financial institution invalidated the account. The `failedReason` and `failedMessage` fields describe the cause. You cannot use the payment method, and its `initial` payment requests change to `canceled`. You receive the `payment_method_registration_failed` webhook. |
| `inactive` | End state. You deactivated the payment method. You cannot use it in new payment requests. Belvo does not send a webhook for this state. |
| `canceled` | End state. Belvo canceled the payment method. You cannot use it, and its `initial` payment requests change to `failed` (`failedReason`: `CANCELED`). You receive the `payment_method_registration_canceled` webhook. |


### Penny validation with a verification code

When you collect consent with a verification code (for example, with Consent Links), the penny also carries a 6-digit code in the description of the deposit (`Codigo Belvo 123456`). Your customer enters the code to authorize the debit. The two checks update different entities:

- The CEP check updates the **payment method**.
- The code check updates the **consent**.


| CEP check  | Code check  | Payment method  | Consent |
|  --- | --- | --- | --- |
| Matches | Correct code | `active` | `confirmed`, for a consent that only requires the code. A consent that also requires documents stays `awaiting_information` until all files are uploaded, then moves to `submitted` for Belvo's review. |
| Matches | Wrong code 3 times, or the code expires (24 hours after the deposit arrives, for Consent Links) | `active` | `rejected`. The payment method stays `active`, but you cannot charge it without a `confirmed` consent: Belvo rejects new payment requests before creating them, or cancels an existing payment request with `failedReason`: `consent_not_confirmed`. Collect a new consent to charge it. |
| Does not match | Code not entered | `error` | `rejected` |
| Does not match | Correct code, entered before the CEP check finished | `error` | `rejected`, even though it was `confirmed` |


To test these outcomes in Sandbox, see Test consent links in Sandbox.

## Payment requests

A **payment request** is a single debit against an `active` payment method. Processing timelines follow Mexico City time (GMT-6):

- **Created before 15:00:** Belvo debits the funds by 20:00 the same day and updates the payment request to `successful` or `failed` by 12:00 the next business day.
- **Created after 15:00:** Belvo debits the funds by 20:00 the next business day and updates the payment request to `successful` or `failed` by 12:00 the business day after that.


For more information, see How long do payments take to process?.


```mermaid
%%{init: {"flowchart": {"curve": "step", "nodeSpacing": 36, "rankSpacing": 80, "padding": 18}, "themeVariables": {"fontFamily": "arial", "fontSize": "14px", "lineColor": "#94A3B8", "edgeLabelBackground": "#FFFFFF", "textColor": "#475569"}}}%%
flowchart LR
    classDef ddsStart fill:#1F2937,stroke:#1F2937,color:#1F2937
    classDef ddsProgress fill:#EEF4FB,stroke:#2F6DB5,stroke-width:2px,color:#2F6DB5,font-family:monospace,font-weight:700
    classDef ddsPaid fill:#1F7A4C,stroke:#1F7A4C,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsFailed fill:#B42318,stroke:#B42318,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsEnded fill:#6B7280,stroke:#6B7280,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsReversed fill:#7E3FBF,stroke:#7E3FBF,color:#FFFFFF,font-family:monospace,font-weight:700

    start(( )):::ddsStart
    start --> initial(initial):::ddsProgress
    initial -- "Charge files<br/>sent to bank" --> processing(processing):::ddsProgress
    processing -- "Bank confirms<br/>the debit" --> successful(successful):::ddsPaid
    successful -- "Customer disputes<br/>(up to 90 days)" --> chargeback(chargeback):::ddsReversed
    processing -- "Bank reports<br/>an error" --> failed(failed):::ddsFailed
    initial -- "Belvo cancels<br/>the method" --> failed
    initial -- "You cancel, checks fail,<br/>or method changes to error" --> canceled(canceled):::ddsEnded
```

### Payment request transitions

| From  | To  | Trigger |
|  --- | --- | --- |
| (new) | `initial` | You create the payment request. |
| `initial` | `processing` | Belvo generates the charge files and sends them to the financial institution. |
| `initial` | `canceled` | You make a Cancel a payment request call (`failedReason`: `canceled_by_merchant`). |
| `initial` | `canceled` | The payment request fails Belvo's validation checks (for example, its consent is not confirmed), or Belvo cancels it. For the reasons, see Validation errors. |
| `initial` | `canceled` | Its payment method changes to `error`. The payment request takes the payment method's `failedReason`. |
| `initial` | `failed` | Belvo cancels its payment method (`failedReason`: `CANCELED`). |
| `processing` | `successful` | The financial institution confirms the debit. |
| `processing` | `failed` | The financial institution reports an error. For the reasons, see Bank errors. |
| `successful` | `chargeback` | The customer disputes the debit with their financial institution. Under Banco de México CIRCULAR 23/2009, the customer has up to 90 calendar days from the transaction date to dispute it. |


### Payment request states

| State  | Description |
|  --- | --- |
| `initial` | The payment request was created and is waiting to be sent to the financial institution. |
| `processing` | Belvo sent the charge files and is waiting for a response from the financial institution. |
| `successful` | The financial institution confirmed the payment request and the funds were transferred. You receive the `payment_request_successful` webhook. |
| `failed` | End state. No funds were transferred. The `failedReason` and `failedMessage` fields describe the cause. You receive the `payment_request_failed` webhook. For the list of reasons, see Bank errors. |
| `canceled` | End state. The payment request was canceled before it reached `processing`. The `failedReason` and `failedMessage` fields describe the cause. You receive the `payment_request_canceled` webhook. |
| `chargeback` | End state. The financial institution reversed a `successful` payment request. The `chargebackDate` and `bankChargebackDate` fields record when it happened. You receive the `payment_request_chargeback` webhook. For more information, see Chargebacks. |


## Consents

A **consent** is the customer's documented authorization to debit a payment method. A consent must be `confirmed` before you can make payment requests. Depending on the consent, you upload documents that Belvo reviews, your customer enters the verification code from the penny deposit, or both.

### Consents with documents

Belvo reviews submitted documents in 1–2 business days. A consent that also requires a verification code moves to `submitted` only after all files are uploaded and your customer enters the correct code.


```mermaid
%%{init: {"flowchart": {"curve": "step", "nodeSpacing": 36, "rankSpacing": 80, "padding": 18}, "themeVariables": {"fontFamily": "arial", "fontSize": "14px", "lineColor": "#94A3B8", "edgeLabelBackground": "#FFFFFF", "textColor": "#475569"}}}%%
flowchart LR
    classDef ddsStart fill:#1F2937,stroke:#1F2937,color:#1F2937
    classDef ddsProgress fill:#EEF4FB,stroke:#2F6DB5,stroke-width:2px,color:#2F6DB5,font-family:monospace,font-weight:700
    classDef ddsUsable fill:#E8F5EC,stroke:#2E7D4F,stroke-width:2px,color:#1E6B3F,font-family:monospace,font-weight:700
    classDef ddsFailed fill:#B42318,stroke:#B42318,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsReversed fill:#7E3FBF,stroke:#7E3FBF,color:#FFFFFF,font-family:monospace,font-weight:700

    start(( )):::ddsStart
    start --> awaiting_information(awaiting_information):::ddsProgress
    awaiting_information -- "All files<br/>uploaded" --> submitted(submitted):::ddsProgress
    submitted -- "Belvo approves<br/>(1–2 business days)" --> confirmed(confirmed):::ddsUsable
    submitted -- "Belvo rejects, or<br/>penny validation fails" --> rejected(rejected):::ddsFailed
    submitted -- "Files missing<br/>or invalid" --> incomplete_information(incomplete_information):::ddsProgress
    incomplete_information -- "You re-upload<br/>files" --> submitted
    confirmed -- "Customer claims<br/>a chargeback" --> received_chargeback(received_chargeback):::ddsReversed
```

### Consents with a verification code

Your customer enters the 6-digit code from the description of the penny deposit, and has 3 attempts. If penny validation fails, Belvo rejects the consent even if your customer already entered the correct code. For the payment method statuses in each case, see Penny validation with a verification code.


```mermaid
%%{init: {"flowchart": {"curve": "step", "nodeSpacing": 36, "rankSpacing": 80, "padding": 18}, "themeVariables": {"fontFamily": "arial", "fontSize": "14px", "lineColor": "#94A3B8", "edgeLabelBackground": "#FFFFFF", "textColor": "#475569"}}}%%
flowchart LR
    classDef ddsStart fill:#1F2937,stroke:#1F2937,color:#1F2937
    classDef ddsProgress fill:#EEF4FB,stroke:#2F6DB5,stroke-width:2px,color:#2F6DB5,font-family:monospace,font-weight:700
    classDef ddsUsable fill:#E8F5EC,stroke:#2E7D4F,stroke-width:2px,color:#1E6B3F,font-family:monospace,font-weight:700
    classDef ddsFailed fill:#B42318,stroke:#B42318,color:#FFFFFF,font-family:monospace,font-weight:700
    classDef ddsReversed fill:#7E3FBF,stroke:#7E3FBF,color:#FFFFFF,font-family:monospace,font-weight:700

    start(( )):::ddsStart
    start --> awaiting_information(awaiting_information):::ddsProgress
    awaiting_information -- "Correct code" --> confirmed(confirmed):::ddsUsable
    awaiting_information -- "Wrong code 3 times<br/>or code expired" --> rejected(rejected):::ddsFailed
    awaiting_information -- "Penny validation<br/>fails" --> rejected
    confirmed -- "Penny validation<br/>fails" --> rejected
```

### Consent transitions

| From  | To  | Trigger |
|  --- | --- | --- |
| (new) | `awaiting_information` | You create the consent. |
| `awaiting_information` | `submitted` | You upload all required files. If the consent also requires a verification code, your customer must enter the correct code too. |
| `awaiting_information` | `confirmed` | Your customer enters the correct verification code, for consents that only require the code. |
| `awaiting_information` | `rejected` | Your customer enters a wrong verification code 3 times, the code expires, or penny validation fails. See Penny validation with a verification code. |
| `submitted` | `confirmed` | Belvo approves the documents. |
| `submitted` | `incomplete_information` | One or more files are missing or invalid. |
| `submitted` | `rejected` | Belvo does not approve the documents, or penny validation fails for a consent that also requires a verification code. |
| `incomplete_information` | `submitted` | You upload the missing or corrected files. |
| `confirmed` | `received_chargeback` | The customer claims a chargeback on a payment request. |
| `confirmed` | `rejected` | Penny validation fails after your customer entered the correct verification code. |


### Consent states

| State  | Description |
|  --- | --- |
| `awaiting_information` | The consent was created. Depending on the consent, you must upload the required files (`id_front`, `id_back`, `selfie`, and `contract`, or `passport`, `selfie`, and `contract` for a Mexican passport), your customer must enter the verification code, or both. |
| `submitted` | All required files are uploaded and Belvo is reviewing them. You receive the `consent_submitted` webhook. |
| `incomplete_information` | One or more files are missing or invalid. You receive the `consent_incomplete_information` webhook. |
| `confirmed` | Belvo accepted the documents, or your customer entered the correct verification code for a consent that only requires the code. The consent is active and you can make payment requests. You receive the `consent_confirmed` webhook. |
| `rejected` | End state. The consent was not granted: Belvo rejected the documents, the verification code was not confirmed, or penny validation failed. You receive the `consent_rejected` webhook. |
| `received_chargeback` | End state. The customer received a chargeback after the consent was `confirmed`. No webhook is sent for this state. |