Both paths require asynchronous mandate approval before you can charge the payment method. Completing checkout is different from receiving approval.
1. Prepare your integration
Use a test secret API key on your server and configure webhooks to receive enrollment and payment results. Checkout Sessions for this payment method require an organization configured for Mexico and currencymxn.
Send Fintoc-Version: 2026-02-01 on API requests. The Node examples use the official fintoc SDK, and the Python examples use the official fintoc package. The Node SDK uses your organization’s default API version, which must be 2026-02-01 or later for these examples. See Authentication for API version selection.
Every payment method belongs to a Customer. For the API path, create a customer first and use its id. For Checkout Sessions, send an existing customer ID or customer_data to create one during session creation. The examples below use customer_data. For later sessions with the same billing customer, send its customer ID instead of creating it again. Repeating a tax ID in customer_data returns a conflict.
For the API path, the customer must have both email and phone. Otherwise, enrollment returns 422 Unprocessable Entity with customer_contact_required. The API doesn’t update customers, so if an existing customer lacks either field, create a new customer with both and use its ID. If the existing customer has a tax ID, omit tax_id on the new customer to avoid the conflict and send the holder’s RFC in mx_direct_debit.account_holder.rfc.
The account holder’s identity is separate from the billing customer’s details. The holder provides a Mexican tax ID (RFC). For a bank account, use its 18-digit standardized Mexican bank account number (CLABE). Debit cards use a 16-digit number.
Prepare live enrollment
Contact Fintoc to enable Mexican direct debit for your organization before you use a live secret key. Fintoc enables live enrollment and live charges for your organization, and can enable them at different times. Until each one is enabled, its live requests return 400 Bad Request with not_supported_mode.
live enrollment accepts only a CLABE from a supported bank. A debit card, or an account at an unsupported bank, returns 422 with invalid_account_for_direct_debit. The examples in this guide use test keys and sandbox fixtures; in live, send your customer’s authorized CLABE and their consent documents.
2. Enroll a payment method by API
Use this path when you collect the holder’s details and consent in your own interface. If your customer will authorize in Fintoc’s checkout, skip to Create a Checkout Session in sandbox. Send onemultipart/form-data request to Create a payment method. Replace cus_000000001 with your customer’s ID and the four file paths with your local files. The account number and RFC in this example are published sandbox fixtures.
Server
201 Created with a payment method whose mandate is pending. Save the payment method id and wait for the approval event before charging it.
The enrollment request accepts these parameters:
Provide the signed mandate as
contract, a photo of the holder with their identity document as selfie, and the front and back of that document as id_front and id_back. Each file must be a PDF, JPEG, or PNG, at least 100 bytes and smaller than 10 MiB (10,485,760 bytes). Fintoc checks the file content instead of relying only on the extension. An invalid document returns 422 and creates neither a mandate nor a payment method.
In live mode, Fintoc rejects the enrollment when the holder’s RFC or the account is blocked for direct debit. The request returns 422 with the account_blocked_for_direct_debit error code and creates neither a mandate nor a payment method. Fintoc doesn’t run this check in test mode.
The official Node and Python SDKs do not expose payment method creation with file uploads. Use the HTTP endpoint for this step. You do not send
consent_source; Fintoc assigns it from the enrollment path.3. Create a Checkout Session in sandbox
Use this path when your customer will complete enrollment in Fintoc’s checkout. Setpayment_method_types explicitly to ['mx_direct_debit'], or include card to offer both. Direct debit is available for setup and subscription sessions in test mode with mxn currency. It is not a payment method for payment flow sessions.
Save the payment method for future charges
Create a session withflow: 'setup'. This enrolls the payment method without creating a subscription or charging the customer.
Set the mandate terms in payment_method_options.mx_direct_debit. If you omit them, max_amount defaults to 1000000 cents ($10,000.00 MXN) and interval defaults to month. Supported intervals are week, month, and year. The example authorizes up to $350.00 MXN per month.
Server
201 Created. payment_method is null until the customer completes enrollment. Use redirect_url to open checkout; the public response’s session_token is null for this flow.
Create a subscription with the payment method
Create a session withflow: 'subscription'. Fintoc derives the mandate limit from the sum of each line item’s unit_amount × quantity, and derives the mandate period from recurring.interval. The example authorizes $350.00 MXN monthly.
All line items must use the same interval, and interval_count must be 1 when direct debit is available, including sessions that also offer cards. Use week, month, or year. Do not send direct debit mandate terms in payment_method_options for a subscription.
Server
201 Created. Both payment_method and subscription are null until enrollment completes. customer_data creates the billing customer; it does not replace the holder details your customer enters during checkout.
4. Redirect your customer to checkout
Returnredirect_url from your backend and redirect the customer’s browser to it. Keep your secret key on the server.
Client
- Enters the holder’s first name, last name, email, and RFC.
- Continues through identity verification, with front and back images of an Instituto Nacional Electoral (INE) voter ID and a selfie. Sandbox uses simulated documents.
- Enters a CLABE or debit card and, for a debit card, selects the bank.
- Confirms the account and mandate terms, then authorizes the direct debit.
- Sees the confirmation and can download the mandate document.
- Correcting an account that fails verification keeps the identity approval.
- A rejected identity does not create a mandate or payment method.
- Enrollment expires one hour after the customer submits the holder details. Advancing through screens does not extend the deadline, and it is independent of the Checkout Session’s public
expires_at. - After enrollment expires, the customer cannot resume direct debit in that session. The customer can return to your site or choose another payment method if the session still allows it.
- Starting identity verification again within the same session is not supported in this release.
5. Handle enrollment and mandate events
Handle webhooks on your backend rather than treating the redirect tosuccess_url as proof that you can charge the payment method. Events can arrive out of order, so use the resource IDs to reconcile your stored state. Follow the webhook verification and delivery guide.
Wait for live mandate verification
A live mandate stays pending while Fintoc verifies it. Creating the payment method doesn’t approve the mandate. Fintoc runs three checks:
- Account: Fintoc sends a verification transfer to the CLABE and compares the RFC and name on the bank’s transfer receipt with the declared holder.
- Identity: Fintoc reviews the identity document and selfie against the declared holder.
- Contract: Fintoc checks that the mandate is signed and matches the holder and the mandate terms in your request.
active and Fintoc sends payment_method.activated. If a check fails, the mandate becomes rejected. If verification doesn’t finish before the approval deadline, the mandate becomes expired with verification_expired. In both cases Fintoc sends payment_method.canceled; read mx_direct_debit.error_reason for the cause, as listed in MX Direct Debit error reasons. live verification has no fixed duration.
Use Get a payment method to reconcile its current state. The mx_direct_debit.status values are pending, active, rejected, expired, and canceled. Only active permits charges.
For subscriptions, follow Manage invoices for billing and collection. Mandate activation does not itself confirm payment of the first invoice or change the subscription’s billing dates.
6. Charge the enrolled payment method
Afterpayment_method.activated, use the payment method ID to create an on-demand charge or create a subscription by API. A subscription created through checkout already has its payment method attached.
Charges must use MXN and stay within the mandate’s remaining authorized limit for the current period. Fintoc rejects a charge at creation with 422 Unprocessable Entity and one of these codes:
Charge creation and the charge result are separate. Handle the payment or invoice result webhooks before marking an order as paid. If the bank rejects a charge for exceeding a limit, the charge fails with
amount_limit_reached.
Wait for the live charge result
A successful create response means Fintoc accepted the charge, not that the bank debited the account. Fintoc submits live charges to the bank once each business day at 14:00 Mexico City time. Charges created at or after 14:00 wait for the next business day’s submission. The bank usually returns the result on the business day after submission, and it can take longer.
Fintoc fails a charge before submission if its mandate is no longer active or Fintoc suspended direct debit for your organization. Some bank failures, such as a closed account or a revoked mandate, also cancel the mandate and trigger payment_method.canceled. Fintoc doesn’t retry a failed direct debit charge automatically, including subscription invoice charges. Create another charge, or follow Manage invoices to collect a failed invoice.
Handle live chargebacks
Direct debit chargebacks have no defense process. Fintoc creates the Dispute as lost, sends only dispute.lost, and doesn’t request supporting documents. The Dispute object has payment_method_type set to mx_direct_debit and documentation_upload_deadline set to null. Use Get a dispute to reconcile the reversal.
A chargeback blocks the holder’s RFC and the account for live direct debit with every merchant. Fintoc cancels the matching pending and active live mandates and sends payment_method.canceled with mx_direct_debit.error_reason set to chargeback to each affected merchant. New enrollments with that RFC or account return account_blocked_for_direct_debit.
Fintoc monitors your organization’s chargeback rate. If the rate exceeds the threshold Fintoc set for your organization, Fintoc suspends direct debit: new live mandates and charges return direct_debit_suspended, and charges not yet submitted to the bank fail with the same reason.
7. Download the mandate document
Call Get a payment method mandate document with your secret key to obtain a temporary download URL. This works for both enrollment paths once the contract is stored, including while the mandate ispending.
Server
download_url expires after five minutes. expires_at is an ISO 8601 datetime in UTC, and filename is the stored file’s name. Request a fresh URL when needed; do not store the URL as a permanent document link. This endpoint is not exposed by the official Node or Python SDKs.
A missing payment method, wrong organization, or wrong API key mode returns 404 with missing_resource. A payment method without a downloadable native direct debit contract returns 422 with invalid_payment_method_state, including legacy Belvo payment methods.
For checkout enrollment, Fintoc sends a confirmation email to the Checkout Session’s resolved customer email when enrollment completes, unless receipt emails are suppressed by your branding configuration. The holder email entered in the widget does not replace that recipient. The confirmation email is not proof that the mandate is active. The widget also offers document download; it does not offer a manual email-send action.
8. Test the integration
Sandbox andlive share the API workflow, but verification and settlement differ:
Use your
test secret key and the fixtures below. Run API enrollment with local sample files, or create a Checkout Session and complete it on desktop and mobile. Verify the returned resources and received webhooks as well as the confirmation screen.
Simulate identity verification in checkout
These RFCs apply to the Checkout Session path. API enrollment accepts the consent documents you supply and does not run the checkout identity simulator.
The last three characters select the scenario. Use a 13-character individual RFC with a valid date and check digit. Retrying identity verification within the same Checkout Session is not part of this release.
Simulate account verification in checkout
Use CLABE012180000000083333 to return account_not_validated before a mandate is created. Correct the account to 012180000000000015 and continue without repeating identity verification. Account numbers with invalid format or checksum, and unsupported banks, are rejected before enrollment.
The 3333 suffix applies to account verification in checkout. It is not a mandate-rejection scenario for API enrollment.
Simulate mandate outcomes in either path
Use the following published sandbox account numbers. For a debit card, select or sendmx_banco_bbva as the issuing bank. Mandates first return pending, then resolve asynchronously. The sandbox resolution delay defaults to five seconds; allow additional time for webhook delivery.
CLABEs ending in
1111 simulate rejection; CLABEs ending in 8888 simulate no bank response and expiry. Debit cards ending in 0335 simulate rejection. Other valid accounts approve, except for checkout account-verification failures. A debit card ending in 1111 approves; it does not use the CLABE rejection rule.
Simulate charges
After the payment method becomesactive, create a charge within the mandate limit. Valid amounts of at least 500 MXN cents ($5.00 MXN) succeed; amounts from 100 to 499 simulate insufficient_funds. Resolution is asynchronous and defaults to five seconds in sandbox. Verify the charge result instead of only the create response.
Also verify that Fintoc rejects a charge exceeding the mandate’s remaining authorized limit with mandate_limit_exceeded, and that charging a pending, rejected, expired, or canceled mandate returns payment_method_inactive.