Idempotencia
Las redes fallan en el peor momento: haces POST de un envío, la conexión se cae y no sabes si el correo salió. La idempotencia te permite reintentar esa solicitud de forma segura. Envía el mismo encabezado Idempotency-Key otra vez y Bird reproduce la respuesta original en lugar de procesar la solicitud una segunda vez.
Cómo funciona
La idempotencia es opcional. Añade un encabezado Idempotency-Key a una solicitud POST, PATCH, PUT o DELETE compatible. Las solicitudes sin él se procesan normalmente, sin deduplicación. Las solicitudes GET ignoran el encabezado.
En la API de cliente, las mutaciones con alcance de espacio de trabajo y de organización admiten la reproducción de respuesta descrita a continuación. Las operaciones exclusivas de usuario, las operaciones no autenticadas sin alcance y los streams la omiten. Las operaciones con un contrato de reproducción propio definen su comportamiento en su página de referencia. Por ejemplo, Crear una llamada de voz conserva la instantánea de aceptación original para reintentos coincidentes cuando proporcionas una clave.
Los SDK generan una clave para cada llamada de mutación y la reutilizan en los reintentos automáticos, incluida la creación de llamadas. No necesitas proporcionar una para los reintentos automáticos de SDK. Proporciona la tuya cuando una operación prevista abarca llamadas SDK separadas, por ejemplo un reintento tras reiniciar tu aplicación. Estos ejemplos muestran ese caso.
await bird.email.send(
{
from: "hello@yourdomain.com",
to: ["delivered@messagebird.dev"],
subject: "Welcome!",
html: "<p>Thanks for signing up.</p>",
},
{ idempotencyKey: "welcome-user/usr_abc123" },
);client.email.send(
from_="hello@yourdomain.com",
to=["delivered@messagebird.dev"],
subject="Welcome!",
html="<p>Thanks for signing up.</p>",
options={"idempotency_key": "welcome-user/usr_abc123"},
)_, err := client.Email.Send(context.Background(), bird.EmailSendParams{
From: "hello@yourdomain.com",
To: []string{"delivered@messagebird.dev"},
Subject: "Welcome!",
HTML: "<p>Thanks for signing up.</p>",
}, option.WithIdempotencyKey("welcome-user/usr_abc123"))$bird->email->send(
from: 'hello@yourdomain.com',
to: ['delivered@messagebird.dev'],
subject: 'Welcome!',
html: '<p>Thanks for signing up.</p>',
options: new RequestOptions(idempotencyKey: 'welcome-user/usr_abc123'),
);curl -X POST https://us1.platform.bird.com/v1/email/messages \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: welcome-user/usr_abc123" \
-d '{
"from": "hello@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"subject": "Welcome!",
"html": "<p>Thanks for signing up.</p>"
}'Una clave es cualquier cadena no vacía de hasta 255 caracteres. Un valor de encabezado vacío omite la deduplicación. El formato recomendado es una clave determinista derivada de tus propias entidades, <event-type>/<entity-id> (por ejemplo welcome-user/usr_abc123), de modo que los reintentos entre reinicios de proceso compartan clave; un UUID aleatorio por operación lógica también funciona. Los SDK de Bird generan automáticamente una clave UUID para cada solicitud de mutación y la reutilizan en sus reintentos internos.
Las claves tienen alcance de espacio de trabajo, o de organización en los endpoints de nivel de organización. Una respuesta completada se conserva durante 3 horas; un reintento después de esa ventana se procesa como una solicitud nueva. La ventana cubre los calendarios de reintento habituales. No queda ningún registro de deduplicación después de que expira.
Repeticiones
Cuando Bird ve una clave que ya completó, devuelve la respuesta en caché, mismo código de estado, mismo cuerpo, sin volver a ejecutar la solicitud. Las respuestas repetidas llevan un encabezado adicional para que puedas distinguirlas de un procesamiento nuevo:
Ejemplo de código
HTTP/1.1 202 Accepted
Idempotency-Replay: trueLas respuestas retenidas pueden incluir rechazos 4xx. Usa una clave nueva cuando corrijas una solicitud: si su rechazo fue retenido, un reintento sin cambios lo reproduce, y una solicitud modificada devuelve 409 E01005 IdempotencyKeyReuse. Las respuestas 5xx no se retienen, así que reintenta con la misma clave y solicitud.
Modos de fallo
| Escenario | Respuesta |
|---|---|
| Misma clave, misma solicitud, original completada | Respuesta en caché repetida con Idempotency-Replay: true |
| Misma clave, cuerpo de solicitud o endpoint diferente | 409, E01005 IdempotencyKeyReuse |
| Misma clave, solicitud original aún en curso | 409, E01004 RequestInProgress |
| Clave de más de 255 caracteres en un endpoint que declara el encabezado | 422, E01001 ValidationError |
| Protección de idempotencia no disponible antes de la ejecución | 503, E01033 IdempotencyUnavailable; este intento no se ejecuta |
Reutilizar una clave completada con una solicitud diferente se trata como un error del cliente: Bird devuelve 409 de inmediato en lugar de entregarte silenciosamente una respuesta que no coincide con lo que enviaste. Genera una clave nueva para la nueva solicitud. La comparación abarca el método, el endpoint, los parámetros de ruta y consulta, y el cuerpo crudo de la solicitud, incluidos los espacios en blanco de JSON. Las cargas multipart comparan nombres de parte, nombres de archivo y contenido; los límites y el orden de las partes no afectan la reproducción.
RequestInProgress significa que una solicitud concurrente con la misma clave aún no ha terminado, normalmente un timeout agresivo del lado del cliente que reintenta mientras el primer intento todavía se está procesando. El bloqueo en curso expira en 30 segundos, así que espera brevemente y reintenta. Consulta Errores para ver la respuesta de error en la que vienen envueltos.
Qué no se almacena en caché
Las respuestas 5xx nunca se almacenan en caché. La clave se desbloquea y Bird puede procesar un reintento como un intento nuevo. Reintenta las respuestas 5xx y los timeouts con retroceso exponencial usando la misma clave y solicitud. Una operación puede surtir efecto antes de que su respuesta se retenga; si esa respuesta se pierde o el bloqueo en curso expira, un reintento puede ejecutar la operación de nuevo.
Si la protección de idempotencia no está disponible antes de la ejecución, API devuelve 503 E01033 IdempotencyUnavailable sin ejecutar este intento. Conserva la clave en cada reintento. Este error no describe el resultado de un intento anterior con la misma clave.
Guía práctica
- Genera una clave por operación lógica y reutilízala en cada intento de HTTP de esa operación.
- Reintenta ante errores de red, timeouts y 5xx con retroceso exponencial, reutilizando la misma clave cada vez.
- Trata 409 IdempotencyKeyReuse como un error en tu generación de claves. No lo reintentes.
- Las claves son opcionales en las mutaciones. Usa una cuando necesites protección de reintento; omítela en las solicitudes GET.
Siguientes pasos
- Referencia de idempotencia API: esquemas de encabezado y de encabezado de respuesta
- Conceptos de SDK: generación automática de claves y comportamiento de reintento en los SDK
- Errores: la respuesta de error y el catálogo de códigos
- Envío de correo electrónico: endpoints de envío y de lotes
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.