# Cuenta de prueba

Tu ambiente propio con datos ficticios, escenarios y webhooks simulados.

La cuenta de prueba es un ambiente por empresa con el mismo contrato que producción: guarda estado, aplica idempotencia real y entrega webhooks firmados. El dinero y los bancos no existen ahí. Toda respuesta JSON lleva `livemode: false`. Para empezar, sigue el [inicio rápido](/docs/sandbox/inicio-rapido/).

## Crear la llave de prueba

El panel está en [merchants.fital.xyz](https://merchants.fital.xyz): entran las empresas con KYB aprobado en [empresa.fital.xyz](https://empresa.fital.xyz). Si tu empresa aún no tiene cuenta, regístrala ahí y completa el KYB. Con KYB aprobado, entras y creas tu llave `sk_test_fital_…`. Es automático. Sin KYB aprobado la respuesta es `403 kyb_required`, sin vía manual. La llave y su secreto de firma se muestran una sola vez, y la llave caduca a los 90 días.

Al revocar una llave de prueba, las escrituras se rechazan al instante; una lectura puede seguir pasando hasta 30 segundos.

## Hacer un pago ficticio

No hay botón de pago en el panel. Usa las muestras del [inicio rápido](/docs/sandbox/inicio-rapido/), o el script para Node 22 de la pantalla Sandbox, que ya trae el beneficiario de prueba. Así pruebas también la firma de la petición.

En unos 30 segundos el pago termina y llega `payment.completed` a tu destino. Lo ves en las pantallas Webhooks y Registros de API.

## Qué se simula

Sólo SPEI en MXN:

- **Beneficiarios:** `rail` debe ser `mxn_spei`, la CLABE debe empezar con `999` y el titular debe incluir la palabra `FICTICIO`. Otro riel responde `403 rail_not_enabled`. Una CLABE o un titular reales responden `422 sandbox_real_account_rejected`.
- **Cobros:** con el método `spei`, que pide `firstName`, `lastName` y `email` en `payer`, igual que dice `payer_fields`, y con `efectivo`, que no pide nada de quien paga y responde una referencia ficticia. Sin esos campos, `spei` responde `400 invalid_request`. Otro método responde `422 method_unavailable`. La cuenta de prueba simula `efectivo` aunque tu empresa aún no lo haya pedido a FITAL para producción.
- **Catálogo `latam`:** [`GET /sandbox/v1/latam/countries`](/docs/operaciones/listar-paises-latam/) responde países ficticios con `available: false`, y [`GET /sandbox/v1/latam/countries/{country}/entities`](/docs/operaciones/listar-bancos-latam/) un banco ficticio. Sirven para leer la forma de la respuesta: el alta `latam` no procede aquí.
- **Saldos:** ficticios, en MXN y USD. El saldo USD sólo se ve: un pago o una cotización en otra moneda que no sea MXN responde `422 currency_not_supported`.
- **Wallets:** dos ficticias, en `base` y `solana`. Salen del mismo saldo ficticio: `MXN` no vive en una wallet.
- **Cuentas para recibir:** [`POST /sandbox/v1/receiving-accounts`](/docs/operaciones/abrir-cuenta-para-recibir/) abre cuentas ficticias que no reciben dinero. Abre en `USD`, `EUR`, `BRL`, `GBP` y `COP` sin pedir activación.
- **Direcciones de depósito:** son ficticias y no reciben dinero.
- **Cotizaciones:** con tipo de cambio ficticio. Si el débito supera `max_source_amount`, el pago responde `409 quote_changed`, sin efecto, igual que en producción.

## Datos ficticios incluidos

La cuenta nace con saldo ficticio y beneficiarios ficticios, cada uno con un escenario asignado; los ves en la pantalla Sandbox. Ningún dato se copia de producción.

## Escenarios

`X-Fital-Scenario` manda sobre el escenario del beneficiario. Sin ninguno de los dos, el pago sigue el camino feliz. Ver la lista en [Ambientes](/docs/ambientes/#escenarios).

| Caso | Cuánto tarda |
|---|---|
| Pago que termina, falla o se devuelve | Unos 30 segundos hasta su primer resultado; una devolución llega 2 minutos después |
| Pago en revisión | 2 minutos |
| Pago sin confirmar (`payment_uncertain`) | 5 minutos. Mientras tanto, otro pago de tu empresa responde `409 payment_in_flight`. Con `advance` lo terminas antes |
| Pago retenido (`payment_held`) | 20 segundos antes de poder repetir con la misma clave |
| Cobro pagado o vencido, y depósito recibido | 30 segundos |

Estos tiempos no anticipan los de producción.

## Avanzar un pago

[`POST /sandbox/v1/payments/{id}/advance`](/docs/operaciones/avanzar-pago-de-prueba/) lleva un pago a `completed`, `failed`, `returned` o `in_review` sin esperar, y emite su evento firmado. Exige `Idempotency-Key` y firma. Sigue las reglas de un pago real: una transición imposible responde `409 sandbox_invalid_transition`. Esta ruta no existe en producción.

## Webhooks simulados

[`POST /sandbox/v1/webhooks/trigger`](/docs/operaciones/emitir-evento-de-prueba/) emite un evento firmado a tus destinos de prueba, con los mismos encabezados y el mismo calendario de reintentos que producción. `data` tiene la forma real de su tipo, con datos ficticios, más `simulated: true` y `livemode: false`. Los destinos se dan de alta en el panel y sólo aceptan HTTPS público. Esta ruta tampoco existe en producción. El contrato de este ambiente, con estas dos rutas, está en [`openapi.sandbox.json`](/docs/openapi.sandbox.json). Para probar en tu máquina usa el [inicio rápido de webhooks](/docs/webhooks/inicio-rapido/).

Un pago de prueba no se reabre. Para practicar ese retroceso, emite `payment.canceled` y después `payment.processing` con el mismo `resource_id`: `sequence` crece por recurso.

Cada destino recibe hasta 2 entregas simultáneas, y la cola guarda hasta 500 pendientes por destino y 1,500 por empresa. Lo que no cabe queda `skipped`, sin entrega: el evento sigue en [`GET /sandbox/v1/events`](/docs/operaciones/listar-eventos/).

[`GET /sandbox/v1/meta/egress-ips`](/docs/operaciones/consultar-ip-de-salida/) responde una lista vacía: este ambiente no publica IP de salida. La [lista de producción](/docs/seguridad/ip-webhooks/) no aplica aquí.

## Reinicio de datos

Desde el panel. Borra los datos de tu empresa y restaura la semilla; conserva llaves y destinos. Hasta 5 veces al día.

## Límites

| Límite | Valor |
|---|---|
| Peticiones | 5 por segundo por llave, ráfaga de 10; lecturas y escrituras igual |
| Por IP | 10 por segundo, ráfaga de 20 |
| Pagos y cobros | 100 al día; después, `429 sandbox_limit` |
| Beneficiarios | 20 |
| Destinos de webhook | 3 |
| Monto por pago | 1,000,000 ficticios; más responde `422 limit_exceeded` |
| Eventos guardados | 10,000 por empresa: los más viejos se borran, sin error |
| Datos sin actividad | Se borran a los 30 días y el siguiente uso restaura la semilla. Llaves y destinos no se tocan |

## Salud

[`GET /sandbox/v1/health`](/docs/operaciones/consultar-salud/) mide sólo este ambiente, no producción. Ver [Salud y estado](/docs/salud-y-estado/).

## Qué no prueba este ambiente

Tiempos reales de cada banco, comisiones y tipos de cambio reales, otros rieles, ni la duración de una revisión de cumplimiento.

Aquí una `Idempotency-Key` vencida se borra: pasados 7 días, otro cuerpo con esa clave ya no responde `422 idempotency_key_reused`, como sí en producción.

Tampoco prueba una lectura de producción: un pago en curso siempre responde `freshness.status` en `current`.

## Errores comunes

- `401 wrong_environment`: usar aquí una llave de otro ambiente, como `sk_live_fital_…` o la llave pública del simulador.
- `sandbox_real_account_rejected`, `sandbox_limit` y `sandbox_invalid_transition`: ver [Errores](/docs/errores/).
- `401 invalid_signature`: firmar la ruta con el prefijo `/sandbox`. Se firma siempre `/v1/...`. Ver [Autenticación](/docs/autenticacion/#firma-de-petición).

## Qué sigue

[Lista para producción](/docs/produccion/).
