Skip to main content

What it does

POST /api/spei/cash-out requests a SPEI transfer to a destination CLABE. In sandbox, the full accounting pipeline runs — balance is debited, fee is charged, statement entry is generated — but the Banxico call is simulated. The HTTP response is always 201 Created with status: PENDING. The final outcome arrives via cash_out webhook ~1 second later (success scenario) or as forced by the scenario.

Prerequisite

Your sandbox account needs balance. Run at least one cash-in first — simulated balance is debited just like in production.

Example

curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amountCentavos": 15000,
    "destinationClabe": "012180001234567890",
    "beneficiaryName": "Maria Lopez",
    "beneficiaryTaxId": "LOPM850101ABC",
    "externalId": "payout-001",
    "description": "Supplier payment"
  }'

Response (201)

{
  "id": 12346,
  "externalId": "payout-001",
  "status": "PENDING",
  "amountCentavos": 15000,
  "clabe": "012180001234567890"
}

Expected webhook

After ~1 second (success scenario):
{
  "event": "cash_out",
  "deliveryId": "...",
  "transaction": {
    "id": 12346,
    "externalId": "payout-001",
    "status": "CONFIRMED",
    "amountCentavos": 15000,
    "clabe": "012180001234567890",
    "referenceNumerical": "9876543",
    "confirmedAt": "2026-03-26T10:00:01.000Z"
  },
  "errorCode": null,
  "errorMessage": null
}

Useful error scenarios

Force specific behaviors via the X-Sandbox-Scenario header:
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 '{ ... }'
ScenarioWhen to use
error:insufficient-fundsValidate UX when your customer tries to pay without balance
error:invalid-clabeValidate CLABE parsing/validation in your frontend
error:account-not-foundValidate post-network error (CLABE exists locally but not on the SPEI network)
error:bank-rejectedValidate generic fallback
delayed:30sValidate “transfer in progress” UX
See Scenarios for the full list.

Synchronous validations

Even in sandbox, some validations happen before the 201 is returned:
Synchronous errorHTTPWhen
400 INVALID_AMOUNT400amountCentavos <= 0
400 INVALID_CLABE_FORMAT400CLABE with invalid format (non-numeric, wrong length)
400 DUPLICATE_EXTERNAL_ID400externalId already used in another transaction for this account
400 INSUFFICIENT_FUNDS400Real balance below amountCentavos + fee (without using a scenario)
Scenarios prefixed with error: affect the webhook — the synchronous response is always 201 PENDING. Structural validations like format/duplication fail synchronously.