Conceptos
Idempotencia
Una clave por reserva para poder reintentar sin crear dos turnos ni dos cobros.
Ver en MarkdownPOST /api/v1/reservas exige la cabecera Idempotency-Key. Si la conexión se corta y no sabés si la reserva se creó, repetí el pedido con la misma clave y el mismo cuerpo: vas a recibir la misma reserva, sin otra fila, sin otro mail y sin otro link de pago.
| Caso | Respuesta |
|---|---|
| Clave nueva | 201 con la reserva y operacion.repetida: false. |
| Misma clave, mismo cuerpo | 200 con la misma reserva y operacion.repetida: true. |
| Misma clave, otro cuerpo | 409 CONFLICTO_INTENCION. No se crea nada. |
| Dos pedidos a la vez con la misma clave | Se crea una sola reserva; los dos reciben el mismo resultado. |
| Sin la cabecera | 400 IDEMPOTENCY_KEY_FALTANTE, sin escribir nada. |
Cómo elegir la clave
- Entre 8 y 100 caracteres: letras, números, punto, guion, guion bajo o dos puntos.
- Generala una vez por intento de reserva de la clienta (por ejemplo, al abrir el paso de confirmación) y guardala hasta tener respuesta. Un UUID sirve.
- Si la clienta cambia el horario o los datos, es otra reserva: usá otra clave.
- La clave es del negocio, no de la credencial: si rotás la clave de la API, el reintento con la nueva recupera la reserva hecha con la anterior.
// Una clave por intento de reserva, reutilizada en cada reintento.
const idem = sessionStorage.getItem("reservaIdem") ?? crypto.randomUUID();
sessionStorage.setItem("reservaIdem", idem);
async function reservar(cuerpo, intentos = 3) {
for (let i = 0; i < intentos; i++) {
try {
const res = await fetch("https://turnovapp.com/api/v1/reservas", {
method: "POST",
headers: {
Authorization: "Bearer tnv_pk_TU_CLAVE_PUBLICA",
"Content-Type": "application/json",
"Idempotency-Key": idem,
},
body: JSON.stringify(cuerpo),
});
const r = await res.json();
if (r.ok || !r.error.reintentable) return r;
const espera = Number(res.headers.get("Retry-After") ?? 2);
await new Promise((ok) => setTimeout(ok, espera * 1000));
} catch {
// Red caída: reintentar con la MISMA clave es seguro.
}
}
throw new Error("No pudimos confirmar la reserva");
}Las lecturas (GET) no llevan clave de idempotencia: se pueden repetir libremente.