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

Do

  • Use ISO 8601 for all dates
  • Consider merchant's time zone
  • Validate that next_payment_date is in the future
  • Verify that end_date is later than next_payment_date
  • Remember weekends auto-adjust to next Monday

Avoid

  • Dates in local format without time zone
  • Dates in the past for next_payment_date
  • Setting today as the charge date (must be future)
  • Scheduling charges on weekends

2. State Management

Do

  • Follow the flow of allowed state transitions
  • Check for pending orders before cancelling
  • Document reasons for status change
  • Subscribe to webhook events for real-time updates
  • Understand single-charge vs recurring retry differences

Avoid

  • Force transitions not allowed
  • Change status without validating consequences
  • Retry recurring debits the same way as single-charge
  • Ignore is_extended_for_retry flag implications

3. CLABE Validation

Do

  • Verify CLABE belongs to participating bank
  • Collect correct RFC from customer
  • Use payment_method_id to shorten activation flow
  • Check verified status before creating direct debit
  • Handle RFC mismatch errors gracefully

Avoid

  • Skip CLABE format validation (18 digits required)
  • Ignore bank code restrictions
  • Create direct debit without verified payment method
  • Allow duplicate CLABE entries

4. Notifications

Do

  • Customize messages with customer information
  • Use consistent templates
  • Respect notification limits
  • Handle activation email resend requests
  • Monitor webhook delivery status

Avoid

  • Send duplicate notifications
  • Use generic texts without personalization
  • Ignore failed webhook deliveries
  • Skip customer notification on status changes

5. Security

Do

  • Validate ownership in all operations
  • Use tokens with short expiration (24h)
  • Implement rate limiting
  • Log unauthorized access attempts
  • Verify authorization scopes per endpoint

Avoid

  • Expose IDs without validation
  • Tokens without expiration
  • Allow cross access between accounts
  • Skip KYC for Level 2 accounts

Troubleshooting

Problem: "Cannot transition from X to Y"

Cause: Attempted invalid state transition Allowed Transitions:

Current StatusCan Transition To
createdcancelled
activecancelled, completed
pendingcancelled, 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:

  1. Verify RFC format:
    • Persona física: 4 letters + 6 digits + 3 alphanumeric (13 chars)
    • Persona moral: 3 letters + 6 digits + 3 alphanumeric (12 chars)
  2. Check RFC on payment method:
GET /api/customers/6944a4946afaf625504595e3/payment-methods/6944a5386afaf625504595ec
{
    "validation": {
        "rfc": "PERJ950714DL2",
        "status": "rejected",
        "rejection_reason": "rfc_mismatch"
    }
}
  1. Ask customer to verify RFC matches their bank account records
  2. 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 debit


Problem: "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/retry


Problem: "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:

  1. Status is active
  2. is_fixed_amount is true
  3. next_payment_date ≤ today
  4. is_extended_for_retry is not true
  5. 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:

CodeDescriptionResult
00Exitoso - CobradoSuccess
01Cuenta inexistenteFailed
02Cuenta bloqueadaFailed
03Cuenta canceladaFailed
04Insuficiencia de fondosFailed
05Cuenta en otra divisaFailed
06Cuenta no pertenece al Banco ReceptorFailed
07Transacción duplicadaFailed
08Por orden del cliente: Orden de no pagarFailed
09Por orden del cliente: Importe mayor al autorizadoFailed
10Por orden del cliente: Cancelación del servicioFailed
11Cliente no tiene autorizado el servicioFailed
12Vencimiento de la Orden de Pago en VentanillaFailed
13Cliente desconoce el cargoFailed
99Error al procesar la ordenFailed

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).