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.
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.
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. 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 in this example is a published sandbox fixture.
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.
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
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.
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, be between 100 and 99999900 cents ($1.00 to $999,999.00 MXN), and stay within the remaining authorized limit for the mandate period. Creating a charge that exceeds the available limit returns limit_exceeded. A charge that fails the limit check during settlement reports amount_limit_reached. Charge creation and charge settlement are separate; handle the charge or invoice result webhooks before marking an order as paid.
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
Use yourtest 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 structurally valid individual RFC with 13 characters. 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 a charge exceeding the mandate’s remaining authorized limit is rejected with limit_exceeded, and that a pending, rejected, expired, or canceled mandate cannot be charged.