What is Sandbox?
El sandbox es un modo de operación de tu cuenta — no un ambiente separado.
- Usa la misma API, misma base URL y los mismos endpoints que producción
- Está conectado a un proveedor bancario simulado (no toca Banxico ni la red SPEI real)
- Las cuentas sandbox son separadas y tienen sus propias credenciales
- Tu código no cambia entre sandbox y producción — solo cambian las credenciales
Sandbox vs Production
| Aspecto | Sandbox | Producción |
|---|
| Base URL | https://api.ntxpay.com (misma) | https://api.ntxpay.com |
| Cuenta | Dedicada de sandbox | Dedicada de producción |
| Credenciales | Certificado + clientId/clientSecret propios | Certificado + credenciales propios |
| Saldo | Simulado | Fondos reales |
| Transacciones | Simuladas/persistidas localmente | Liquidan en SPEI/Banxico real |
| Webhooks | Simulados (~1s después de la request) | Reales, dependientes del provider |
X-Sandbox-Scenario | Soportado | 400 Bad Request |
| Documentación | La misma para ambos | — |
Getting Started with Sandbox
Solicita una cuenta de sandbox
Contacta a tu account manager o escribe a contact@ntxpay.com.
Recibe tus credenciales
Certificado X.509 + clientId/clientSecret exclusivos del sandbox.
Registra la URL del webhook
POST /api/webhooks-config con la URL HTTPS que recibirá los eventos simulados.
Confirma el modo sandbox en el panel
En el dashboard, ve a Settings y verifica que el provider sea sandbox.
Autentica y simula escenarios
Autentica vía POST /api/auth/token y usa el header X-Sandbox-Scenario para simular resultados.
Overview
- El header
X-Sandbox-Scenario controla el resultado del webhook asíncrono.
- Sin el header, el sandbox devuelve webhooks de éxito por default.
- Para escenarios de error, envía el header explícitamente en la request.
- La feature funciona solo en sandbox — en producción, la request retorna
400.
How It Works
El header no altera la respuesta HTTP. La API siempre responde 201 Created con status: "PENDING". El scenario afecta exclusivamente el webhook asíncrono disparado ~1 segundo después.
| Request | HTTP Response | Webhook (~1s después) |
|---|
Sin X-Sandbox-Scenario | 201 PENDING | CONFIRMED |
X-Sandbox-Scenario: success | 201 PENDING | CONFIRMED |
X-Sandbox-Scenario: error:insufficient-funds | 201 PENDING | FAILED con errorCode |
X-Sandbox-Scenario: delayed:5s | 201 PENDING | CONFIRMED con +5s de delay |
How to Use
curl -X POST https://api.ntxpay.com/api/spei/cash-out \
-H "Authorization: Bearer $TOKEN" \
-H "X-Sandbox-Scenario: error:insufficient-funds" \
-H "Content-Type: application/json" \
-d '{
"amountCentavos": 15000,
"destinationClabe": "012180001234567890",
"beneficiaryName": "Maria Lopez",
"externalId": "test-error-001"
}'
Available Scenarios
Error Scenarios
| Header Value | Descripción | Webhook Status |
|---|
error:insufficient-funds | Cuenta sin saldo suficiente | FAILED |
error:invalid-clabe | CLABE de destino malformada o inexistente | FAILED |
error:account-not-found | Cuenta destino no localizada en la red SPEI | FAILED |
error:account-blocked | Cuenta destino bloqueada o cerrada | FAILED |
error:duplicate-external-id | externalId ya usado en otra transacción | FAILED |
error:bank-rejected | Banco destino rechazó la transferencia (genérico) | FAILED |
error:oxxo-expired | Cupón OXXO expiró sin pago | EXPIRED |
Success Scenario
| Header Value | Descripción | Webhook Status |
|---|
success | Fuerza éxito (mismo comportamiento del default) | CONFIRMED |
| (sin header) | Comportamiento default del sandbox | CONFIRMED |
Delay Scenarios
| Header Value | Descripción | Webhook Status |
|---|
delayed:5s | Éxito tras 5 segundos extra | CONFIRMED |
delayed:30s | Éxito tras 30 segundos extra | CONFIRMED |
delayed:60s | Éxito tras 60 segundos extra | CONFIRMED |
El delay máximo permitido es de 120 segundos — valores arriba se truncan automáticamente.
Received Webhook Examples
Success Webhook (default)
{
"event": "cash_out",
"deliveryId": "8e2c5b6f-3a12-4b9c-9a18-77a2b3c4d5e6",
"createdAt": "2026-03-26T10:00:00.000Z",
"transaction": {
"id": 12345,
"externalId": "test-success-001",
"paymentMethod": "SPEI",
"direction": "out",
"type": "cash_out",
"status": "CONFIRMED",
"provider": "sandbox",
"amountCentavos": 15000,
"clabe": "012180001234567890",
"referenceNumerical": "9876543",
"createdAt": "2026-03-26T09:59:59.000Z",
"confirmedAt": "2026-03-26T10:00:00.000Z",
"counterpart": {
"name": "Maria Lopez",
"taxId": null,
"bank": {}
}
},
"errorCode": null,
"errorMessage": null,
"metadata": {}
}
Error Webhook (error:insufficient-funds)
{
"event": "cash_out",
"deliveryId": "1a3f9e8d-2c47-4b9c-aa18-77a2b3c4d5e6",
"createdAt": "2026-03-26T10:01:00.000Z",
"transaction": {
"id": 12346,
"externalId": "test-error-001",
"paymentMethod": "SPEI",
"direction": "out",
"type": "cash_out",
"status": "FAILED",
"provider": "sandbox",
"amountCentavos": 15000,
"clabe": "012180001234567890",
"referenceNumerical": null,
"createdAt": "2026-03-26T10:00:59.000Z",
"confirmedAt": null,
"counterpart": {
"name": null,
"taxId": null,
"bank": {}
}
},
"errorCode": "INSUFFICIENT_FUNDS",
"errorMessage": "Cuenta sin saldo suficiente",
"metadata": {}
}
Notas:
- En
status: FAILED, referenceNumerical y confirmedAt son null (la red SPEI nunca confirmó la transacción).
errorCode y errorMessage describen el motivo de la falla.
Compatible Endpoints
| Endpoint | Método | Descripción |
|---|
/api/spei/cash-in | POST | Generar CLABE desechable de cobro |
/api/spei/cash-out | POST | Enviar SPEI por CLABE |
/api/oxxo/cash-in | POST | Generar cupón OXXO |
Behavior
- La API procesa la request normalmente: retorna
201 Created con status: PENDING.
- El header no altera la respuesta inmediata.
- Tras ~1 segundo (o más con
delayed:), el webhook es enviado a la URL configurada.
- Tu sistema recibe el webhook con
status correspondiente al scenario (CONFIRMED o FAILED).
El header controla solo el webhook. La respuesta HTTP siempre es 201 Created con status: PENDING, sin importar el scenario.
Restrictions
X-Sandbox-Scenario funciona exclusivamente con cuentas configuradas en modo sandbox.
- Cuentas de producción que envíen el header reciben:
{
"statusCode": 400,
"message": "X-Sandbox-Scenario header is only supported in sandbox mode. This account is not configured with a sandbox provider."
}
Contacta a contact@ntxpay.com para verificar la configuración de tu cuenta.
Best Practices
- Prueba todos los escenarios — implementa el manejo de
CONFIRMED, PENDING, FAILED y EXPIRED antes de ir a producción.
- Valida los campos de error — usa
errorCode y errorMessage para tomar la acción adecuada (notificar usuario, retry, etc.).
- Prueba con delay — verifica que tu sistema maneja bien la entrega lenta del webhook.
- Idempotencia — usa
transaction.id como llave de idempotencia; el mismo webhook puede ser reenviado.