Skip to main content
This guide explains how to send payouts, or withdrawals, to beneficiaries using the Tonder API. Withdrawals are processed through the same unified Process Transaction endpoint as payments, by setting the operation_type to "withdrawal".
Availability NoticeWithdrawals are currently only available for beneficiaries in Mexico. Support for additional countries will be added in future releases.
Available Transfer MethodsThere are two transfer methods available:
  • SPEI: Bank transfers processed same business day during banking hours.
  • Debit Card: Instant deposits available within 5-15 minutes, 24/7.
Critical: Geolocation Required for MexicoThe metadata.latitude and metadata.longitude fields are mandatory for processing withdrawals in Mexico. Omitting these fields or providing erroneous coordinates will result in a failed transaction. If the merchant cannot obtain the user’s device geolocation, the merchant’s own office location can be used instead, as long as it is within Mexican territory.

Step 1: Choose Your Transfer Method

Select the transfer method that fits your payout needs. Here you can find a quick comparison between the two methods:
AspectSPEIDebit Card
Processing TimeSame business day5-15 minutes
AvailabilityBanking hours only24/7
Account Type18-digit CLABE16-digit card number
Best ForRegular payments, larger amountsUrgent payments, instant cashouts

SPEI Bank Transfer

SPEI (Sistema de Pagos Electrónicos Interbancarios) is Mexico’s standard electronic payment system for bank-to-bank transfers. You should use SPEI when:
  • Making regular business payments, such as commissions or vendor payments.
  • Processing payroll and salary transfers.
  • Sending larger amounts where cost-effectiveness is important.
  • Same-day processing during business hours is acceptable.
Key requirementsPay attention to the following specifics for SPEI withdrawals:
  • The transfer_method value must be "SPEI".
  • The beneficiary.account must be a valid 18-digit CLABE (Clave Bancaria Estandarizada).
  • Processing occurs during banking hours (typically 9 AM - 5 PM MXT, Monday-Friday).

Debit Card Instant Transfer

Debit card withdrawals provide near-instant fund delivery directly to the beneficiary’s debit card. You should use Debit Card withdrawals when:
  • Making urgent or emergency payments that can’t wait for business hours.
  • Paying gig economy workers who need immediate access to funds.
  • Providing instant cashouts or on-demand withdrawals.
  • Processing customer refunds that require immediate availability.
Key requirementsPay attention to the following specifics for debit card withdrawals:
  • The transfer_method value must be "DEBIT_CARD".
  • The beneficiary.account must be a valid 16-digit debit card number.
  • Processing occurs 24/7, including weekends and holidays.
  • Funds are typically available within 5-15 minutes.

Step 2: Make the Withdrawal Request

Create and send your withdrawal request using the Process Transaction endpoint with operation_type set to "withdrawal". The request must have the following fields:
FieldDescription
operation_typeAlways set to "withdrawal" for payout operations
amountThe withdrawal amount in the specified currency
currencyCurrency code (currently only "MXN" is supported)
client_referenceYour internal reference identifier for this withdrawal
transfer_methodEither "SPEI" or "DEBIT_CARD"
beneficiaryComplete beneficiary information object
metadataAdditional required information (must include latitude and longitude)
The beneficiary object contains the recipient’s information for the withdrawal. This object specifies who will receive the funds and how they should be delivered. You can see the properties of the beneficiary object in the table below:
FieldDescription
accountThe destination account number (18-digit CLABE for SPEI transfers, or 16-digit card number for debit card deposits)
nameFull legal name of the beneficiary as it appears on their bank account or card
institutionBank institution code (you can find codes in our Mexican Banking Reference)
emailBeneficiary’s email address for notifications and record-keeping
rfcMexican tax ID (RFC), used for compliance and verification
curpMexican CURP, 18-character alphanumeric personal identification number
RFC and CURP requirementsEither rfc or curp must be provided for every withdrawal request. If neither is available, send "ND" (No Disponible) as the value for one of the two fields.
Here is a confirmed working example for a SPEI transfer:
SPEI Transfer
{
  "operation_type": "withdrawal",
  "amount": 6.00,
  "currency": "MXN",
  "client_reference": "card-payout-002",
  "transfer_method": "SPEI",
  "description": "Instant payout",
  "beneficiary": {
    "account": "846180000400000001",
    "name": "Ana María González",
    "rfc": "GOAN850315AB2",
    "institution": "40012",
    "email": "ana.gonzalez@email.com"
  },
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "orderId": "pruebaTonderPayout-00001"
  }
}

Metadata Requirements

The metadata object is required for all withdrawal requests and must include geolocation information:
FieldTypeRequiredDescription
latitudestringYesGeographic latitude coordinate of the transaction origin
longitudestringYesGeographic longitude coordinate of the transaction origin
You can also include optional fields in the metadata object for tracking purposes: operation_date, customer_email, business_user, customer_id, or order_id (sent as orderId in the confirmed example above). Make a POST request to the Process Transaction endpoint with your withdrawal data:
curl -X POST https://stage.tonder.io/api/v1/process/ \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operation_type": "withdrawal",
    "amount": 6.00,
    "currency": "MXN",
    "client_reference": "card-payout-002",
    "transfer_method": "SPEI",
    "description": "Instant payout",
    "beneficiary": {
      "account": "846180000400000001",
      "name": "Ana María González",
      "rfc": "GOAN850315AB2",
      "institution": "40012",
      "email": "ana.gonzalez@email.com"
    },
    "metadata": {
      "latitude": "22.8870221",
      "longitude": "-109.911775",
      "orderId": "pruebaTonderPayout-00001"
    }
  }'

Step 3: Handle the Response

Upon successful request, the API will return an immediate acknowledgment. Here you find a description of the fields in the response:
FieldDescription
idUnique transaction identifier
operation_typeConfirms this is a withdrawal operation
statusCurrent transaction status (initially PENDING)
amountWithdrawal amount as submitted
currencyCurrency code
merchant_referenceYour internal reference identifier
created_atISO 8601 timestamp when the withdrawal was created
status_codeHTTP status code (201 for successful creation)
The response structure is as follows:
{
  "id": "550e8400-e29b-41d4-a716-446655440001",
  "operation_type": "withdrawal",
  "status": "PENDING",
  "amount": 6.00,
  "currency": "MXN",
  "merchant_reference": "card-payout-002",
  "created_at": "2024-07-26T10:30:00Z",
  "status_code": 201
}
After receiving the response, save the transaction ID from the id field to monitor progress.

Step 4: Withdrawal Lifecycle and Statuses

Withdrawals are asynchronous operations. As your withdrawal progresses, it moves through the following statuses:
StatusTypeDescription
PENDINGInitialThe withdrawal request has been received and is queued
PROCESSINGIntermediateThe transfer is currently being approved and prepared
SENT_TO_PROVIDERIntermediateThe request has been sent to the bank or payment provider
PAID_FULLSuccessThe transfer was completed successfully
REJECTEDTerminalThe transfer was declined (for example, invalid account)
REFUNDEDTerminalFunds from a previously paid withdrawal were reversed by SPEI
PAID_FULL is not always final. A PAID_FULL (Success) withdrawal, and also a declined one, can still transition to REFUNDED if the SPEI system reverses the disbursement afterward. Do not treat PAID_FULL as the end of the lifecycle in your integration logic. See Refunds below.

Internal Status vs Webhook Status

Only two webhook notifications are sent per withdrawal: an initial Pending notification, and one terminal notification.
Internal stageWebhook status you receive
PENDINGPending
PROCESSING, SENT_TO_PROVIDERNo separate webhook, internal only
PAID_FULLSuccess
REJECTED (rejected before reaching the provider)Declined
Failure after being sent to the providerFailed
REFUNDED (can follow either a Success or a Declined withdrawal)See Refunds below

Monitoring Options

You can monitor withdrawal status using one of these methods:
  • Webhooks (Recommended): configure webhooks to receive real-time status updates automatically.
  • Status Polling: check transaction status periodically using the Get Transaction Status endpoint.

Refunds

A withdrawal refund (REFUNDED) is distinct from a payment refund. It means the disbursed funds were returned to the merchant’s sub account, not to the end customer’s bank. A refund occurs when the SPEI system reverses a previously completed or declined disbursement. Tonder detects this automatically and transitions the withdrawal to REFUNDED — no action is required from your integration to trigger it. This can happen after a PAID_FULL (Success) withdrawal, and also after a Declined one.

How It Works

  1. The withdrawal reaches PAID_FULL status. A webhook notification is dispatched to your endpoint after a brief delay.
  2. If SPEI notifies Tonder that the disbursement has been reversed before that delay elapses, Tonder suppresses the pending PAID_FULL webhook and moves the withdrawal directly to REFUNDED.
  3. If the reversal happens after the PAID_FULL webhook has already been sent, you will receive a separate REFUNDED webhook afterward.
  4. REFUNDED is a terminal state — no further transitions occur.
  5. The refunded amount is credited back to the merchant’s sub account. Notify the withdrawal recipient and initiate a new withdrawal request if appropriate.
Design your integration to handle a REFUNDED notification arriving without a prior PAID_FULL notification. Do not assume PAID_FULL will always be received first.

Notification Ordering

ScenarioNotifications you receive
Successful disbursement, no reversalPENDINGPAID_FULL
Fast reversal, before the PAID_FULL webhook is dispatchedPENDINGREFUNDED
Reversal after the PAID_FULL webhook was already sentPENDINGPAID_FULLREFUNDED

Common Refund Reasons

ReasonDescription
Cuenta inexistenteThe destination account does not exist
CLABE incorrectaThe CLABE number is invalid or formatted incorrectly
Cuenta canceladaThe destination account has been closed
Fondos insuficientesInsufficient funds at the receiving institution
Operación no permitidaThe transfer type is not permitted for this account
This list is not exhaustive. Always surface the reason to your operations team for investigation.

Handling a Refund Notification

  1. Acknowledge the notification immediately (HTTP 200) — do not delay the response while processing business logic.
  2. Use the withdrawal id to check for idempotency. If you already processed a REFUNDED event for this withdrawal, skip further processing.
  3. Credit the refunded amount to the withdrawal recipient in your own system.
  4. Notify the recipient that the transfer was reversed, including the reason if available.
  5. If the reversal was due to a correctable error (for example, an incorrect CLABE), allow the recipient to submit a new withdrawal request after verifying their account details.

Webhooks

Withdrawal webhooks for API Direct follow the same format as API Direct payment webhooks, with a few differences:
  • operation_type is "withdrawal"
  • transfer_method_type is used instead of payment_method_type
  • event_type uses the withdrawal_ prefix (for example, withdrawal_Pending, withdrawal_Success)
  • provider is "STP"
  • metadata contains the withdrawal fields defined by the merchant (latitude, longitude, beneficiary_rfc, and so on)
Two webhooks are always generated per withdrawal: first a Pending notification, then a terminal notification (Success, Declined, or Failed).

Successful SPEI Withdrawal

{
  "id": "f50e4a1f-7145-4737-836f-32250eee38c2",
  "operation_type": "withdrawal",
  "amount": "55",
  "currency": "MXN",
  "client_reference": "card-payout-002",
  "status": "Pending",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T06:41:50.338733Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Pending",
  "action": "MODIFY"
}
{
  "id": "f50e4a1f-7145-4737-836f-32250eee38c2",
  "operation_type": "withdrawal",
  "amount": "55",
  "currency": "MXN",
  "client_reference": "card-payout-002",
  "status": "Success",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T06:41:50.338733Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Success",
  "action": "MODIFY"
}

Declined SPEI Withdrawal

A Declined withdrawal means the transfer was rejected by Tonder before being handed off to the provider.
{
  "id": "c7b14546-84bd-4a81-89fb-3dc660f47011",
  "operation_type": "withdrawal",
  "amount": "60",
  "currency": "MXN",
  "client_reference": "card-payout-002",
  "status": "Pending",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T06:47:09.205388Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Pending",
  "action": "MODIFY"
}
{
  "id": "c7b14546-84bd-4a81-89fb-3dc660f47011",
  "operation_type": "withdrawal",
  "amount": "60",
  "currency": "MXN",
  "client_reference": "card-payout-002",
  "status": "Declined",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T06:47:09.205388Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Declined",
  "action": "MODIFY"
}

Failed SPEI Withdrawal

A Failed withdrawal is sent to the provider but STP is unable to process the transfer, which is different from Declined.
The examples below are illustrative and follow the standard API Direct webhook pattern.
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "operation_type": "withdrawal",
  "amount": "75",
  "currency": "MXN",
  "client_reference": "card-payout-003",
  "status": "Pending",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T07:00:00.000000Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Pending",
  "action": "MODIFY"
}
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "operation_type": "withdrawal",
  "amount": "75",
  "currency": "MXN",
  "client_reference": "card-payout-003",
  "status": "Failed",
  "provider": "STP",
  "transfer_method_type": "SPEI",
  "created": "2026-02-27T07:00:00.000000Z",
  "metadata": {
    "latitude": "22.8870221",
    "longitude": "-109.911775",
    "beneficiary_rfc": "QUIG850315H42"
  },
  "event_type": "withdrawal_Failed",
  "action": "MODIFY"
}

Best Practices

  1. Idempotency: handle duplicate notifications gracefully using the withdrawal id.
  2. Acknowledgment: return HTTP 200 quickly, then process asynchronously.
  3. Two notifications per withdrawal: always expect a Pending notification followed by exactly one terminal notification (Success, Declined, or Failed).
  4. Logging: log all notification receipts for debugging and audit purposes.

Testing

Use the following institution codes in the Stage environment:
MethodInstitution code
SPEI97846
DEBIT_CARD97846
For production, use real institution codes from the Mexican Banking Reference.

Next Steps

  • Set up webhooks to receive real-time notifications when withdrawal statuses change.
  • Check out HTTP response codes to understand how to handle different API responses and error scenarios.
  • Explore rate limits to ensure your withdrawal processing doesn’t exceed API usage limits.