# Idempotencia (/docs/idempotency)

Una red puede cortarse justo después de que enviaste un pago. ¿Llegó o no? Con `Idempotency-Key` no importa: reenvías **la misma solicitud con la misma clave** y recibes el resultado original, sin un segundo efecto.

```bash
curl https://api-sandbox.caibopay.app/v1/payouts \
  -H "Authorization: Bearer $CAIBO_API_KEY" \
  -H "Idempotency-Key: pago-orden-5531" \
  -H "Content-Type: application/json" \
  -d '{ "beneficiary_id": "ben_...", "quote_id": "quo_..." }'
```

## Cómo se comporta [#cómo-se-comporta]

| Envías | Recibes |
| --- | --- |
| Una clave nueva | `201` y el recurso creado. |
| La misma clave con la misma solicitud | `200`, el mismo recurso en su estado actual y el encabezado `Idempotent-Replayed: true`. Nada se repite. |
| La misma clave con otra solicitud | `409 idempotency_key_reused`. |
| Sin clave, donde es obligatoria | `400 idempotency_key_required`. |

Si dos solicitudes con la misma clave llegan a la vez, la segunda espera a la primera y devuelve su resultado.

## Dónde es obligatoria [#dónde-es-obligatoria]

En todas las creaciones que mueven dinero o fijan un precio:

<Endpoint method="POST" path="/v1/customers" /> <Endpoint method="POST" path="/v1/quotes" /> <Endpoint method="POST" path="/v1/payouts" /> <Endpoint method="POST" path="/v1/payouts/{id}/cancel" /> <Endpoint method="POST" path="/v1/payout-batches" /> <Endpoint method="POST" path="/v1/withdrawals" /> <Endpoint method="POST" path="/v1/remittances" /> <Endpoint method="POST" path="/v1/funding-accounts" /> <Endpoint method="POST" path="/v1/refunds" /> <Endpoint method="POST" path="/v1/hosted-sessions" />

El resto de las operaciones ignoran el encabezado. Registrar dos veces el mismo beneficiario o la misma cuenta de destino ya devuelve el registro existente.

## Buenas prácticas [#buenas-prácticas]

- **Una clave por operación de negocio**, derivada de tu propio identificador: `pago-orden-5531`, `cobro-factura-F-2201`. Así un reintento, incluso días después o desde otro proceso, usa la misma.
- Entre **8 y 128 caracteres** de `A-Z a-z 0-9 . _ : -`.
- **Las claves no vencen.** Una clave usada sigue amarrada a su solicitud original para siempre.
- Una solicitud rechazada (`4xx`) no gasta la clave: corrige y reenvía con la misma.
- Ante `500` o `503`, reintenta **con la misma clave**.

<Callout type="warn" title="Un pago sin fondos sí gasta su clave">
Si tu saldo no alcanza, `POST /v1/payouts` responde `201` con `status: failed` y `failure_code: insufficient_funds`. Ese pago existe y su clave quedó usada. Para reintentar cuando tengas fondos, usa una clave nueva (y una cotización nueva si usaste una).
</Callout>
