diff --git a/api-reference/openapi.json b/api-reference/openapi.json index 340d4ad..9494ccc 100644 --- a/api-reference/openapi.json +++ b/api-reference/openapi.json @@ -17,10 +17,6 @@ "name": "auth", "description": "Geração de token via certificado X.509 + clientId/clientSecret" }, - { - "name": "Signup", - "description": "Criação de conta (sandbox ou produção)" - }, { "name": "SPEI", "description": "Transferências interbancárias instantâneas mexicanas (cash-in via CLABE descartável; cash-out para CLABE)" @@ -29,10 +25,6 @@ "name": "Balance", "description": "Consulta de saldo da conta (centavos MXN)" }, - { - "name": "Transactions", - "description": "Listagem paginada de transações da conta (rate-limit 30/min)" - }, { "name": "Webhooks Config", "description": "Configuração de webhooks para notificações de eventos" @@ -63,7 +55,7 @@ "properties": { "clientId": { "type": "string", - "description": "OAuth 2.0 client ID emitido durante o signup", + "description": "OAuth 2.0 client ID da sua conta NTX Pay (fornecido no onboarding)", "example": "qr-93-550e8400" }, "clientSecret": { @@ -98,154 +90,6 @@ } } }, - "CreateSignupInputDto": { - "type": "object", - "required": [ - "email", - "holderName", - "entityType" - ], - "properties": { - "email": { - "type": "string", - "format": "email", - "description": "Email de contato — vira o login (owner) do portal.", - "example": "dev@empresa.com" - }, - "holderName": { - "type": "string", - "minLength": 3, - "maxLength": 255, - "description": "Nome/razão do titular da conta", - "example": "Empresa Demo S.A. de C.V." - }, - "entityType": { - "type": "string", - "enum": [ - "SAPI_CV", - "SA_CV", - "OTHER" - ], - "description": "Tipo de entidade jurídica mexicana. `SAPI_CV` e `SA_CV` exigem `razonSocial`.", - "example": "OTHER" - }, - "razonSocial": { - "type": "string", - "minLength": 3, - "maxLength": 255, - "description": "Razão social. **Obrigatória** quando `entityType` é `SAPI_CV` (sufixo \"S.A.P.I. de C.V.\") ou `SA_CV` (sufixo \"S.A. de C.V.\").", - "example": "Empresa Demo S.A. de C.V." - }, - "holderTaxIdPrimary": { - "type": "string", - "minLength": 10, - "maxLength": 20, - "description": "RFC do titular (10-20 caracteres). **Opcional** no sandbox: se omitido, um RFC único de teste é gerado automaticamente.", - "example": "XAXX010101000" - }, - "name": { - "type": "string", - "minLength": 3, - "maxLength": 255, - "description": "Nome do contato (default = holderName).", - "example": "Maria Lopez" - }, - "holderNickname": { - "type": "string", - "minLength": 3, - "maxLength": 100, - "description": "Apelido / nome fantasia.", - "example": "Empresa Demo" - }, - "phone": { - "type": "string", - "minLength": 8, - "maxLength": 20, - "description": "Telefone E.164", - "example": "+5215512345678" - }, - "isSandbox": { - "type": "boolean", - "description": "Default **true**: cria conta SANDBOX self-service. `isSandbox=false` (conta de produção) NÃO é self-service — requer onboarding com KYC pelo time.", - "default": true, - "example": true - }, - "holderTaxIdPrimaryType": { - "type": "string", - "enum": [ - "RFC", - "CURP" - ], - "deprecated": true, - "description": "[DEPRECATED] Ignorado pelo backend (o tipo do documento é sempre RFC; a classificação jurídica vem de `entityType`)." - }, - "accountType": { - "type": "string", - "enum": [ - "PJ", - "PF" - ], - "deprecated": true, - "description": "[DEPRECATED] Ignorado pelo backend. Use `entityType`." - } - } - }, - "SignupCertificateDto": { - "type": "object", - "properties": { - "fingerprint": { - "type": "string", - "example": "sha256:abcd1234..." - }, - "expiresAt": { - "type": "string", - "format": "date-time", - "example": "2027-05-13T00:00:00.000Z" - } - } - }, - "CreateSignupOutputDto": { - "type": "object", - "properties": { - "accountId": { - "type": "integer", - "example": 93 - }, - "publicId": { - "type": "string", - "example": "acc_550e8400-e29b-41d4-a716-446655440000" - }, - "mainProvider": { - "type": "string", - "enum": [ - "smartfastpay", - "sandbox" - ] - }, - "credentials": { - "type": "object", - "properties": { - "clientId": { - "type": "string", - "example": "qr-93-550e8400" - }, - "clientSecret": { - "type": "string", - "description": "Secret OAuth 2.0 — exibido **uma única vez**. Guarde em local seguro.", - "example": "a1b2c3d4e5f6g7h8" - } - } - }, - "certificate": { - "$ref": "#/components/schemas/SignupCertificateDto", - "description": "Certificado mTLS, quando emitido" - }, - "message": { - "type": "string", - "example": "Conta criada com sucesso. Guarde clientSecret em local seguro." - } - } - }, "SpeiCashInInputDto": { "type": "object", "required": [ @@ -602,113 +446,6 @@ } } }, - "TransactionOutputDto": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "description": "ID interno da transação", - "example": 12345 - }, - "externalId": { - "type": "string", - "nullable": true, - "description": "External / idempotency reference", - "example": "ext-abc-123" - }, - "paymentMethod": { - "type": "string", - "example": "SPEI" - }, - "direction": { - "type": "string", - "enum": [ - "in", - "out" - ], - "example": "in" - }, - "type": { - "type": "string", - "description": "cash_in, cash_out, refund_in, refund_out, internal_transfer", - "example": "cash_in" - }, - "status": { - "type": "string", - "enum": [ - "PENDING", - "CONFIRMED", - "FAILED", - "EXPIRED" - ], - "example": "CONFIRMED" - }, - "provider": { - "type": "string", - "example": "smartfastpay" - }, - "amountCentavos": { - "type": "integer", - "example": 50000 - }, - "clabe": { - "type": "string", - "nullable": true, - "description": "CLABE de origem / destino", - "example": "012180001234567890" - }, - "createdAt": { - "type": "string", - "format": "date-time", - "example": "2026-05-12T14:30:00.000Z" - }, - "confirmedAt": { - "type": "string", - "nullable": true, - "format": "date-time", - "example": "2026-05-12T14:31:05.000Z" - } - } - }, - "PaginationMetadataDto": { - "type": "object", - "properties": { - "total": { - "type": "integer", - "description": "Total de registros", - "example": 142 - }, - "limit": { - "type": "integer", - "description": "Limite aplicado", - "example": 20 - }, - "offset": { - "type": "integer", - "description": "Offset aplicado", - "example": 0 - }, - "hasMore": { - "type": "boolean", - "description": "Existe próxima página", - "example": true - } - } - }, - "SearchTransactionsOutputDto": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TransactionOutputDto" - } - }, - "metadata": { - "$ref": "#/components/schemas/PaginationMetadataDto" - } - } - }, "TestWebhookInputDto": { "type": "object", "required": [ @@ -851,44 +588,6 @@ } } }, - "/api/signup": { - "post": { - "summary": "Criar nova conta (sandbox ou produção)", - "description": "Endpoint **público** (sem JWT, sem certificado). Cria conta NTX Pay MX, configura Keycloak, limites e taxas default. Se `isSandbox=true`, conta usa provider `sandbox` (transações simuladas); caso contrário, `smartfastpay` (produção).", - "operationId": "SignupController_create", - "tags": [ - "Signup" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSignupInputDto" - } - } - } - }, - "responses": { - "201": { - "description": "Conta criada com sucesso", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSignupOutputDto" - } - } - } - }, - "400": { - "description": "Dados inválidos ou tax ID já em uso" - }, - "502": { - "description": "account-ms indisponível" - } - } - } - }, "/api/spei/cash-in": { "post": { "summary": "Criar cobrança SPEI (cash-in)", @@ -1014,104 +713,6 @@ } } }, - "/api/transactions": { - "get": { - "summary": "Listar transações da conta autenticada", - "description": "**Requer Bearer JWT**. O `accountId` é extraído do token. Retorna uma lista paginada de transações da conta. **Rate-limit: 30 req/min por conta.**", - "operationId": "TransactionsController_search", - "tags": [ - "Transactions" - ], - "security": [ - { - "bearer": [] - } - ], - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 20 - }, - "description": "Quantidade máxima de registros (1-100, default 20)" - }, - { - "name": "offset", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "minimum": 0, - "default": 0 - }, - "description": "Offset para paginação (default 0)" - }, - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "type": "string" - }, - "description": "Filtro por status (PENDING | CONFIRMED | FAILED | EXPIRED)", - "example": "CONFIRMED" - }, - { - "name": "paymentMethod", - "in": "query", - "required": false, - "schema": { - "type": "string" - }, - "description": "Filtro por payment method (SPEI)", - "example": "SPEI" - }, - { - "name": "direction", - "in": "query", - "required": false, - "schema": { - "type": "string", - "enum": [ - "in", - "out" - ] - }, - "description": "Filtro por direction (in | out)", - "example": "in" - } - ], - "responses": { - "200": { - "description": "Transações retornadas com sucesso", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SearchTransactionsOutputDto" - } - } - } - }, - "400": { - "description": "Parâmetros inválidos" - }, - "401": { - "description": "Token inválido ou ausente" - }, - "429": { - "description": "Rate limit excedido (30 req/min por conta)" - }, - "502": { - "description": "mexico-ms indisponível" - } - } - } - }, "/api/webhooks-config": { "get": { "summary": "Listar webhooks da conta", diff --git a/docs.json b/docs.json index 9e9ab5e..690356a 100644 --- a/docs.json +++ b/docs.json @@ -44,12 +44,9 @@ "pages": [ "es/guides/get-started", "es/guides/authentication", - "es/guides/signup", "es/guides/balance", "es/guides/spei-cash-in", "es/guides/spei-cash-out", - "es/guides/transactions-list", - "es/guides/sandbox-testing", "es/guides/postman-collections" ] }, @@ -76,12 +73,6 @@ "es/guides/webhooks/refund-out" ] }, - { - "group": "Registro", - "pages": [ - "es/endpoints/signup" - ] - }, { "group": "Autenticación", "pages": [ @@ -118,12 +109,9 @@ "pages": [ "en/guides/get-started", "en/guides/authentication", - "en/guides/signup", "en/guides/balance", "en/guides/spei-cash-in", "en/guides/spei-cash-out", - "en/guides/transactions-list", - "en/guides/sandbox-testing", "en/guides/postman-collections" ] }, @@ -150,12 +138,6 @@ "en/guides/webhooks/refund-out" ] }, - { - "group": "Signup", - "pages": [ - "en/endpoints/signup" - ] - }, { "group": "Authentication", "pages": [ @@ -193,12 +175,9 @@ "pages": [ "pt-br/guides/get-started", "pt-br/guides/authentication", - "pt-br/guides/signup", "pt-br/guides/balance", "pt-br/guides/spei-cash-in", "pt-br/guides/spei-cash-out", - "pt-br/guides/transactions-list", - "pt-br/guides/sandbox-testing", "pt-br/guides/postman-collections" ] }, @@ -225,12 +204,6 @@ "pt-br/guides/webhooks/refund-out" ] }, - { - "group": "Cadastro", - "pages": [ - "pt-br/endpoints/signup" - ] - }, { "group": "Autenticação", "pages": [ diff --git a/en/endpoints/signup.mdx b/en/endpoints/signup.mdx deleted file mode 100644 index a31b083..0000000 --- a/en/endpoints/signup.mdx +++ /dev/null @@ -1,3 +0,0 @@ ---- -openapi: post /api/signup ---- diff --git a/en/guides/authentication.mdx b/en/guides/authentication.mdx index 7f7c4a8..ec9fa06 100644 --- a/en/guides/authentication.mdx +++ b/en/guides/authentication.mdx @@ -8,7 +8,7 @@ description: 'X.509 certificate (mTLS) + OAuth 2.0 client_credentials to get an The NTX Pay México API uses two-layer authentication: 1. **X.509 certificate (mTLS)** — delivered by NTX Pay at onboarding, proves the client server's identity. -2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` received at signup, validated together with the certificate. +2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` received during onboarding, validated together with the certificate. The combination returns a **JWT** (10-minute validity) used in the other endpoints as `Authorization: Bearer ...`. @@ -115,7 +115,7 @@ async function getToken(): Promise { - Full flow (signup → token → transaction) + Full flow (token → transaction) Use the token to query the balance diff --git a/en/guides/balance.mdx b/en/guides/balance.mdx index de745c7..fb0a03c 100644 --- a/en/guides/balance.mdx +++ b/en/guides/balance.mdx @@ -46,7 +46,7 @@ curl -X GET https://sandbox.mx.ntxpay.com/api/balance \ - Pending balance in MXN centavos. Includes cash-out in processing and cash-in waiting for final provider confirmation. + Pending balance in MXN centavos. Includes cash-out in processing and cash-in waiting for final settlement confirmation. @@ -109,7 +109,4 @@ async function safeSpeiCashOut(amountCentavos: number, token: string, dto: any) Send a SPEI transfer using the available balance - - See the movement history - diff --git a/en/guides/get-started.mdx b/en/guides/get-started.mdx index c3d1fae..d8b4c17 100644 --- a/en/guides/get-started.mdx +++ b/en/guides/get-started.mdx @@ -52,10 +52,10 @@ The NTX Pay México API lets your company perform payment operations, check bala ## Environments -| Environment | URL | Provider | -|---|---|---| -| Sandbox | `https://sandbox.mx.ntxpay.com` | `sandbox` (simulated transactions) | -| Production | Provided at onboarding | `smartfastpay` | +| Environment | URL | +|---|---| +| Sandbox | `https://sandbox.mx.ntxpay.com` | +| Production | Provided at onboarding | ## Support diff --git a/en/guides/postman-collections.mdx b/en/guides/postman-collections.mdx index a7ef0a6..4cee607 100644 --- a/en/guides/postman-collections.mdx +++ b/en/guides/postman-collections.mdx @@ -45,7 +45,6 @@ The collection is organized in typical usage order: ## Available Folders - `Auth` — JWT generation -- `Signup` — account creation - `Balance` — balance query - `SPEI` — cash-in, cash-out, transaction by external ID - `Transactions` — list diff --git a/en/guides/sandbox-testing.mdx b/en/guides/sandbox-testing.mdx deleted file mode 100644 index 85aebcf..0000000 --- a/en/guides/sandbox-testing.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: 'Sandbox' -description: 'Simulate SPEI scenarios with no cost or production risk' ---- - -## What it is - -The **sandbox** is an isolated environment with simulated transactions. Useful for: - -- Testing integration before going to production -- Validating webhook flows in different scenarios -- Training team without risk of moving real money - -## How to access - -1. Create an account with `isSandbox: true` in `POST /api/signup`: - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "dev@example.com", - "holderName": "Test", - "entityType": "OTHER", - "isSandbox": true - }' -``` - -2. The created account will have `mainProvider: "sandbox"` (instead of `smartfastpay`) -3. Always use the host `https://sandbox.mx.ntxpay.com` for that account - -## Differences vs Production - -| Aspect | Sandbox | Production | -|---|---|---| -| Provider | `sandbox` | `smartfastpay` | -| SPEI cash-in confirmation | **Immediate** (~seconds) | Real (seconds to minutes) | -| SPEI cash-out | Settles immediately | Real Banxico settlement | -| Webhooks | Same format | Same format | -| Cost | Free | Per contract | - -## Recommended Scenarios - -### 1. Happy-path cash-in - -1. Create sandbox account -2. Generate token -3. Create SPEI cash-in -4. Confirm receipt of `cash_in` webhook with `status: CONFIRMED` - -### 2. Cash-out + balance - -1. Receive at least one cash-in (balance > 0) -2. Cash-out an amount ≤ balance -3. Confirm `cash_out` webhook with `status: CONFIRMED` -4. Confirm decremented balance in `/api/balance` - -### 3. Cash-out with insufficient balance - -1. Attempt cash-out > available balance -2. Should receive `400` immediately - -### 4. Rate-limit on transactions - -1. Make 31+ calls to `/api/transactions` in < 1 minute -2. From the 31st onward, should receive `429` - -### 5. Webhook dedupe - -1. Force your handler to return `500` on one delivery -2. NTX Pay will retry — verify your dedupe by the `X-NTXPay-Delivery` - -## Force Specific Scenarios - -In sandbox, specific `amountCentavos` values can trigger special behaviors (consult the NTX Pay team for active conventions). Typical examples: - -| `amountCentavos` | Expected behavior | -|---|---| -| `1` | Immediate confirmation | -| `666` | Force failure (`status: FAILED`) | -| `13` | Force quick expiration | - - - These conventions may vary — confirm with NTX Pay which are currently active. - - -## Promotion to Production - -When comfortable: - -1. Create a **new account** via `POST /api/signup` on your production host (provided at onboarding) **without** `isSandbox` -2. Only change: - - Host: `sandbox.mx.ntxpay.com` → production host (provided at onboarding) - - Credentials (`clientId`/`clientSecret`) - - X.509 certificate (production is distinct from sandbox) -3. Reconfigure webhooks on the production account -4. Make a low-value transaction before releasing volume diff --git a/en/guides/signup.mdx b/en/guides/signup.mdx deleted file mode 100644 index 8269c7b..0000000 --- a/en/guides/signup.mdx +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: 'Signup' -description: 'Programmatic NTX Pay México account creation (sandbox or production)' ---- - -## Overview - -The `POST /api/signup` endpoint creates a new NTX Pay México account. **No authentication required** (no JWT, no certificate) — it's the integration entry point. - -On creation, NTX Pay: - -1. Sets up the account in Keycloak (identity provider) -2. Applies default limits and fees -3. Sets the `mainProvider`: - - `sandbox` if `isSandbox=true` (default — self-service simulated transactions) - - `smartfastpay` otherwise (production — **not** self-service; requires KYC onboarding with the team) -4. Issues OAuth 2.0 credentials (`clientId` + `clientSecret`) -5. Optionally issues mTLS certificate - -## Endpoint - -### POST /api/signup - -#### Request — Individual (sandbox) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "maria@example.com", - "holderName": "Maria Lopez", - "entityType": "OTHER", - "phone": "+5215512345678", - "isSandbox": true - }' -``` - - - In sandbox, `holderTaxIdPrimary` (RFC) is optional — if omitted, a unique test RFC is generated automatically. - - -#### Request — Legal Entity (`SA_CV` / `SAPI_CV`) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "contact@acme.mx", - "holderName": "Acme S.A. de C.V.", - "entityType": "SA_CV", - "razonSocial": "Acme S.A. de C.V.", - "holderTaxIdPrimary": "ACM850101AB1", - "isSandbox": true - }' -``` - -#### Response (201) - -```json -{ - "accountId": 93, - "publicId": "acc_550e8400-e29b-41d4-a716-446655440000", - "mainProvider": "sandbox", - "credentials": { - "clientId": "qr-93-550e8400", - "clientSecret": "a1b2c3d4e5f6g7h8" - }, - "certificate": { - "fingerprint": "sha256:abcd1234...", - "expiresAt": "2027-05-13T00:00:00.000Z" - }, - "message": "Account created successfully. Store clientSecret in a safe place." -} -``` - - - The `clientSecret` is shown **only once**, in the signup response. If lost, a new credential must be issued via the panel or by contacting support. - - -## Request Fields - - - Contact email — becomes the portal login (owner). - - - - Name / legal name of the account holder (minimum 3, maximum 255 characters). - - - - Mexican legal entity type: `SAPI_CV`, `SA_CV` or `OTHER`. `SAPI_CV` and `SA_CV` require `razonSocial`. - - - - Legal name (razón social). **Required** when `entityType` is `SAPI_CV` (suffix "S.A.P.I. de C.V.") or `SA_CV` (suffix "S.A. de C.V."). Optional for `OTHER`. - - - - RFC of the holder (10–20 characters). **Optional in sandbox**: if omitted, a unique test RFC is generated automatically. - - - - Phone in E.164 format (8–20 characters). Ex.: `+5215512345678`. - - - - Defaults to **`true`** → self-service sandbox account (provider `sandbox`, simulated transactions). - `false` → production account (provider `smartfastpay`) — **not** self-service; requires KYC onboarding with the team. - - - - **Deprecated** — accepted but ignored by the backend (the document type is always RFC). Legal classification comes from `entityType`. - - - - **Deprecated** — accepted but ignored by the backend. Use `entityType` instead. - - -## Sandbox vs Production - -| Aspect | Sandbox | Production | -|---|---|---| -| Provider | `sandbox` | `smartfastpay` | -| SPEI confirmation | Immediate (simulated) | Real (seconds to minutes via Banxico) | -| Cost | Free | Tariffs in production | -| Limits | Permissive | Per contract | -| Base endpoint | `https://sandbox.mx.ntxpay.com` | Provided at onboarding | - -## Common Errors - -| Code | Cause | -|---|---| -| `400` | Missing required field (`email`/`holderName`/`entityType`), missing `razonSocial` for `SAPI_CV`/`SA_CV`, invalid RFC, or tax ID already in use | -| `502` | `account-ms` (provisioning) unavailable — retry | - -## Next Steps - - - - Use the freshly issued clientId/clientSecret to generate the JWT - - - Best practices for testing in sandbox - - diff --git a/en/guides/spei-cash-out.mdx b/en/guides/spei-cash-out.mdx index cbfd285..4daa451 100644 --- a/en/guides/spei-cash-out.mdx +++ b/en/guides/spei-cash-out.mdx @@ -5,7 +5,7 @@ description: 'Send SPEI transfers to any CLABE' ## Overview -**SPEI cash-out** sends an interbank transfer to a **destination CLABE**. The account balance is debited and NTX Pay forwards to the provider (`smartfastpay` in production, `sandbox` for testing). Confirmation arrives via `cash_out` webhook. +**SPEI cash-out** sends an interbank transfer to a **destination CLABE**. The account balance is debited and NTX Pay processes the transfer over the SPEI network. Confirmation arrives via `cash_out` webhook. ## Endpoint @@ -89,7 +89,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `PENDING` | Cash-out accepted, waiting for SPEI settlement | | `CONFIRMED` | Settled at Banxico | -| `FAILED` | Rejected by the provider or by the SPEI network | +| `FAILED` | Rejected by the SPEI network | ## Error Codes @@ -97,7 +97,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `400` | Insufficient balance, invalid CLABE, invalid payload | | `401` | Invalid token | -| `502` | mexico-ms / provider unavailable — don't retry without checking status via `GET /api/transactions` | +| `502` | Service temporarily unavailable — don't retry without checking status via `GET /api/transactions` | ## Node.js Example with Retry @@ -126,7 +126,4 @@ async function speiCashOut(token: string, dto: any) { Details of the settlement webhook payload - - Check status without depending on webhook - diff --git a/en/guides/transactions-list.mdx b/en/guides/transactions-list.mdx deleted file mode 100644 index 2b22c48..0000000 --- a/en/guides/transactions-list.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: 'List Transactions' -description: 'Query the SPEI history of your account' ---- - -## Overview - -`GET /api/transactions` returns the paginated list of transactions for the authenticated account, covering **SPEI** (cash-in, cash-out, refund-in, refund-out, internal_transfer). It's the source of truth when you need to **reconcile** or check status without depending on webhooks. - - - **Rate limit**: 30 requests per minute, per account. Above that, `429`. - - -## Endpoint - -### GET /api/transactions - -#### Headers - -``` -Authorization: Bearer {token} -``` - -#### Query Parameters - -| Parameter | Type | Default | Description | -|---|---|---|---| -| `limit` | int (1–100) | 20 | Items per page | -| `offset` | int (≥0) | 0 | Pagination offset | -| `status` | enum | — | `PENDING`, `CONFIRMED`, `FAILED`, `EXPIRED` | -| `paymentMethod` | enum | — | `SPEI` | -| `direction` | enum | — | `in` (received), `out` (sent) | - -#### Request - -```bash -curl -X GET "https://sandbox.mx.ntxpay.com/api/transactions?status=CONFIRMED&paymentMethod=SPEI&limit=50" \ - -H "Authorization: Bearer $TOKEN" -``` - -#### Response (200) - -```json -{ - "data": [ - { - "id": 12345, - "externalId": "order-abc-123", - "paymentMethod": "SPEI", - "direction": "in", - "type": "cash_in", - "status": "CONFIRMED", - "provider": "smartfastpay", - "amountCentavos": 50000, - "clabe": "012180001234567890", - "createdAt": "2026-05-12T14:30:00.000Z", - "confirmedAt": "2026-05-12T14:31:05.000Z" - } - ], - "metadata": { - "total": 142, - "limit": 20, - "offset": 0, - "hasMore": true - } -} -``` - -## Pagination - -Iterate using `offset` until `hasMore` is `false`: - -```typescript -let offset = 0; -const limit = 50; - -while (true) { - const { data } = await axios.get('https://sandbox.mx.ntxpay.com/api/transactions', { - headers: { Authorization: `Bearer ${token}` }, - params: { limit, offset, status: 'CONFIRMED' }, - }); - - for (const tx of data.data) { - await process(tx); - } - - if (!data.metadata.hasMore) break; - offset += limit; -} -``` - -## Daily Reconciliation - -Recommended pattern for daily closing: - -1. List `CONFIRMED` transactions of the day (ideally filtering by `createdAt` on your side after fetching) -2. Cross each `externalId` with the corresponding order in your system -3. Flag pending/divergences for investigation - -## Rate Limit - -`AccountThrottlerGuard` applies a **per-account** limit (not per IP). Exceeding: - -```json -HTTP 429 Too Many Requests -{ "message": "ThrottlerException: Too Many Requests" } -``` - -Wait a few seconds before retrying. In batch routines, use `limit=100` to reduce the number of calls. - -## Response Codes - -| Code | Meaning | -|---|---| -| `200` | List returned | -| `400` | Invalid parameters (e.g. `limit > 100`) | -| `401` | Invalid token | -| `429` | Rate limit exceeded | -| `502` | mexico-ms unavailable | diff --git a/en/guides/webhooks/cash-in.mdx b/en/guides/webhooks/cash-in.mdx index 1585673..1b30012 100644 --- a/en/guides/webhooks/cash-in.mdx +++ b/en/guides/webhooks/cash-in.mdx @@ -23,7 +23,6 @@ The `cash_in` event fires when: "direction": "in", "type": "cash_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-12T14:30:00.000Z", diff --git a/en/guides/webhooks/cash-out.mdx b/en/guides/webhooks/cash-out.mdx index d40b6ec..ee31f44 100644 --- a/en/guides/webhooks/cash-out.mdx +++ b/en/guides/webhooks/cash-out.mdx @@ -8,7 +8,7 @@ description: 'Notification sent when a SPEI cash-out is settled or fails' The `cash_out` event fires in two scenarios: - **Success** — the SPEI cash-out sent via `POST /api/spei/cash-out` was settled at Banxico (`status: CONFIRMED`) -- **Failure** — the SPEI network or the provider rejected the transfer (`status: FAILED`) +- **Failure** — the SPEI network rejected the transfer (`status: FAILED`) ## Payload (confirmed) @@ -24,7 +24,6 @@ The `cash_out` event fires in two scenarios: "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-13T12:00:00.000Z", diff --git a/en/guides/webhooks/refund-in.mdx b/en/guides/webhooks/refund-in.mdx index 1216207..da8a417 100644 --- a/en/guides/webhooks/refund-in.mdx +++ b/en/guides/webhooks/refund-in.mdx @@ -27,7 +27,6 @@ Common scenarios: "direction": "in", "type": "refund_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T09:14:50.000Z", diff --git a/en/guides/webhooks/refund-out.mdx b/en/guides/webhooks/refund-out.mdx index 2fe93b8..9339625 100644 --- a/en/guides/webhooks/refund-out.mdx +++ b/en/guides/webhooks/refund-out.mdx @@ -26,7 +26,6 @@ Common scenarios: "direction": "out", "type": "refund_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T11:44:50.000Z", diff --git a/en/index.mdx b/en/index.mdx index 986f235..b982d08 100644 --- a/en/index.mdx +++ b/en/index.mdx @@ -14,7 +14,7 @@ Public gateway for SPEI (instant interbank transfers) integration. Receive and s ## Authentication -1. `POST /api/signup` creates the account and returns `clientId` + `clientSecret`. +1. Your credentials (`clientId` + `clientSecret`) are provided during onboarding. 2. `POST /api/auth/token` with X.509 certificate in the `X-SSL-Client-Cert` header + credentials returns a JWT (10 min validity). The JWT goes in `Authorization: Bearer ` for the other endpoints. @@ -36,13 +36,13 @@ ISO 8601 UTC: `2026-05-12T14:31:05.000Z`. | `401` | Invalid token or certificate | | `404` | Resource not found | | `429` | Rate limit | -| `502` | Downstream provider unavailable | +| `502` | Service temporarily unavailable | ## First steps - Signup, token and first transaction + Token and first transaction Cash-in and cash-out via CLABE diff --git a/en/sandbox/authentication.mdx b/en/sandbox/authentication.mdx index 87fb1a8..d866ee9 100644 --- a/en/sandbox/authentication.mdx +++ b/en/sandbox/authentication.mdx @@ -9,7 +9,7 @@ mode: 'wide' Sandbox authentication uses the same two layers as production: 1. **X.509 certificate (mTLS)** — issued by NTX Pay at onboarding. -2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` received during signup. +2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` received during onboarding. Together they return a **JWT** (10-minute validity) used on the remaining endpoints as `Authorization: Bearer ...`. diff --git a/en/sandbox/cash-out.mdx b/en/sandbox/cash-out.mdx index 97a1bb8..2ffcb14 100644 --- a/en/sandbox/cash-out.mdx +++ b/en/sandbox/cash-out.mdx @@ -25,7 +25,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ "destinationClabe": "012180001234567890", "beneficiaryName": "Maria Lopez", "beneficiaryTaxId": "LOPM850101ABC", - "concept": "Supplier payment" + "concept": "Invoice payment" }' ``` @@ -80,7 +80,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ |---|---|---| | `insufficient_funds` | Validate UX when your customer tries to pay without balance | `FAILED` (`errorCode: INSUFFICIENT_FUNDS`) | | `bad_clabe` | Validate handling of a transfer returned for an invalid CLABE | `RETURNED` (`errorCode: INVALID_CLABE`) | -| `rejected` | Validate generic provider/network rejection | `FAILED` | +| `rejected` | Validate generic SPEI network rejection | `FAILED` | | `returned` | Validate a transfer reversed by the counterpart bank | `RETURNED` | | `pending_long` | Validate "transfer in progress" UX (~30s) | `CONFIRMED` | | `timeout` / `provider_5xx` | Validate synchronous upstream failures (`504` / `503`) | — (synchronous error) | diff --git a/en/sandbox/introduction.mdx b/en/sandbox/introduction.mdx index efaa38f..2071be1 100644 --- a/en/sandbox/introduction.mdx +++ b/en/sandbox/introduction.mdx @@ -6,7 +6,7 @@ mode: 'wide' ## What it is -The NTX Pay sandbox lets your integration exercise **cash-in**, **cash-out**, **refund**, and **webhooks** without moving real money. Unlike simplistic mocks, the full accounting pipeline (TigerBeetle balance, limit validation, fee charging, statement generation, webhook delivery via outbox) is exercised intact. Only the external provider (SPEI/Banxico) is simulated. +The NTX Pay sandbox lets your integration exercise **cash-in**, **cash-out**, **refund**, and **webhooks** without moving real money. Unlike simplistic mocks, the full accounting pipeline (TigerBeetle balance, limit validation, fee charging, statement generation, webhook delivery via outbox) is exercised intact. Only settlement on the SPEI network is simulated. Every NTX Pay integration starts in sandbox. The endpoints, payloads, and webhooks described in this documentation are the final ones — when production is enabled for your company, the same code works by just swapping credentials. @@ -14,7 +14,7 @@ The NTX Pay sandbox lets your integration exercise **cash-in**, **cash-out**, ** ## How to enable -Your API credentials are **structurally the same** as those you would use in production. The difference lives at the account level: accounts with `mainProvider: "sandbox"` route every SPEI call internally to the NTX simulator. To create a sandbox account, contact your Account Manager or write to `contact@ntxpay.com` — onboarding is instant and KYC is auto-approved. +Your API credentials are **structurally the same** as those you would use in production. The difference lives at the account level: sandbox accounts route SPEI calls to NTX Pay's internal simulator. To create a sandbox account, contact your Account Manager or write to `contact@ntxpay.com` — onboarding is instant and KYC is auto-approved. ## Base URL @@ -37,7 +37,6 @@ Register your `webhookUrl` on the sandbox account exactly as you would in produc | Aspect | Sandbox | Production | |---|---|---| | Base URL | `https://sandbox.mx.ntxpay.com` | Provided at onboarding | -| Provider | `sandbox` (simulated) | Real bank (Banxico/SPEI) | | Balance | Simulated | Real funds | | SPEI cash-in confirmation | Immediate (~1s) | Real (seconds to minutes) | | `X-Sandbox-Scenario` | Supported | Rejected with `400` | diff --git a/en/sandbox/scenarios.mdx b/en/sandbox/scenarios.mdx index c342523..a2cad06 100644 --- a/en/sandbox/scenarios.mdx +++ b/en/sandbox/scenarios.mdx @@ -36,7 +36,7 @@ These return `201 PENDING` synchronously; the final state arrives via webhook. |---|---|---| | `success` (default) | `CONFIRMED` in ~1s | Also used when no header is sent | | `pending_long` | `CONFIRMED` after ~30s | Tests slow settlement | -| `rejected` | `FAILED` | Provider / SPEI network rejected the transfer | +| `rejected` | `FAILED` | The SPEI network rejected the transfer | | `returned` | `RETURNED` | Accepted, then reversed by the counterpart bank | | `insufficient_funds` | `FAILED` with `errorCode: INSUFFICIENT_FUNDS` | **Cash-out only** | | `bad_clabe` | `RETURNED` with `errorCode: INVALID_CLABE` | **Cash-out only** — accepted, then returned | @@ -48,7 +48,7 @@ These fail on the HTTP response itself — no webhook is sent. | Header Value | Synchronous response | |---|---| | `timeout` | Upstream timeout (`504`) after ~16s | -| `provider_5xx` | `503` provider unavailable | +| `provider_5xx` | Service temporarily unavailable (`503`) | **Cash-in restrictions:** `insufficient_funds` and `bad_clabe` do not apply to cash-in (there's no balance to debit, and the deposit CLABE is system-generated). Sending either on a cash-in returns `400` with code `SCENARIO_NOT_APPLICABLE`. @@ -68,7 +68,6 @@ These fail on the HTTP response itself — no webhook is sent. "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": "9876543", @@ -100,7 +99,6 @@ These fail on the HTTP response itself — no webhook is sent. "direction": "out", "type": "cash_out", "status": "FAILED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": null, diff --git a/es/endpoints/signup.mdx b/es/endpoints/signup.mdx deleted file mode 100644 index a31b083..0000000 --- a/es/endpoints/signup.mdx +++ /dev/null @@ -1,3 +0,0 @@ ---- -openapi: post /api/signup ---- diff --git a/es/guides/authentication.mdx b/es/guides/authentication.mdx index 0bb83b1..f9bb92f 100644 --- a/es/guides/authentication.mdx +++ b/es/guides/authentication.mdx @@ -8,7 +8,7 @@ description: 'Certificado X.509 (mTLS) + OAuth 2.0 client_credentials para obten La API NTX Pay México usa autenticación en dos capas: 1. **Certificado X.509 (mTLS)** — entregado por NTX Pay en el onboarding, comprueba la identidad del servidor cliente. -2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` recibidos en el signup, validados junto con el certificado. +2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` entregados en el onboarding, validados junto con el certificado. La combinación retorna un **JWT** (validez 10 minutos) usado en los demás endpoints como `Authorization: Bearer ...`. @@ -115,7 +115,7 @@ async function getToken(): Promise { - Flujo completo (signup → token → transacción) + Flujo completo (token → transacción) Usa el token para consultar el saldo diff --git a/es/guides/balance.mdx b/es/guides/balance.mdx index 39a8ed9..514f345 100644 --- a/es/guides/balance.mdx +++ b/es/guides/balance.mdx @@ -46,7 +46,7 @@ curl -X GET https://sandbox.mx.ntxpay.com/api/balance \ - Saldo pendiente en centavos MXN. Incluye cash-out en procesamiento y cash-in aguardando confirmación final del provider. + Saldo pendiente en centavos MXN. Incluye cash-out en procesamiento y cash-in aguardando confirmación final de la liquidación. @@ -109,7 +109,4 @@ async function safeSpeiCashOut(amountCentavos: number, token: string, dto: any) Envía una transferencia SPEI usando el saldo disponible - - Consulta el historial de movimientos - diff --git a/es/guides/get-started.mdx b/es/guides/get-started.mdx index 9582408..b083e3f 100644 --- a/es/guides/get-started.mdx +++ b/es/guides/get-started.mdx @@ -52,10 +52,10 @@ La API NTX Pay México permite que tu empresa realice operaciones de pago, consu ## Ambientes -| Ambiente | URL | Provider | -|---|---|---| -| Sandbox | `https://sandbox.mx.ntxpay.com` | `sandbox` (transacciones simuladas) | -| Producción | Provista en el onboarding | `smartfastpay` | +| Ambiente | URL | +|---|---| +| Sandbox | `https://sandbox.mx.ntxpay.com` | +| Producción | Provista en el onboarding | ## Soporte diff --git a/es/guides/postman-collections.mdx b/es/guides/postman-collections.mdx index 1d44f02..7a494b2 100644 --- a/es/guides/postman-collections.mdx +++ b/es/guides/postman-collections.mdx @@ -45,7 +45,6 @@ La colección está organizada en el orden de uso típico: ## Carpetas Disponibles - `Auth` — generación de JWT -- `Signup` — creación de cuenta - `Balance` — consulta de saldo - `SPEI` — cash-in, cash-out, transaction by external ID - `Transactions` — listar diff --git a/es/guides/sandbox-testing.mdx b/es/guides/sandbox-testing.mdx deleted file mode 100644 index f0a3701..0000000 --- a/es/guides/sandbox-testing.mdx +++ /dev/null @@ -1,251 +0,0 @@ ---- -title: 'Sandbox Testing' -description: 'Cómo usar el ambiente sandbox del NTX Pay México para simular escenarios SPEI sin costo ni riesgo de producción.' ---- - -## 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://sandbox.mx.ntxpay.com` | Provista en el onboarding | -| 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 - - - - Contacta a tu account manager o escribe a `contact@ntxpay.com`. - - - Certificado X.509 + `clientId`/`clientSecret` exclusivos del sandbox. - - - `POST /api/webhooks-config` con la URL HTTPS que recibirá los eventos simulados. - - - En el dashboard, ve a **Settings** y verifica que el provider sea `sandbox`. - - - 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 - -En la mayoría de los escenarios el header **no altera la respuesta HTTP**: la API responde `201 Created` con `status: "PENDING"` y el scenario afecta el **webhook asíncrono** disparado ~1 segundo después. Las excepciones son `timeout` y `provider_5xx`, que fallan en la propia respuesta HTTP síncrona. - -| Request | HTTP Response | Webhook (~1s después) | -|---|---|---| -| Sin `X-Sandbox-Scenario` | `201 PENDING` | `CONFIRMED` | -| `X-Sandbox-Scenario: success` | `201 PENDING` | `CONFIRMED` | -| `X-Sandbox-Scenario: insufficient_funds` | `201 PENDING` | `FAILED` con `errorCode` (solo cash-out) | -| `X-Sandbox-Scenario: pending_long` | `201 PENDING` | `CONFIRMED` tras ~30s | -| `X-Sandbox-Scenario: provider_5xx` | `503` (síncrono) | — | - -## How to Use - - - -```bash cURL -curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ - -H "Authorization: Bearer $TOKEN" \ - -H "X-Sandbox-Scenario: insufficient_funds" \ - -H "Content-Type: application/json" \ - -d '{ - "amountCentavos": 15000, - "destinationClabe": "012180001234567890", - "beneficiaryName": "Maria Lopez" - }' -``` - -```javascript JavaScript -const response = await axios.post( - 'https://sandbox.mx.ntxpay.com/api/spei/cash-out', - { - amountCentavos: 15000, - destinationClabe: '012180001234567890', - beneficiaryName: 'Maria Lopez', - }, - { - headers: { - Authorization: `Bearer ${token}`, - 'X-Sandbox-Scenario': 'insufficient_funds', - }, - } -); -``` - -```python Python -response = requests.post( - "https://sandbox.mx.ntxpay.com/api/spei/cash-out", - json={ - "amountCentavos": 15000, - "destinationClabe": "012180001234567890", - "beneficiaryName": "Maria Lopez", - }, - headers={ - "Authorization": f"Bearer {token}", - "X-Sandbox-Scenario": "insufficient_funds", - }, -) -``` - - - -## Available Scenarios - -Valores canónicos: `success`, `pending_long`, `rejected`, `returned`, `insufficient_funds`, `bad_clabe`, `timeout`, `provider_5xx`. - -### Escenarios de resultado asíncrono (`201 PENDING` → webhook) - -| Header Value | Descripción | Webhook Status | -|---|---|---| -| `success` _(o sin header)_ | Comportamiento default del sandbox | `CONFIRMED` | -| `pending_long` | Confirma tras ~30s (settlement lento) | `CONFIRMED` | -| `rejected` | El proveedor / red SPEI rechazó | `FAILED` | -| `returned` | Aceptada y luego devuelta por el banco contraparte | `RETURNED` | -| `insufficient_funds` | Cuenta sin saldo suficiente (**solo cash-out**) | `FAILED` (`errorCode: INSUFFICIENT_FUNDS`) | -| `bad_clabe` | CLABE inválida (**solo cash-out**) | `RETURNED` (`errorCode: INVALID_CLABE`) | - -### Escenarios de error síncrono (sin webhook) - -| Header Value | Descripción | HTTP Response | -|---|---|---| -| `timeout` | Timeout upstream tras ~16s | `504` | -| `provider_5xx` | Proveedor no disponible | `503` | - - - `insufficient_funds` y `bad_clabe` **no aplican a cash-in** — enviarlos en un cash-in devuelve `400` con código `SCENARIO_NOT_APPLICABLE`. - - -## Received Webhook Examples - -### Success Webhook (default) - -```json -{ - "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 (`insufficient_funds`) - -```json -{ - "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 | - -## 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`). - - - En la mayoría de los escenarios el header controla **solo el webhook**, y la respuesta HTTP es `201 Created` con `status: PENDING`. Las excepciones `timeout` (`504`) y `provider_5xx` (`503`) fallan en la propia respuesta síncrona. - - -## Restrictions - -- `X-Sandbox-Scenario` funciona **exclusivamente** con cuentas configuradas en modo sandbox. -- Cuentas de producción que envíen el header reciben: - -```json -{ - "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 - -1. **Prueba todos los escenarios** — implementa el manejo de `CONFIRMED`, `PENDING`, `FAILED` y `EXPIRED` antes de ir a producción. -2. **Valida los campos de error** — usa `errorCode` y `errorMessage` para tomar la acción adecuada (notificar usuario, retry, etc.). -3. **Prueba con delay** — verifica que tu sistema maneja bien la entrega lenta del webhook. -4. **Idempotencia** — usa `transaction.id` como llave de idempotencia; el mismo webhook puede ser reenviado. diff --git a/es/guides/signup.mdx b/es/guides/signup.mdx deleted file mode 100644 index a31926d..0000000 --- a/es/guides/signup.mdx +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: 'Signup' -description: 'Creación programática de cuenta NTX Pay México (sandbox o producción)' ---- - -## Visión General - -El endpoint `POST /api/signup` crea una nueva cuenta NTX Pay México. **No requiere autenticación** (sin JWT, sin certificado) — es el punto de entrada de la integración. - -Al crearla, NTX Pay: - -1. Configura la cuenta en Keycloak (identity provider) -2. Aplica límites y tarifas default -3. Define el `mainProvider`: - - `sandbox` si `isSandbox=true` (default — self-service con transacciones simuladas) - - `smartfastpay` en caso contrario (producción — **no** es self-service; requiere onboarding con KYC por el equipo) -4. Emite credenciales OAuth 2.0 (`clientId` + `clientSecret`) -5. Opcionalmente emite certificado mTLS - -## Endpoint - -### POST /api/signup - -#### Request — Persona Física (sandbox) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "maria@example.com", - "holderName": "Maria Lopez", - "entityType": "OTHER", - "phone": "+5215512345678", - "isSandbox": true - }' -``` - - - En sandbox, `holderTaxIdPrimary` (RFC) es opcional — si se omite, se genera automáticamente un RFC de prueba único. - - -#### Request — Persona Moral (`SA_CV` / `SAPI_CV`) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "contacto@acme.mx", - "holderName": "Acme S.A. de C.V.", - "entityType": "SA_CV", - "razonSocial": "Acme S.A. de C.V.", - "holderTaxIdPrimary": "ACM850101AB1", - "isSandbox": true - }' -``` - -#### Response (201) - -```json -{ - "accountId": 93, - "publicId": "acc_550e8400-e29b-41d4-a716-446655440000", - "mainProvider": "sandbox", - "credentials": { - "clientId": "qr-93-550e8400", - "clientSecret": "a1b2c3d4e5f6g7h8" - }, - "certificate": { - "fingerprint": "sha256:abcd1234...", - "expiresAt": "2027-05-13T00:00:00.000Z" - }, - "message": "Cuenta creada exitosamente. Guarda clientSecret en lugar seguro." -} -``` - - - El `clientSecret` se muestra **solo una vez**, en la respuesta del signup. Si se pierde, hay que emitir una nueva credencial desde el panel o contactar soporte. - - -## Campos del Request - - - Email de contacto — se convierte en el login (owner) del portal. - - - - Nombre / razón del titular de la cuenta (mínimo 3, máximo 255 caracteres). - - - - Tipo de entidad jurídica mexicana: `SAPI_CV`, `SA_CV` u `OTHER`. `SAPI_CV` y `SA_CV` exigen `razonSocial`. - - - - Razón social. **Obligatoria** cuando `entityType` es `SAPI_CV` (sufijo "S.A.P.I. de C.V.") o `SA_CV` (sufijo "S.A. de C.V."). Opcional para `OTHER`. - - - - RFC del titular (10–20 caracteres). **Opcional en sandbox**: si se omite, se genera automáticamente un RFC de prueba único. - - - - Teléfono en formato E.164 (8–20 caracteres). Ej.: `+5215512345678`. - - - - Default **`true`** → cuenta sandbox self-service (provider `sandbox`, transacciones simuladas). - `false` → cuenta de producción (provider `smartfastpay`) — **no** es self-service; requiere onboarding con KYC por el equipo. - - - - **Deprecado** — aceptado pero ignorado por el backend (el tipo de documento es siempre RFC). La clasificación jurídica viene de `entityType`. - - - - **Deprecado** — aceptado pero ignorado por el backend. Usa `entityType`. - - -## Sandbox vs Producción - -| Aspecto | Sandbox | Producción | -|---|---|---| -| Provider | `sandbox` | `smartfastpay` | -| Confirmación SPEI | Inmediata (simulada) | Real (segundos a minutos vía Banxico) | -| Costo | Gratuito | Tarifas en producción | -| Límites | Permisivos | Según contrato | -| Endpoint base | `https://sandbox.mx.ntxpay.com` | Provista en el onboarding | - -## Errores Comunes - -| Código | Causa | -|---|---| -| `400` | Falta un campo obligatorio (`email`/`holderName`/`entityType`), falta `razonSocial` para `SAPI_CV`/`SA_CV`, RFC inválido, o tax ID ya en uso | -| `502` | `account-ms` (provisión) no disponible — reintentar | - -## Próximos Pasos - - - - Usa el clientId/clientSecret recién emitidos para generar el JWT - - - Buenas prácticas para tests en ambiente sandbox - - diff --git a/es/guides/spei-cash-out.mdx b/es/guides/spei-cash-out.mdx index 1cbce69..aef1cd8 100644 --- a/es/guides/spei-cash-out.mdx +++ b/es/guides/spei-cash-out.mdx @@ -5,7 +5,7 @@ description: 'Envía transferencias SPEI a cualquier CLABE' ## Visión General -El **SPEI cash-out** envía una transferencia interbancaria a una **CLABE de destino**. El saldo de la cuenta se debita y NTX Pay reenvía al provider (`smartfastpay` en producción, `sandbox` en testing). La confirmación llega vía webhook `cash_out`. +El **SPEI cash-out** envía una transferencia interbancaria a una **CLABE de destino**. El saldo de la cuenta se debita y NTX Pay procesa la transferencia sobre la red SPEI. La confirmación llega vía webhook `cash_out`. ## Endpoint @@ -89,7 +89,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `PENDING` | Cash-out aceptado, esperando liquidación SPEI | | `CONFIRMED` | Liquidado en Banxico | -| `FAILED` | Rechazado por el provider o por la red SPEI | +| `FAILED` | Rechazado por la red SPEI | ## Códigos de Error @@ -97,7 +97,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `400` | Saldo insuficiente, CLABE inválida, payload inválido | | `401` | Token inválido | -| `502` | mexico-ms / provider no disponible — no reenvíes sin checar status en `GET /api/transactions` | +| `502` | Servicio temporalmente no disponible — no reenvíes sin checar status en `GET /api/transactions` | ## Ejemplo Node.js con Retry @@ -126,7 +126,4 @@ async function speiCashOut(token: string, dto: any) { Detalles del payload del webhook de liquidación - - Verifica status sin depender de webhook - diff --git a/es/guides/transactions-list.mdx b/es/guides/transactions-list.mdx deleted file mode 100644 index 7211983..0000000 --- a/es/guides/transactions-list.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: 'Listar Transacciones' -description: 'Consulta el historial SPEI de tu cuenta' ---- - -## Visión General - -`GET /api/transactions` retorna la lista paginada de transacciones **SPEI** de la cuenta autenticada (cash-in, cash-out, refund-in, refund-out, internal_transfer). Es la fuente de verdad cuando necesitas **reconciliar** o consultar el status sin depender de webhooks. - - - **Rate limit**: 30 requests por minuto, por cuenta. Por encima de eso, `429`. - - -## Endpoint - -### GET /api/transactions - -#### Headers - -``` -Authorization: Bearer {token} -``` - -#### Query Parameters - -| Parámetro | Tipo | Default | Descripción | -|---|---|---|---| -| `limit` | int (1–100) | 20 | Cantidad por página | -| `offset` | int (≥0) | 0 | Offset para paginación | -| `status` | enum | — | `PENDING`, `CONFIRMED`, `FAILED`, `EXPIRED` | -| `paymentMethod` | enum | — | `SPEI` | -| `direction` | enum | — | `in` (recibido), `out` (enviado) | - -#### Request - -```bash -curl -X GET "https://sandbox.mx.ntxpay.com/api/transactions?status=CONFIRMED&paymentMethod=SPEI&limit=50" \ - -H "Authorization: Bearer $TOKEN" -``` - -#### Response (200) - -```json -{ - "data": [ - { - "id": 12345, - "externalId": "order-abc-123", - "paymentMethod": "SPEI", - "direction": "in", - "type": "cash_in", - "status": "CONFIRMED", - "provider": "smartfastpay", - "amountCentavos": 50000, - "clabe": "012180001234567890", - "createdAt": "2026-05-12T14:30:00.000Z", - "confirmedAt": "2026-05-12T14:31:05.000Z" - } - ], - "metadata": { - "total": 142, - "limit": 20, - "offset": 0, - "hasMore": true - } -} -``` - -## Paginación - -Itera usando `offset` hasta que `hasMore` sea `false`: - -```typescript -let offset = 0; -const limit = 50; - -while (true) { - const { data } = await axios.get('https://sandbox.mx.ntxpay.com/api/transactions', { - headers: { Authorization: `Bearer ${token}` }, - params: { limit, offset, status: 'CONFIRMED' }, - }); - - for (const tx of data.data) { - await procesar(tx); - } - - if (!data.metadata.hasMore) break; - offset += limit; -} -``` - -## Conciliación Diaria - -Patrón recomendado para cierre diario: - -1. Lista transacciones `CONFIRMED` del día (idealmente filtrando por `createdAt` en tu lado tras buscar) -2. Cruza cada `externalId` con el pedido correspondiente en tu sistema -3. Marca pendientes/divergencias para investigación - -## Rate Limit - -`AccountThrottlerGuard` aplica límite **por cuenta** (no por IP). Excediendo: - -```json -HTTP 429 Too Many Requests -{ "message": "ThrottlerException: Too Many Requests" } -``` - -Espera unos segundos antes de reintentar. En rutinas batch, usa `limit=100` para reducir el número de llamadas. - -## Códigos de Respuesta - -| Código | Significado | -|---|---| -| `200` | Lista retornada | -| `400` | Parámetros inválidos (ej.: `limit > 100`) | -| `401` | Token inválido | -| `429` | Rate limit excedido | -| `502` | mexico-ms no disponible | diff --git a/es/guides/webhooks/cash-in.mdx b/es/guides/webhooks/cash-in.mdx index b2c6b57..5255b05 100644 --- a/es/guides/webhooks/cash-in.mdx +++ b/es/guides/webhooks/cash-in.mdx @@ -23,7 +23,6 @@ El evento `cash_in` se dispara cuando: "direction": "in", "type": "cash_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-12T14:30:00.000Z", diff --git a/es/guides/webhooks/cash-out.mdx b/es/guides/webhooks/cash-out.mdx index 6538cfd..9547199 100644 --- a/es/guides/webhooks/cash-out.mdx +++ b/es/guides/webhooks/cash-out.mdx @@ -8,7 +8,7 @@ description: 'Notificación enviada cuando un SPEI cash-out es liquidado o falla El evento `cash_out` se dispara en dos escenarios: - **Éxito** — el SPEI cash-out enviado vía `POST /api/spei/cash-out` fue liquidado en Banxico (`status: CONFIRMED`) -- **Falla** — la red SPEI o el provider rechazó la transferencia (`status: FAILED`) +- **Falla** — la red SPEI rechazó la transferencia (`status: FAILED`) ## Payload (confirmado) @@ -24,7 +24,6 @@ El evento `cash_out` se dispara en dos escenarios: "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-13T12:00:00.000Z", diff --git a/es/guides/webhooks/refund-in.mdx b/es/guides/webhooks/refund-in.mdx index c297b86..a099f79 100644 --- a/es/guides/webhooks/refund-in.mdx +++ b/es/guides/webhooks/refund-in.mdx @@ -27,7 +27,6 @@ Escenarios comunes: "direction": "in", "type": "refund_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T09:14:50.000Z", diff --git a/es/guides/webhooks/refund-out.mdx b/es/guides/webhooks/refund-out.mdx index 2edc3a5..d7c55c1 100644 --- a/es/guides/webhooks/refund-out.mdx +++ b/es/guides/webhooks/refund-out.mdx @@ -26,7 +26,6 @@ Escenarios comunes: "direction": "out", "type": "refund_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T11:44:50.000Z", diff --git a/es/index.mdx b/es/index.mdx index 11e195d..a4947f3 100644 --- a/es/index.mdx +++ b/es/index.mdx @@ -14,7 +14,7 @@ Gateway público para integración con SPEI (transferencias interbancarias insta ## Autenticación -1. `POST /api/signup` crea la cuenta y retorna `clientId` + `clientSecret`. +1. Tus credenciales (`clientId` + `clientSecret`) se entregan en el onboarding. 2. `POST /api/auth/token` con certificado X.509 en el header `X-SSL-Client-Cert` + credenciales retorna un JWT (10 min de validez). El JWT va en `Authorization: Bearer ` en los demás endpoints. @@ -36,13 +36,13 @@ ISO 8601 UTC: `2026-05-12T14:31:05.000Z`. | `401` | Token o certificado inválido | | `404` | Recurso no encontrado | | `429` | Rate limit | -| `502` | Provider downstream no disponible | +| `502` | Servicio temporalmente no disponible | ## Primeros pasos - Signup, token y primera transacción + Token y primera transacción Cash-in y cash-out vía CLABE diff --git a/es/sandbox/authentication.mdx b/es/sandbox/authentication.mdx index 509cd81..47e9a13 100644 --- a/es/sandbox/authentication.mdx +++ b/es/sandbox/authentication.mdx @@ -9,7 +9,7 @@ mode: 'wide' La autenticación de sandbox usa las mismas dos capas que producción: 1. **Certificado X.509 (mTLS)** — entregado por NTX Pay en el onboarding. -2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` recibidos en el signup. +2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` entregados en el onboarding. En conjunto, devuelven un **JWT** (validez de 10 minutos) usado en los demás endpoints como `Authorization: Bearer ...`. diff --git a/es/sandbox/cash-out.mdx b/es/sandbox/cash-out.mdx index 8ab4c27..8c386bf 100644 --- a/es/sandbox/cash-out.mdx +++ b/es/sandbox/cash-out.mdx @@ -25,7 +25,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ "destinationClabe": "012180001234567890", "beneficiaryName": "Maria Lopez", "beneficiaryTaxId": "LOPM850101ABC", - "concept": "Pago a proveedor" + "concept": "Pago de factura" }' ``` @@ -80,7 +80,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ |---|---|---| | `insufficient_funds` | Validar UX cuando tu cliente intenta pagar sin saldo | `FAILED` (`errorCode: INSUFFICIENT_FUNDS`) | | `bad_clabe` | Validar manejo de devolución por CLABE inválida | `RETURNED` (`errorCode: INVALID_CLABE`) | -| `rejected` | Validar rechazo genérico del proveedor/red | `FAILED` | +| `rejected` | Validar rechazo genérico de la red SPEI | `FAILED` | | `returned` | Validar transferencia devuelta por el banco contraparte | `RETURNED` | | `pending_long` | Validar UX de "transferencia en progreso" (~30s) | `CONFIRMED` | | `timeout` / `provider_5xx` | Validar fallas upstream síncronas (`504` / `503`) | — (error síncrono) | diff --git a/es/sandbox/introduction.mdx b/es/sandbox/introduction.mdx index fd381cd..da76540 100644 --- a/es/sandbox/introduction.mdx +++ b/es/sandbox/introduction.mdx @@ -6,7 +6,7 @@ mode: 'wide' ## Qué es -El sandbox de NTX Pay permite que tu integración ejercite **cash-in**, **cash-out**, **refund** y **webhooks** sin mover dinero real. A diferencia de mocks simples, el pipeline contable completo (saldo TigerBeetle, validación de límites, cobro de tarifas, generación de extractos, entrega de webhooks vía outbox) se ejercita intacto. Solo el provider externo (SPEI/Banxico) es simulado. +El sandbox de NTX Pay permite que tu integración ejercite **cash-in**, **cash-out**, **refund** y **webhooks** sin mover dinero real. A diferencia de mocks simples, el pipeline contable completo (saldo TigerBeetle, validación de límites, cobro de tarifas, generación de extractos, entrega de webhooks vía outbox) se ejercita intacto. Solo la liquidación en la red SPEI es simulada. Toda integración con NTX Pay empieza por el sandbox. Los endpoints, payloads y webhooks descritos en esta documentación son los definitivos — cuando producción se habilite para tu empresa, el mismo código funcionará simplemente cambiando las credenciales. @@ -14,7 +14,7 @@ El sandbox de NTX Pay permite que tu integración ejercite **cash-in**, **cash-o ## Cómo activar -Tus credenciales de API son **estructuralmente las mismas** que usarías en producción. La diferencia vive en la cuenta: las cuentas con `mainProvider: "sandbox"` enrutan toda llamada SPEI internamente al simulador NTX. Para crear una cuenta sandbox, contacta a tu Account Manager o escribe a `contact@ntxpay.com` — el onboarding es instantáneo y el KYC es auto-aprobado. +Tus credenciales de API son **estructuralmente las mismas** que usarías en producción. La diferencia vive en la cuenta: las cuentas sandbox enrutan las llamadas SPEI al simulador interno de NTX Pay. Para crear una cuenta sandbox, contacta a tu Account Manager o escribe a `contact@ntxpay.com` — el onboarding es instantáneo y el KYC es auto-aprobado. ## Base URL @@ -37,7 +37,6 @@ Registra tu `webhookUrl` en la cuenta sandbox exactamente como lo harías en pro | Aspecto | Sandbox | Producción | |---|---|---| | Base URL | `https://sandbox.mx.ntxpay.com` | Provista en el onboarding | -| Provider | `sandbox` (simulado) | Banco real (Banxico/SPEI) | | Saldo | Simulado | Fondos reales | | Confirmación SPEI cash-in | Inmediata (~1s) | Real (segundos a minutos) | | `X-Sandbox-Scenario` | Soportado | Rechazado con `400` | diff --git a/es/sandbox/scenarios.mdx b/es/sandbox/scenarios.mdx index 02848b1..af97168 100644 --- a/es/sandbox/scenarios.mdx +++ b/es/sandbox/scenarios.mdx @@ -36,7 +36,7 @@ Devuelven `201 PENDING` de forma síncrona; el estado final llega vía webhook. |---|---|---| | `success` (default) | `CONFIRMED` en ~1s | También se usa cuando no se envía header | | `pending_long` | `CONFIRMED` tras ~30s | Prueba settlement lento | -| `rejected` | `FAILED` | El proveedor / red SPEI rechazó la transferencia | +| `rejected` | `FAILED` | La red SPEI rechazó la transferencia | | `returned` | `RETURNED` | Aceptada y luego devuelta por el banco contraparte | | `insufficient_funds` | `FAILED` con `errorCode: INSUFFICIENT_FUNDS` | **Solo cash-out** | | `bad_clabe` | `RETURNED` con `errorCode: INVALID_CLABE` | **Solo cash-out** — aceptada y luego devuelta | @@ -48,7 +48,7 @@ Fallan en la propia respuesta HTTP — no se envía webhook. | Header Value | Respuesta síncrona | |---|---| | `timeout` | Timeout upstream (`504`) tras ~16s | -| `provider_5xx` | `503` proveedor no disponible | +| `provider_5xx` | Servicio temporalmente no disponible (`503`) | **Restricciones de cash-in:** `insufficient_funds` y `bad_clabe` no aplican a cash-in (no hay saldo que debitar, y la CLABE de depósito la genera el sistema). Enviar cualquiera de ellos en un cash-in devuelve `400` con código `SCENARIO_NOT_APPLICABLE`. @@ -68,7 +68,6 @@ Fallan en la propia respuesta HTTP — no se envía webhook. "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": "9876543", @@ -100,7 +99,6 @@ Fallan en la propia respuesta HTTP — no se envía webhook. "direction": "out", "type": "cash_out", "status": "FAILED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": null, diff --git a/pt-br/endpoints/signup.mdx b/pt-br/endpoints/signup.mdx deleted file mode 100644 index 4729384..0000000 --- a/pt-br/endpoints/signup.mdx +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: 'Signup' -description: 'Criação de conta NTX Pay México (sandbox ou produção)' -openapi: post /api/signup ---- diff --git a/pt-br/guides/authentication.mdx b/pt-br/guides/authentication.mdx index eb5ccc9..4b1d347 100644 --- a/pt-br/guides/authentication.mdx +++ b/pt-br/guides/authentication.mdx @@ -9,7 +9,7 @@ mode: 'wide' A API NTX Pay México usa autenticação em duas camadas: 1. **Certificado** — entregue pelo NTX Pay no onboarding, comprova a identidade do servidor cliente. -2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` recebidos no signup, validados em conjunto com o certificado. +2. **OAuth 2.0 client_credentials** — `clientId` + `clientSecret` fornecidos no onboarding, validados em conjunto com o certificado. A combinação retorna um **JWT** (validade 10 minutos) usado nos demais endpoints como `Authorization: Bearer ...`. @@ -240,7 +240,7 @@ func getToken() (string, error) { ## Próximos Passos - + Use o header `X-Sandbox-Scenario` para simular sucesso, falha e atraso nos webhooks diff --git a/pt-br/guides/balance.mdx b/pt-br/guides/balance.mdx index c7d6d02..dac98cb 100644 --- a/pt-br/guides/balance.mdx +++ b/pt-br/guides/balance.mdx @@ -46,7 +46,7 @@ curl -X GET https://sandbox.mx.ntxpay.com/api/balance \ - Saldo pendente em centavos MXN. Inclui cash-out em processamento e cash-in aguardando a confirmação final do provedor. + Saldo pendente em centavos MXN. Inclui cash-out em processamento e cash-in aguardando a confirmação final da liquidação. @@ -109,7 +109,4 @@ async function safeSpeiCashOut(amountCentavos: number, token: string, dto: any) Envie uma transferência SPEI usando o saldo disponível - - Veja o histórico de movimentações - diff --git a/pt-br/guides/get-started.mdx b/pt-br/guides/get-started.mdx index 7a897c4..72a4279 100644 --- a/pt-br/guides/get-started.mdx +++ b/pt-br/guides/get-started.mdx @@ -50,9 +50,9 @@ A API NTX Pay México permite que sua empresa realize operações de pagamento, ## Ambiente -| Ambiente | URL | Provider | -|---|---|---| -| Sandbox | `https://sandbox.mx.ntxpay.com` | `sandbox` (transações simuladas) | +| Ambiente | URL | +|---|---| +| Sandbox | `https://sandbox.mx.ntxpay.com` | ## Suporte diff --git a/pt-br/guides/sandbox-testing.mdx b/pt-br/guides/sandbox-testing.mdx deleted file mode 100644 index 46ebbd4..0000000 --- a/pt-br/guides/sandbox-testing.mdx +++ /dev/null @@ -1,214 +0,0 @@ ---- -title: 'Testes em Sandbox' -description: 'Como usar o ambiente sandbox do NTX Pay México para simular cenários SPEI sem custo nem risco.' -mode: 'wide' ---- - -## O que é o Sandbox? - -O sandbox é o ambiente público da NTX Pay México para integração e testes: - -- **Base URL única**: `https://sandbox.mx.ntxpay.com` -- **Provedor bancário simulado** — não toca Banxico nem a rede SPEI real -- **Saldo simulado** — sem movimentação financeira real -- **Webhooks simulados** disparados ~1 segundo após cada request -- **`X-Sandbox-Scenario`** disponível para forçar diferentes resultados nos webhooks - - - Atualmente toda integração com a NTX Pay acontece pelo sandbox. Os endpoints, payloads e webhooks descritos nesta documentação são os definitivos — quando produção for liberada, o mesmo código funcionará apenas trocando as credenciais. - - -## Visão Geral - -- O header `X-Sandbox-Scenario` controla o **resultado do webhook** assíncrono. -- Sem o header, o sandbox devolve webhooks de **sucesso** por padrão. -- Para cenários de erro, **envie o header explicitamente** na request. -- A feature está disponível em **todas** as contas sandbox. - -## Como Funciona - -Na maioria dos cenários o header **não altera a resposta HTTP**: a API responde `201 Created` com `status: "PENDING"` e o cenário afeta o **webhook assíncrono** disparado ~1 segundo depois. As exceções são `timeout` e `provider_5xx`, que falham na própria resposta HTTP síncrona. - -| Request | HTTP Response | Webhook (~1s depois) | -|---|---|---| -| Sem `X-Sandbox-Scenario` | `201 PENDING` | `CONFIRMED` | -| `X-Sandbox-Scenario: success` | `201 PENDING` | `CONFIRMED` | -| `X-Sandbox-Scenario: insufficient_funds` | `201 PENDING` | `FAILED` com `errorCode` (apenas cash-out) | -| `X-Sandbox-Scenario: pending_long` | `201 PENDING` | `CONFIRMED` após ~30s | -| `X-Sandbox-Scenario: provider_5xx` | `503` (síncrono) | — | - -## Como Usar - - - -```bash cURL -curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ - -H "Authorization: Bearer $TOKEN" \ - -H "X-Sandbox-Scenario: insufficient_funds" \ - -H "Content-Type: application/json" \ - -d '{ - "amountCentavos": 15000, - "destinationClabe": "012180001234567890", - "beneficiaryName": "Maria Lopez" - }' -``` - -```javascript JavaScript -const response = await axios.post( - 'https://sandbox.mx.ntxpay.com/api/spei/cash-out', - { - amountCentavos: 15000, - destinationClabe: '012180001234567890', - beneficiaryName: 'Maria Lopez', - }, - { - headers: { - Authorization: `Bearer ${token}`, - 'X-Sandbox-Scenario': 'insufficient_funds', - }, - } -); -``` - -```python Python -response = requests.post( - "https://sandbox.mx.ntxpay.com/api/spei/cash-out", - json={ - "amountCentavos": 15000, - "destinationClabe": "012180001234567890", - "beneficiaryName": "Maria Lopez", - }, - headers={ - "Authorization": f"Bearer {token}", - "X-Sandbox-Scenario": "insufficient_funds", - }, -) -``` - - - -## Cenários Disponíveis - -Valores canônicos: `success`, `pending_long`, `rejected`, `returned`, `insufficient_funds`, `bad_clabe`, `timeout`, `provider_5xx`. - -### Cenários de resultado assíncrono (`201 PENDING` → webhook) - -| Header Value | Descrição | Webhook Status | -|---|---|---| -| `success` _(ou sem header)_ | Comportamento default do sandbox | `CONFIRMED` | -| `pending_long` | Confirma após ~30s (settlement lento) | `CONFIRMED` | -| `rejected` | Provedor / rede SPEI rejeitou | `FAILED` | -| `returned` | Aceita e depois devolvida pelo banco contraparte | `RETURNED` | -| `insufficient_funds` | Conta sem saldo suficiente (**apenas cash-out**) | `FAILED` (`errorCode: INSUFFICIENT_FUNDS`) | -| `bad_clabe` | CLABE inválida (**apenas cash-out**) | `RETURNED` (`errorCode: INVALID_CLABE`) | - -### Cenários de erro síncrono (sem webhook) - -| Header Value | Descrição | HTTP Response | -|---|---|---| -| `timeout` | Timeout upstream após ~16s | `504` | -| `provider_5xx` | Provedor indisponível | `503` | - - - `insufficient_funds` e `bad_clabe` **não se aplicam a cash-in** — enviá-los em um cash-in retorna `400` com código `SCENARIO_NOT_APPLICABLE`. - - -## Exemplos de Webhook Recebido - -### Webhook de Sucesso (default) - -```json -{ - "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": {} -} -``` - -### Webhook de Erro (`insufficient_funds`) - -```json -{ - "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": "Account without sufficient balance", - "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. - -## Endpoints Compatíveis - -| Endpoint | Método | Descrição | -|---|---|---| -| `/api/spei/cash-in` | POST | Gerar CLABE descartável de cobrança | -| `/api/spei/cash-out` | POST | Enviar SPEI por CLABE | - -## Comportamento - -- A API processa a request normalmente: retorna `201 Created` com `status: PENDING`. -- O header **não altera a resposta imediata**. -- Após ~1 segundo (ou mais com `delayed:`), o webhook é enviado para a URL configurada. -- Seu sistema recebe o webhook com `status` correspondente ao cenário (`CONFIRMED` ou `FAILED`). - - - Na maioria dos cenários o header controla **apenas o webhook**, e a resposta HTTP é `201 Created` com `status: PENDING`. As exceções `timeout` (`504`) e `provider_5xx` (`503`) falham na própria resposta síncrona. - - -## Boas Práticas - -1. **Teste todos os cenários** — implemente o tratamento de `CONFIRMED`, `PENDING`, `FAILED` e `EXPIRED` antes de ir ao ar. -2. **Valide os campos de erro** — use `errorCode` e `errorMessage` para tomar a ação adequada (notificar usuário, retry, etc.). -3. **Teste com delay** — verifique se seu sistema lida bem com entrega lenta do webhook. -4. **Idempotência** — use `transaction.id` como chave de idempotência; o mesmo webhook pode ser reenviado. - -## Suporte - -`support@ntxpay.com` diff --git a/pt-br/guides/signup.mdx b/pt-br/guides/signup.mdx deleted file mode 100644 index fd886d2..0000000 --- a/pt-br/guides/signup.mdx +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: 'Signup' -description: 'Criação programática de conta NTX Pay México (sandbox ou produção)' ---- - -## Visão Geral - -O endpoint `POST /api/signup` cria uma nova conta NTX Pay México. **Não requer autenticação** (sem JWT, sem certificado) — é a porta de entrada da integração. - -Na criação, a NTX Pay: - -1. Provisiona a conta no Keycloak (provedor de identidade) -2. Aplica limites e tarifas padrão -3. Define o `mainProvider`: - - `sandbox` se `isSandbox=true` (padrão — transações simuladas, self-service) - - `smartfastpay` caso contrário (produção — **não** é self-service; exige onboarding de KYC com o time) -4. Emite credenciais OAuth 2.0 (`clientId` + `clientSecret`) -5. Opcionalmente emite certificado mTLS - -## Endpoint - -### POST /api/signup - -#### Request — Pessoa física (sandbox) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "maria@example.com", - "holderName": "Maria Lopez", - "entityType": "OTHER", - "phone": "+5215512345678", - "isSandbox": true - }' -``` - - - No sandbox, o `holderTaxIdPrimary` (RFC) é opcional — se omitido, um RFC de teste único é gerado automaticamente. - - -#### Request — Pessoa jurídica (`SA_CV` / `SAPI_CV`) - -```bash -curl -X POST https://sandbox.mx.ntxpay.com/api/signup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "contact@acme.mx", - "holderName": "Acme S.A. de C.V.", - "entityType": "SA_CV", - "razonSocial": "Acme S.A. de C.V.", - "holderTaxIdPrimary": "ACM850101AB1", - "isSandbox": true - }' -``` - -#### Response (201) - -```json -{ - "accountId": 93, - "publicId": "acc_550e8400-e29b-41d4-a716-446655440000", - "mainProvider": "sandbox", - "credentials": { - "clientId": "qr-93-550e8400", - "clientSecret": "a1b2c3d4e5f6g7h8" - }, - "certificate": { - "fingerprint": "sha256:abcd1234...", - "expiresAt": "2027-05-13T00:00:00.000Z" - }, - "message": "Account created successfully. Store clientSecret in a safe place." -} -``` - - - O `clientSecret` é exibido **uma única vez**, na resposta do signup. Se perdido, é necessário emitir uma nova credencial pelo painel ou contatando o suporte. - - -## Campos do Request - - - E-mail de contato — torna-se o login do portal (owner). - - - - Nome / razão social do titular da conta (mínimo 3, máximo 255 caracteres). - - - - Tipo de pessoa jurídica mexicana: `SAPI_CV`, `SA_CV` ou `OTHER`. `SAPI_CV` e `SA_CV` exigem `razonSocial`. - - - - Razão social. **Obrigatório** quando `entityType` é `SAPI_CV` (sufixo "S.A.P.I. de C.V.") ou `SA_CV` (sufixo "S.A. de C.V."). Opcional para `OTHER`. - - - - RFC do titular (10–20 caracteres). **Opcional no sandbox**: se omitido, um RFC de teste único é gerado automaticamente. - - - - Telefone no formato E.164 (8–20 caracteres). Ex.: `+5215512345678`. - - - - Padrão **`true`** → conta sandbox self-service (provider `sandbox`, transações simuladas). - `false` → conta de produção (provider `smartfastpay`) — **não** é self-service; exige onboarding de KYC com o time. - - - - **Deprecado** — aceito mas ignorado pelo backend (o tipo de documento é sempre RFC). A classificação legal vem de `entityType`. - - - - **Deprecado** — aceito mas ignorado pelo backend. Use `entityType` no lugar. - - -## Sandbox vs Produção - -| Aspecto | Sandbox | Produção | -|---|---|---| -| Provider | `sandbox` | `smartfastpay` | -| Confirmação SPEI | Imediata (simulada) | Real (segundos a minutos via Banxico) | -| Custo | Gratuito | Tarifas em produção | -| Limites | Permissivos | Por contrato | -| Endpoint base | `https://sandbox.mx.ntxpay.com` | Fornecido no onboarding | - -## Erros Comuns - -| Código | Causa | -|---|---| -| `400` | Campo obrigatório ausente (`email`/`holderName`/`entityType`), `razonSocial` ausente para `SAPI_CV`/`SA_CV`, RFC inválido, ou tax ID já em uso | -| `502` | `account-ms` (provisionamento) indisponível — tente novamente | - -## Próximos Passos - - - - Use o clientId/clientSecret recém-emitidos para gerar o JWT - - - Boas práticas para testar no sandbox - - diff --git a/pt-br/guides/spei-cash-out.mdx b/pt-br/guides/spei-cash-out.mdx index 7b2e58f..6ac3300 100644 --- a/pt-br/guides/spei-cash-out.mdx +++ b/pt-br/guides/spei-cash-out.mdx @@ -5,7 +5,7 @@ description: 'Envie transferências SPEI para qualquer CLABE' ## Visão Geral -O **cash-out SPEI** envia uma transferência interbancária para uma **CLABE de destino**. O saldo da conta é debitado e a NTX Pay encaminha ao provedor (`smartfastpay` em produção, `sandbox` para testes). A confirmação chega via webhook `cash_out`. +O **cash-out SPEI** envia uma transferência interbancária para uma **CLABE de destino**. O saldo da conta é debitado e a NTX Pay processa a transferência na rede SPEI. A confirmação chega via webhook `cash_out`. ## Endpoint @@ -89,7 +89,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `PENDING` | Cash-out aceito, aguardando liquidação SPEI | | `CONFIRMED` | Liquidado no Banxico | -| `FAILED` | Rejeitado pelo provedor ou pela rede SPEI | +| `FAILED` | Rejeitado pela rede SPEI | ## Códigos de Erro @@ -97,7 +97,7 @@ if (balance.availableCentavos < amountCentavos) { |---|---| | `400` | Saldo insuficiente, CLABE inválida, payload inválido | | `401` | Token inválido | -| `502` | mexico-ms / provedor indisponível — não tente novamente sem verificar o status via `GET /api/transactions` | +| `502` | Falha temporária no processamento — não tente novamente sem verificar o status via `GET /api/transactions` | ## Exemplo em Node.js com Retry @@ -126,7 +126,4 @@ async function speiCashOut(token: string, dto: any) { Detalhes do payload do webhook de liquidação - - Verifique o status sem depender do webhook - diff --git a/pt-br/guides/transactions-list.mdx b/pt-br/guides/transactions-list.mdx deleted file mode 100644 index 65a2aa9..0000000 --- a/pt-br/guides/transactions-list.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: 'Listar Transações' -description: 'Consulte o histórico SPEI da sua conta' ---- - -## Visão Geral - -`GET /api/transactions` retorna a lista paginada de transações da conta autenticada, cobrindo **SPEI** (cash-in, cash-out, refund-in, refund-out, internal_transfer). É a fonte da verdade quando você precisa **reconciliar** ou verificar status sem depender de webhooks. - - - **Rate limit**: 30 requisições por minuto, por conta. Acima disso, `429`. - - -## Endpoint - -### GET /api/transactions - -#### Headers - -``` -Authorization: Bearer {token} -``` - -#### Query Parameters - -| Parâmetro | Tipo | Padrão | Descrição | -|---|---|---|---| -| `limit` | int (1–100) | 20 | Itens por página | -| `offset` | int (≥0) | 0 | Offset de paginação | -| `status` | enum | — | `PENDING`, `CONFIRMED`, `FAILED`, `EXPIRED` | -| `paymentMethod` | enum | — | `SPEI` | -| `direction` | enum | — | `in` (recebido), `out` (enviado) | - -#### Request - -```bash -curl -X GET "https://sandbox.mx.ntxpay.com/api/transactions?status=CONFIRMED&paymentMethod=SPEI&limit=50" \ - -H "Authorization: Bearer $TOKEN" -``` - -#### Response (200) - -```json -{ - "data": [ - { - "id": 12345, - "externalId": "order-abc-123", - "paymentMethod": "SPEI", - "direction": "in", - "type": "cash_in", - "status": "CONFIRMED", - "provider": "smartfastpay", - "amountCentavos": 50000, - "clabe": "012180001234567890", - "createdAt": "2026-05-12T14:30:00.000Z", - "confirmedAt": "2026-05-12T14:31:05.000Z" - } - ], - "metadata": { - "total": 142, - "limit": 20, - "offset": 0, - "hasMore": true - } -} -``` - -## Paginação - -Itere usando `offset` até `hasMore` ser `false`: - -```typescript -let offset = 0; -const limit = 50; - -while (true) { - const { data } = await axios.get('https://sandbox.mx.ntxpay.com/api/transactions', { - headers: { Authorization: `Bearer ${token}` }, - params: { limit, offset, status: 'CONFIRMED' }, - }); - - for (const tx of data.data) { - await process(tx); - } - - if (!data.metadata.hasMore) break; - offset += limit; -} -``` - -## Reconciliação Diária - -Padrão recomendado para o fechamento diário: - -1. Liste as transações `CONFIRMED` do dia (idealmente filtrando por `createdAt` no seu lado após o fetch) -2. Cruze cada `externalId` com o pedido correspondente no seu sistema -3. Sinalize pendências/divergências para investigação - -## Rate Limit - -O `AccountThrottlerGuard` aplica um limite **por conta** (não por IP). Ao exceder: - -```json -HTTP 429 Too Many Requests -{ "message": "ThrottlerException: Too Many Requests" } -``` - -Aguarde alguns segundos antes de tentar novamente. Em rotinas em lote, use `limit=100` para reduzir o número de chamadas. - -## Códigos de Resposta - -| Código | Significado | -|---|---| -| `200` | Lista retornada | -| `400` | Parâmetros inválidos (ex.: `limit > 100`) | -| `401` | Token inválido | -| `429` | Rate limit excedido | -| `502` | mexico-ms indisponível | diff --git a/pt-br/guides/webhooks/cash-in.mdx b/pt-br/guides/webhooks/cash-in.mdx index 3127cbf..4cb45be 100644 --- a/pt-br/guides/webhooks/cash-in.mdx +++ b/pt-br/guides/webhooks/cash-in.mdx @@ -24,7 +24,6 @@ O evento `cash_in` é disparado quando: "direction": "in", "type": "cash_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-12T14:30:00.000Z", diff --git a/pt-br/guides/webhooks/cash-out.mdx b/pt-br/guides/webhooks/cash-out.mdx index b36f99b..129c3fc 100644 --- a/pt-br/guides/webhooks/cash-out.mdx +++ b/pt-br/guides/webhooks/cash-out.mdx @@ -9,7 +9,7 @@ mode: 'wide' O evento `cash_out` é disparado em dois cenários: - **Sucesso** — o SPEI cash-out enviado via `POST /api/spei/cash-out` foi liquidado no Banxico (`status: CONFIRMED`) -- **Falha** — a rede SPEI ou o provider rejeitou a transferência (`status: FAILED`) +- **Falha** — a rede SPEI rejeitou a transferência (`status: FAILED`) ## Payload (confirmado) @@ -25,7 +25,6 @@ O evento `cash_out` é disparado em dois cenários: "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-13T12:00:00.000Z", diff --git a/pt-br/guides/webhooks/refund-in.mdx b/pt-br/guides/webhooks/refund-in.mdx index d8b8ab2..a314616 100644 --- a/pt-br/guides/webhooks/refund-in.mdx +++ b/pt-br/guides/webhooks/refund-in.mdx @@ -28,7 +28,6 @@ Cenários comuns: "direction": "in", "type": "refund_in", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T09:14:50.000Z", diff --git a/pt-br/guides/webhooks/refund-out.mdx b/pt-br/guides/webhooks/refund-out.mdx index 2bd0e4b..c20748e 100644 --- a/pt-br/guides/webhooks/refund-out.mdx +++ b/pt-br/guides/webhooks/refund-out.mdx @@ -27,7 +27,6 @@ Cenários comuns: "direction": "out", "type": "refund_out", "status": "CONFIRMED", - "provider": "smartfastpay", "amountCentavos": 50000, "clabe": "012180001234567890", "createdAt": "2026-05-14T11:44:50.000Z", diff --git a/pt-br/guides/webhooks/setup.mdx b/pt-br/guides/webhooks/setup.mdx index d3be1d3..ba5f77c 100644 --- a/pt-br/guides/webhooks/setup.mdx +++ b/pt-br/guides/webhooks/setup.mdx @@ -111,7 +111,7 @@ Cada webhook assina exatamente um evento, então configure **um webhook por tipo Antes de liberar o webhook para receber tráfego de verdade, valide seu endpoint: 1. Use [webhook.site](https://webhook.site) ou [ngrok](https://ngrok.com) para inspecionar o tráfego -2. Dispare cobranças com `X-Sandbox-Scenario` (veja [Testes em Sandbox](/pt-br/guides/sandbox-testing)) +2. Dispare cobranças com `X-Sandbox-Scenario` (veja [Cenários de Sandbox](/pt-br/sandbox/scenarios)) 3. Confira que sua aplicação: - Valida `X-NTXPay-Signature` corretamente - Retorna `200` em menos de 10 segundos diff --git a/pt-br/index.mdx b/pt-br/index.mdx index 309b044..54161cb 100644 --- a/pt-br/index.mdx +++ b/pt-br/index.mdx @@ -14,7 +14,7 @@ Gateway público para integração com SPEI (transferências interbancárias ins ## Autenticação -1. `POST /api/signup` cria a conta e retorna `clientId` + `clientSecret`. +1. Suas credenciais (`clientId` + `clientSecret`) são fornecidas no onboarding. 2. `POST /api/auth/token` com certificado X.509 no header `X-SSL-Client-Cert` + credenciais retorna um JWT (validade de 10 min). O JWT vai em `Authorization: Bearer ` nos demais endpoints. @@ -36,13 +36,13 @@ ISO 8601 UTC: `2026-05-12T14:31:05.000Z`. | `401` | Token ou certificado inválido | | `404` | Recurso não encontrado | | `429` | Rate limit | -| `502` | Provedor downstream indisponível | +| `502` | Falha temporária no processamento | ## Primeiros passos - Signup, token e primeira transação + Token e primeira transação Cash-in e cash-out via CLABE diff --git a/pt-br/sandbox/authentication.mdx b/pt-br/sandbox/authentication.mdx index 5831584..9a3a6ad 100644 --- a/pt-br/sandbox/authentication.mdx +++ b/pt-br/sandbox/authentication.mdx @@ -9,7 +9,7 @@ mode: 'wide' A autenticação em sandbox usa as mesmas duas camadas que produção: 1. **Certificado X.509 (mTLS)** — entregue pelo NTX Pay no onboarding. -2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` recebidos no signup. +2. **OAuth 2.0 `client_credentials`** — `clientId` + `clientSecret` fornecidos no onboarding. Em conjunto, retornam um **JWT** (validade 10 minutos) usado nos demais endpoints como `Authorization: Bearer ...`. diff --git a/pt-br/sandbox/cash-out.mdx b/pt-br/sandbox/cash-out.mdx index 6726aef..4dc2aec 100644 --- a/pt-br/sandbox/cash-out.mdx +++ b/pt-br/sandbox/cash-out.mdx @@ -25,7 +25,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ "destinationClabe": "012180001234567890", "beneficiaryName": "Maria Lopez", "beneficiaryTaxId": "LOPM850101ABC", - "concept": "Pagamento de fornecedor" + "concept": "Pagamento de fatura" }' ``` @@ -80,7 +80,7 @@ curl -X POST https://sandbox.mx.ntxpay.com/api/spei/cash-out \ |---|---|---| | `insufficient_funds` | Validar UX quando seu cliente tenta pagar sem saldo | `FAILED` (`errorCode: INSUFFICIENT_FUNDS`) | | `bad_clabe` | Validar tratamento de devolução por CLABE inválida | `RETURNED` (`errorCode: INVALID_CLABE`) | -| `rejected` | Validar rejeição genérica do provedor/rede | `FAILED` | +| `rejected` | Validar rejeição genérica da rede SPEI | `FAILED` | | `returned` | Validar transferência estornada pelo banco contraparte | `RETURNED` | | `pending_long` | Validar UX de "transferência em andamento" (~30s) | `CONFIRMED` | | `timeout` / `provider_5xx` | Validar falhas upstream síncronas (`504` / `503`) | — (erro síncrono) | diff --git a/pt-br/sandbox/introduction.mdx b/pt-br/sandbox/introduction.mdx index 5fe3dc4..121c745 100644 --- a/pt-br/sandbox/introduction.mdx +++ b/pt-br/sandbox/introduction.mdx @@ -6,7 +6,7 @@ mode: 'wide' ## O que é -O sandbox NTX Pay permite que sua integração exercite **cash-in**, **cash-out**, **refund** e **webhooks** sem mover dinheiro real. Diferente de mocks simplistas, o pipeline contábil completo (saldo TigerBeetle, validação de limites, cobrança de tarifas, geração de extratos, entrega de webhooks via outbox) é exercitado intacto. Apenas o provider externo (SPEI/Banxico) é simulado. +O sandbox NTX Pay permite que sua integração exercite **cash-in**, **cash-out**, **refund** e **webhooks** sem mover dinheiro real. Diferente de mocks simplistas, o pipeline contábil completo (saldo TigerBeetle, validação de limites, cobrança de tarifas, geração de extratos, entrega de webhooks via outbox) é exercitado intacto. Apenas a liquidação na rede SPEI é simulada. Toda integração com a NTX Pay começa pelo sandbox. Os endpoints, payloads e webhooks descritos nesta documentação são os definitivos — quando produção for liberada para a sua empresa, o mesmo código funcionará apenas trocando as credenciais. @@ -14,7 +14,7 @@ O sandbox NTX Pay permite que sua integração exercite **cash-in**, **cash-out* ## Como ativar -Suas credenciais de API são as **mesmas estruturalmente** que você usaria em produção. A diferença vive na conta: contas com `mainProvider: "sandbox"` roteiam todas as chamadas SPEI internamente para o simulador NTX. Para criar uma conta sandbox, peça ao seu Account Manager ou escreva para `contact@ntxpay.com` — o onboarding é instantâneo e o KYC é auto-aprovado. +Suas credenciais de API são as **mesmas estruturalmente** que você usaria em produção. A diferença vive na conta: contas sandbox roteiam as chamadas SPEI para o simulador interno da NTX Pay. Para criar uma conta sandbox, peça ao seu Account Manager ou escreva para `contact@ntxpay.com` — o onboarding é instantâneo e o KYC é auto-aprovado. ## Base URL @@ -37,7 +37,6 @@ Registre seu `webhookUrl` na conta sandbox exatamente como faria em produção | Aspecto | Sandbox | Produção | |---|---|---| | Base URL | `https://sandbox.mx.ntxpay.com` | Fornecida no onboarding | -| Provider | `sandbox` (simulado) | Banco real (Banxico/SPEI) | | Saldo | Simulado | Fundos reais | | Confirmação SPEI cash-in | Imediata (~1s) | Real (segundos a minutos) | | `X-Sandbox-Scenario` | Suportado | Rejeitado com `400` | diff --git a/pt-br/sandbox/scenarios.mdx b/pt-br/sandbox/scenarios.mdx index a85fcb5..98de565 100644 --- a/pt-br/sandbox/scenarios.mdx +++ b/pt-br/sandbox/scenarios.mdx @@ -36,7 +36,7 @@ Retornam `201 PENDING` de forma síncrona; o estado final chega via webhook. |---|---|---| | `success` (default) | `CONFIRMED` em ~1s | Também usado quando nenhum header é enviado | | `pending_long` | `CONFIRMED` após ~30s | Testa settlement lento | -| `rejected` | `FAILED` | Provedor / rede SPEI rejeitou a transferência | +| `rejected` | `FAILED` | A rede SPEI rejeitou a transferência | | `returned` | `RETURNED` | Aceita e depois devolvida pelo banco contraparte | | `insufficient_funds` | `FAILED` com `errorCode: INSUFFICIENT_FUNDS` | **Apenas cash-out** | | `bad_clabe` | `RETURNED` com `errorCode: INVALID_CLABE` | **Apenas cash-out** — aceita e depois devolvida | @@ -48,7 +48,7 @@ Falham na própria resposta HTTP — nenhum webhook é enviado. | Header Value | Resposta síncrona | |---|---| | `timeout` | Timeout upstream (`504`) após ~16s | -| `provider_5xx` | `503` provedor indisponível | +| `provider_5xx` | Serviço temporariamente indisponível (`503`) | **Restrições de cash-in:** `insufficient_funds` e `bad_clabe` não se aplicam a cash-in (não há saldo a debitar, e a CLABE de depósito é gerada pelo sistema). Enviar qualquer um deles em um cash-in retorna `400` com código `SCENARIO_NOT_APPLICABLE`. @@ -68,7 +68,6 @@ Falham na própria resposta HTTP — nenhum webhook é enviado. "direction": "out", "type": "cash_out", "status": "CONFIRMED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": "9876543", @@ -100,7 +99,6 @@ Falham na própria resposta HTTP — nenhum webhook é enviado. "direction": "out", "type": "cash_out", "status": "FAILED", - "provider": "sandbox", "amountCentavos": 15000, "clabe": "012180001234567890", "referenceNumerical": null,