Best Practices & Troubleshooting
Ensure a reliable integration by following our recommended patterns for date handling, state management, and security. This guide outlines the golden rules for managing the Direct Debit lifecycle and provides solutions for common implementation errors.
Best Practices
1. Date Management
2. State Management
3. CLABE Validation
4. Notifications
5. Security
Troubleshooting
Problem: "Cannot transition from X to Y"
Cause: Attempted invalid state transition
Allowed Transitions:
| Current Status | Can Transition To |
|---|---|
created | cancelled |
active | cancelled, completed |
pending | cancelled, active |
cancelled | (none - final state) |
completed | (none - final state) |
| Solution: |
// Check current status
GET /api/direct-debits/6944a5366afaf625504595ea
{
"_id": "6944a5366afaf625504595ea",
"status": "active",
"is_recurring": true
}
// Use transition allowed
// From 'active' you can go to 'cancelled' or 'completed'
PATCH /api/direct-debits/6944a5366afaf625504595ea
{
"status": "cancelled"
}Note: Cannot cancel if pending orders exist (status: created, pending, in_process).
Problem: "Payment method not found for this customer"
Cause: CLABE does not exist or does not belong to the customer/account
Solution:
// Verify that the payment method exists
GET /api/customers/6944a4946afaf625504595e3/payment-methods
[
{
"_id": "6944a5386afaf625504595ec",
"number": "012555555555555555",
"name": "Juan Perez",
"method": "clabe",
"bank": "012",
"bank_name": "BBVA México",
"verified": true,
"account_id": "68a4c3150b28a9584305a2a6",
"customer_id": "6944a4946afaf625504595e3" // Match
}
]
// Verify customer belongs to your account
GET /api/customers/6944a4946afaf625504595e3
{
"_id": "6944a4946afaf625504595e3",
"account_id": "68a4c3150b28a9584305a2a6", // Match
"email": "[email protected]",
"first_name": "Juan",
"last_name": "Perez"
}Problem: "The CLABE belongs to a bank (code XXX) not available for direct debit"
Cause: CLABE bank code not in participating banks list
Solution: Check participating banks table in Customer CLABE Management. Supported codes: 002, 012, 014, 019, 021, 030, 036, 042, 044, 058, 059, 062, 072, 106, 113, 127, 130, 132, 133, 136, 137, 145, 147, 151, 152, 156.
// Extract bank code from first 3 digits of CLABE
// 012555555555555555 -> Bank code 012 (BBVA México) ✓
// 999555555555555555 -> Bank code 999 (Not supported) ✗Problem: "RFC mismatch" (CEP Validation Failed)
Cause: RFC provided does not match bank records
Solution:
- Verify RFC format:
- Persona física: 4 letters + 6 digits + 3 alphanumeric (13 chars)
- Persona moral: 3 letters + 6 digits + 3 alphanumeric (12 chars)
- Check RFC on payment method:
GET /api/customers/6944a4946afaf625504595e3/payment-methods/6944a5386afaf625504595ec
{
"validation": {
"rfc": "PERJ950714DL2",
"status": "rejected",
"rejection_reason": "rfc_mismatch"
}
}- Ask customer to verify RFC matches their bank account records
- Update RFC and re-trigger validation:
PATCH /api/payment-methods/validate
{
"payment_method_id": "6944a5386afaf625504595ec",
"rfc": "CORRECT950714DL2"
}Problem: "Direct debit must be in created status to acknowledge"
Cause: Trying to acknowledge already activated or cancelled direct debit
Solution:
// Check current status
GET /api/direct-debits/6944a5366afaf625504595ea
{
"status": "active" // Already activated!
}
// If status is 'created', proceed with acknowledgment
// If already 'active', no acknowledgment needed
// If 'cancelled', create new direct debitProblem: "Direct debit must be in pending status to retry"
Cause: Attempting to retry a recurring debit or one that isn't pending
Solution:
// Only single-charge non-recurring debits can be retried
GET /api/direct-debits/6944a5366afaf625504595ea
{
"status": "pending", // Must be 'pending'
"is_recurring": false, // Must be false
"is_fixed_amount": true // Must be true (scheduled)
}
// For variable debits with failed charges, use charge retry:
POST /api/direct-debits/6944a5366afaf625504595ea/charges/ORDER_ID/retryProblem: "Order has already been paid"
Cause: Attempting to retry a successful payment
Solution:
// Check order status before retry
GET /api/direct-debits/6944a5366afaf625504595ea/payments
{
"payment_history": [
{
"order_id": "6944a53a6afaf625504595ee",
"status": "paid", // Already paid - no retry needed
"amount": 500.00
}
]
}Problem: "Direct debit has not reached the maximum number of attempts"
Cause: Trying to retry before order has failed
Solution:
// Single-charge retry requires max attempts reached
// Check order attempts in payment history
GET /api/direct-debits/6944a5366afaf625504595ea/payments
{
"payment_history": [
{
"order_id": "6944a53a6afaf625504595ee",
"status": "failed",
"attempts": 1 // Max attempts = 1, can retry
}
]
}Problem: Payment not generated on schedule
Cause: One of the order generation conditions not met
Solution: Verify all conditions:
- Status is
active is_fixed_amountistruenext_payment_date≤ todayis_extended_for_retryis nottrue- No active orders exist (status:
created,pending,in_process)
GET /api/direct-debits/6944a5366afaf625504595ea
{
"status": "active",
"is_fixed_amount": true,
"next_payment_date": "2026-03-20T12:00:00.000Z",
"is_extended_for_retry": false
}Santander Response Codes
When Santander processes the batch file, each record receives a response code:
| Code | Description | Result |
|---|---|---|
| 00 | Exitoso - Cobrado | Success |
| 01 | Cuenta inexistente | Failed |
| 02 | Cuenta bloqueada | Failed |
| 03 | Cuenta cancelada | Failed |
| 04 | Insuficiencia de fondos | Failed |
| 05 | Cuenta en otra divisa | Failed |
| 06 | Cuenta no pertenece al Banco Receptor | Failed |
| 07 | Transacción duplicada | Failed |
| 08 | Por orden del cliente: Orden de no pagar | Failed |
| 09 | Por orden del cliente: Importe mayor al autorizado | Failed |
| 10 | Por orden del cliente: Cancelación del servicio | Failed |
| 11 | Cliente no tiene autorizado el servicio | Failed |
| 12 | Vencimiento de la Orden de Pago en Ventanilla | Failed |
| 13 | Cliente desconoce el cargo | Failed |
| 99 | Error al procesar la orden | Failed |
Only code 00 is treated as successful. All others result in failed orders. Failed orders trigger direct_debit.payment_failed webhook and require merchant action (retry or next cycle).