# Pruebas y stubs

Cada operación es atendida por un stub (un endpoint simulado) que devuelve
**el propio ejemplo canónico de la especificación**. Los cuerpos de los stubs
y los ejemplos documentados son exactamente los mismos bytes. Un solo host,
dos prefijos de ruta:

| | |
| --- | --- |
| [Endpoints de Nexa expuestos a Tesser](/api-nexa) | `https://nexa-poc-main-c82e5ac.zuplo.app/nexa/v1/...` |
| [Endpoints de Tesser expuestos a Nexa](/api-tesser) | `https://nexa-poc-main-c82e5ac.zuplo.app/tesser/v1/...` |

Ese host ya viene seleccionado en cada referencia de la API, así que los
ejemplos de `curl` que se copian y pegan ahí apuntan directamente a él.

Para ejercitar el flujo completo con un solo comando, se recomienda usar la
[prueba de extremo a extremo](/es/e2e-test).

## Lo que los stubs no son

- **Con estado.** No se exige ningún orden de operaciones. Se puede reportar
  un depósito contra una cotización que nunca se creó y el stub responderá
  sin problema.
- **Autenticados.** No hay mTLS ni claves de API. El
  [modelo de autenticación real](/es/authentication) aplica a las
  implementaciones reales, no al host de stubs.
- **Variables.** Las respuestas son siempre el ejemplo canónico, con los
  montos del ejemplo trabajado: `250000.00` GTQ a `7.745100` GTQ/USDC =
  `32278.472841` USDC.

Existen para que ambos equipos puedan escribir y ejecutar código cliente
contra un endpoint HTTP real antes de que cualquiera de las dos partes tenga
una implementación. No son un simulador.

## Id mágico de error

**Un id que termina en `dead` hace que el stub devuelva el error principal de
esa operación** en lugar del camino feliz. Hay una única variante de error
preparada por operación: la que muestra su ejemplo de error en la referencia
de la API.

El valor canónico es `9b2f6c1e-0000-4000-8000-00000000dead`. Se usa como
`tesser_quote_id` en las operaciones de cotización, depósito y pago, o como
`nexa_payment_id` en [consultar pago](/api-nexa/payments#get-payment-optional-op-9)
<N />.

Todos los demás errores que se listan abajo están documentados y tienen
esquema definido en las referencias de la API, pero desde un stub solo se
puede alcanzar el error principal de cada operación. Al no tener estado, el
stub no puede distinguir las condiciones que producen los demás.

## Catálogo de errores

El mismo envoltorio en ambos lados, en todas las operaciones:

```json
{
  "errors": [
    { "error_code": "QUOTE_EXPIRED", "error_message": "Quote expired at 2026-10-14T15:05:00Z." }
  ],
  "request_id": "req_01JA8F3K2M7Q"
}
```

<div className="error-table">

| `error_code` | HTTP | Operaciones |
| --- | --- | --- |
| `VALIDATION_ERROR` | 400 | todas |
| `UNAUTHENTICATED` | 401 | todas |
| `QUOTE_NOT_FOUND` | 404 | aceptar, depósitos, pagos, consultar cotización |
| `PAYMENT_NOT_FOUND` | 404 | consultar pago |
| `NO_LIQUIDITY` | 422 | crear cotización |
| `QUOTE_CONFLICT` | 409 | crear cotización (mismo `tesser_quote_id`, cuerpo distinto) |
| `QUOTE_EXPIRED` | 409 | aceptar, depósitos (cotización en `EXPIRED`) |
| `QUOTE_NOT_ACCEPTED` | 409 | depósitos (cotización todavía en `CREATED`) |
| `QUOTE_REJECTED` | 409 | depósitos, pagos (cotización en `REJECTED`) |
| `DEPOSIT_CONFLICT` | 409 | depósitos (mismo `tesser_deposit_id`, cuerpo distinto) |
| `QUOTE_NOT_CREDITED` | 409 | pagos (la acreditación todavía no está en `CREDIT_CONFIRMED`) |
| `AMOUNT_MISMATCH` | 422 | pagos (`gtq_amount` ≠ monto acreditado) |
| `PAYMENT_CONFLICT` | 409 | pagos (la cotización ya tiene otro pago distinto) |
| `INTERNAL_ERROR` | 500 | todas |

</div>

Las dos operaciones de la API principal de Tesser que se incorporan aquí
([consultar cuenta](/api-tesser/accounts#get-an-account-by-id) <T />,
[crear retiro](/api-tesser/treasury#create-withdrawal) <T />) conservan los
códigos de error propios de la API principal (`api-0001`, `api-0004`, `api-0006`,
`counterparties-300x`) en lugar de los de este catálogo. Su contrato ya está
en producción y no se está redefiniendo aquí.
