> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maple.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# Idempotencia y seguridad ante reintentos

> Cómo hace Maple que los reintentos sean seguros sin una clave de idempotencia: decisiones seguras ante reintentos, menús aplicados como diferencias, repetición idempotente y deduplicación de su lado.

Las redes fallan a mitad de una solicitud. La pregunta que importa es: si reintenta, ¿algo ocurrirá dos veces? Con Maple, las escrituras que más reintentará están diseñadas para poder repetirse sin riesgo, así que puede reintentar tras un tiempo de espera agotado sin conciliar primero.

<Note>
  Esta API **no tiene un encabezado `Idempotency-Key`**. Para pedidos, menús y eventos, la seguridad es una propiedad de
  cada operación, como se describe a continuación, y no algo que usted active en cada solicitud. El único lugar donde
  sí envía una clave es en las **escrituras de reservas y de lista de espera**, que reciben un `idempotency_key` en el
  cuerpo de la solicitud (vea más abajo).
</Note>

## Las decisiones sobre pedidos son seguras ante reintentos

Repetir una decisión sobre un pedido (`accept`, `deny`, `ready`, `complete`, `cancel` o `status`) devuelve el mismo acuse de recibo sin aplicar el efecto secundario dos veces:

```json theme={null}
{ "object": "order_decision", "order_id": "ord_...", "decision": "accept", "status": "received" }
```

Si envía `accept` y la respuesta agota el tiempo de espera, envíelo de nuevo. El pedido se acepta exactamente una vez y usted recibe `{ "status": "received" }` en ambos casos. Así, un ciclo simple de reintento ante errores transitorios es correcto sin que usted tenga que llevar ningún registro adicional.

## Publicar un menú es aplicar una diferencia

Una publicación de menú describe el estado deseado de todo el menú y se aplica como una diferencia respecto de lo que está publicado actualmente, usando como clave sus `externalId`:

* Volver a publicar un documento **idéntico** no hace nada.
* Las identidades de los objetos se mantienen estables entre publicaciones según el `externalId`, así que republicar no recrea ni altera objetos.
* La validación es de todo o nada: un `400` no cambia nada, por lo que una publicación fallida deja el menú exactamente como estaba.

Por lo tanto, si una publicación agota el tiempo de espera, reenviar el mismo documento es seguro. Vea [Publicar un menú](/es/developer-api/guides/publish-menu).

## Las escrituras de reservas llevan un `idempotency_key`

Crear, modificar o cancelar una reserva (`POST /v1/bookings`, `POST /v1/bookings/{id}/change`, `POST /v1/bookings/{id}/cancel`), cancelarla como el establecimiento (`POST /v1/bookings/{id}/venue_cancel`) y sentar a un cliente sin reserva (`POST /v1/locations/{locationId}/walk_ins`) requieren un `idempotency_key` **en el cuerpo**, limitado a su app. Las claves de clientes sin reserva, al igual que las de las incorporaciones a la lista de espera, pertenecen a su app en todos sus locales. Las claves deben tener de 1 a 255 caracteres. Para las **reservas nativas de Maple**, el registro guarda la escritura y el resultado de su repetición en una sola transacción:

* Reintentar con la **misma clave y la misma solicitud** repite el resultado original: usted recibe la misma `booking` y nada se reserva, se mueve ni se cancela dos veces.
* La **misma clave con una solicitud distinta** (otro cliente, otro horario u otra nota) responde `409` con `code: "idempotency_key_reused"`. Genere una clave nueva por cada escritura que desee hacer; un UUID sirve.

Un reintento devuelve la misma identidad de reserva sin volver a aplicar la modificación; la respuesta se lee de la reserva actual. Las claves tienen una ventana de repetición de 24 horas desde el primer uso. Las repeticiones se verifican antes que `expected_version`, que con frecuencia estará desactualizada después de que la escritura original tuvo éxito.

Las retenciones nativas y de proveedores se conservan y pertenecen a la app que las obtuvo. Repetir el mismo `slot_token` reproduce la retención activa de la app sin tomar otro bloqueo. Otra app no puede consumirla ni liberarla, incluso en un local con acceso otorgado a ambas. Las retenciones de proveedor desconocidas liberan su reserva de cuota después de una cuarentena conservadora de 24 horas de inactividad, independientemente de su registro de auditoría conservado; las operaciones vencidas no pueden revivirse reintentando.

### Escrituras respaldadas por un proveedor

Para OpenTable, Maple registra de forma duradera la clave y el resumen de la solicitud antes de cualquier E/S con el proveedor y usa un único ID de solicitud estable ante el proveedor. Un cambio o una cancelación pendiente también reserva la reserva reflejada frente a otras escrituras de socios. Cuando tiene éxito, Maple registra el reflejo y el resultado de la repetición juntos. Las fallas transitorias del reflejo se reintentan de forma sincrónica; un conciliador en segundo plano repara el trabajo pendiente.

Un tiempo de espera agotado del proveedor devuelve `409 operation_in_progress` mientras el resultado no esté resuelto. Reintente la misma solicitud con la misma clave después de `details.retry_after` segundos. Maple realiza una lectura de conciliación antes de repetir una escritura de reserva con el ID de solicitud original del proveedor. Las escrituras completadas se repiten sin volver a llamar al proveedor.

<Warning>
  Una clave pendiente sin resolver **no** se recicla cuando termina su ventana automática de repetición de 24 horas. Si `details.reason` es `replay_window_expired`, detenga los reintentos automáticos y comuníquese con Maple con el `details.operation_id`. No genere una clave nueva para evitar un resultado incierto.
</Warning>

La configuración de reservas usa en cambio una publicación direccionada por contenido: una configuración idéntica no hace nada, sin necesidad de una clave explícita. Los verbos de estado del establecimiento (confirmar, rechazar, sentar, completar, no se presentó) reciben `expected_version`, no una clave de idempotencia; después de una respuesta ambigua, lea la reserva antes de tomar otra acción. La cancelación por parte del establecimiento y los clientes sin reserva sí reciben un `idempotency_key`, limitado a su app como todas las demás claves.

```json theme={null}
{ "hold_id": "bkh_…", "guest": { "first_name": "Alex", "last_name": "Quinn", "phone": "+12125551234" }, "idempotency_key": "6f1c…" }
```

## Repetir un evento es idempotente

`POST /v1/webhook_events/{eventId}/replay` vuelve a entregar un evento solo a las suscripciones que aún no lo han recibido. Las suscripciones que ya lo recibieron se omiten, así que repetir un evento después de una caída no genera entregas dobles a los endpoints que funcionan bien.

## De su lado: deduplique las entregas

El único lugar donde usted debe agregar idempotencia es su **manejador de webhooks**. La entrega es de al menos una vez, así que el mismo evento puede llegar más de una vez. Deduplique usando el `id` del sobre:

```ts theme={null}
async function handleEvent(event: { id: string; type: string; data: unknown }) {
  if (await alreadyProcessed(event.id)) return; // no-op on a repeat
  await process(event);
  await markProcessed(event.id);
}
```

Haga que el trabajo en sí sea idempotente cuando pueda; por ejemplo, use el `order_id` de Maple como clave de sus propios registros de pedidos, de modo que un `order.notification` duplicado actualice en lugar de duplicar. No dependa del orden de los eventos; concilie con `GET /v1/orders/{orderId}` cuando la secuencia importe. Vea [Webhooks](/es/developer-api/concepts/webhooks).

## Resumen

| Operación | ¿Es seguro reintentar? | Por qué |
| - | - | - |
| Decisiones sobre pedidos | Sí | Seguras ante reintentos; las repeticiones devuelven `received` sin efecto doble |
| Publicación de menú | Sí | Se aplica como diferencia; volver a publicar lo idéntico no hace nada |
| Repetición de eventos | Sí | Omite las suscripciones que ya recibieron la entrega |
| Crear / modificar / cancelar reserva nativa | Sí, con su `idempotency_key` | Misma clave + mismo cuerpo se repite; misma clave + cuerpo distinto es `409 idempotency_key_reused` |
| Clientes sin reserva y cancelación por el establecimiento | Sí, con su `idempotency_key` | Misma clave + mismo cuerpo repite la misma reserva, incluso después de que se ocupe su mesa; misma clave + cuerpo distinto (o, en el caso de clientes sin reserva, otro local) es `409 idempotency_key_reused` |
| Retenciones de reservas nativas | Mientras la retención original esté activa | Volver a presentar su `slot_token` devuelve la retención activa |
| Escrituras y retenciones de reservas con proveedor | Con la misma clave / cotización | Registros duraderos e IDs de solicitud estables ante el proveedor; los resultados sin resolver pueden requerir conciliación |
| Configuración de reservas | Sí | Una configuración idéntica no hace nada (direccionada por contenido) |
| Recepción de webhooks | Usted deduplica | Entrega de al menos una vez: deduplique por el `id` del evento |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.