Como usar
Adicione o header X-Sandbox-Scenario: <cenário> a qualquer chamada de cash-in ou cash-out. Sem o header, o sandbox usa o cenário success por padrão.
curl -X POST https://sandbox.mx.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"
}'
O header controla apenas o webhook assíncrono. A resposta HTTP é sempre 201 Created com status: PENDING, independentemente do cenário. O resultado final (CONFIRMED, FAILED ou EXPIRED) chega no webhook ~1 segundo depois.
Cenários disponíveis
Cenários de sucesso
| Header Value | Comportamento síncrono | Webhook |
|---|
success (default) | 201 PENDING | CONFIRMED em ~1s |
| (sem header) | 201 PENDING | CONFIRMED em ~1s |
Cenários de erro
| Header Value | Comportamento síncrono | Webhook |
|---|
error:insufficient-funds | 201 PENDING | FAILED com errorCode: INSUFFICIENT_FUNDS |
error:invalid-clabe | 201 PENDING | FAILED com errorCode: INVALID_CLABE |
error:account-not-found | 201 PENDING | FAILED com errorCode: ACCOUNT_NOT_FOUND |
error:account-blocked | 201 PENDING | FAILED com errorCode: ACCOUNT_BLOCKED |
error:duplicate-external-id | 201 PENDING | FAILED com errorCode: DUPLICATE_EXTERNAL_ID |
error:bank-rejected | 201 PENDING | FAILED com errorCode: BANK_REJECTED |
Cenários de atraso
| Header Value | Comportamento síncrono | Webhook |
|---|
delayed:5s | 201 PENDING | CONFIRMED após +5s |
delayed:30s | 201 PENDING | CONFIRMED após +30s |
delayed:60s | 201 PENDING | CONFIRMED após +60s |
O delay máximo permitido é de 120 segundos — valores acima são truncados automaticamente.
Exemplo: webhook de sucesso
{
"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": {}
}
Exemplo: webhook de falha
{
"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,
"confirmedAt": null
},
"errorCode": "INSUFFICIENT_FUNDS",
"errorMessage": "Conta sem saldo suficiente",
"metadata": {}
}
Notas:
- Em
status: FAILED, referenceNumerical e confirmedAt são null — a rede SPEI nunca confirmou a transação.
errorCode e errorMessage descrevem o motivo da falha.
Restrições
- O header
X-Sandbox-Scenario funciona exclusivamente em contas sandbox.
- Contas de produção que enviem o header recebem:
{
"statusCode": 400,
"message": "X-Sandbox-Scenario header is only supported in sandbox mode."
}
Boas práticas
- Teste todos os cenários antes de ir ao ar — implemente o tratamento de
CONFIRMED, PENDING, FAILED e EXPIRED.
- Valide os campos de erro — use
errorCode para decisões automáticas; reserve errorMessage para logs/usuários.
- Teste com delay — verifique que seu sistema lida bem com entrega lenta do webhook.
- Idempotência — use
transaction.id como chave de idempotência; o mesmo webhook pode ser reenviado.