Errores e idempotencia
Decida según el código de error, no según el estado. Y haga seguro cada reintento que cuesta dinero.
Decida según el código, no según el estado
Los errores llegan como { "error": "<code>" }. El estado por sí solo no basta
para decidir qué hacer: dos 403 pueden requerir soluciones opuestas.
| Status | Code | Qué significa y qué hacer |
|---|---|---|
| 401 | invalid_key | Clave desconocida o revocada. Cree una nueva; reintentar nunca ayudará. |
| 403 | ip_not_allowed | La clave tiene una lista de IP permitidas y esta dirección no figura en ella. La clave está bien: agregue la dirección en developers.wasync.app/keys. No la rote. |
| 403 | insufficient_scope | La credencial no tiene el alcance que necesita este endpoint. |
| 403 | forbidden_portal_kind | POST /connections en un portal de Bitrix24. Allí las conexiones las crea el administrador del portal. |
| 400 | invalid_phone_number | phoneNumber debe contener solo dígitos, sin + inicial. |
| 400 | invalid_webhook | La URL debe ser HTTPS en un host accesible públicamente. |
| 402 | — | La licencia de la conexión ha vencido. Consulte Licences & trial. |
| 409 | already_connected | La sesión está activa; no hay nada que vincular. |
| 409 | not_supported_for_provider | Una operación exclusiva de qr sobre un número cloud_api. Es permanente: no reintente. |
| 422 | recipient_not_on_whatsapp | WhatsApp no encontró una cuenta para el destinatario. Compruebe que el número esté en formato internacional (primero el código de país, sin cero inicial) y que la persona use WhatsApp. Es permanente para ese número: no reintente sin cambios. |
| 502 | send_failed | WhatsApp no pudo entregar el mensaje por un motivo ajeno al destinatario (sesión o proveedor). Reintente tras una breve pausa; si persiste, revise el estado de la conexión. |
| 429 | warmup_limited | Límite horario de calentamiento en un número qr nuevo. Espere unos minutos antes de reintentar. |
| 429 | rate_limited | Limitador contra abusos. Respete Retry-After cuando esté presente; mantenga siempre una espera por defecto. |
| 502 | pairing_code_unavailable | Un resultado normal, no una caída del servicio: use el QR como alternativa. |
Retry-After no está garantizado en todos los 409/429, así que nunca haga que
su espera dependa de él.
Idempotencia en POST /connections
Crear una conexión aprovisiona una sesión de WhatsApp y consume un cupo de pago.
Un cliente que agote el tiempo de espera y reintente crearía, de otro modo, una
segunda conexión, y usted pagaría sin saberlo dos cupos por un solo cliente.
El encabezado opcional Idempotency-Key cierra ese hueco. Solo se admite en
POST /connections; si no lo envía, el comportamiento es exactamente el de antes.
Una clave es cualquier cadena opaca de hasta 255 caracteres, con espacio de nombres propio de su workspace (dos partners que usen la misma cadena nunca colisionan), y vive 24 horas desde la primera solicitud que la usó.
201 Created.200 OK más el encabezado de respuesta Idempotency-Replayed: true. El qr de esa respuesta se obtiene de nuevo, no es el código guardado en la primera creación: los códigos de vinculación rotan aproximadamente cada 20 segundos, de modo que un QR antiguo reenviado simplemente no se podría escanear. Trate el 200 como un éxito, no como un error.400 { "error": "idempotency_key_reuse" }. La comparación usa un hash del cuerpo canónico, por lo que el orden de las claves JSON no importa.409 { "error": "idempotency_in_progress" } con Retry-After: 1. Respételo y reintente con la misma clave.Una clave de más de 255 caracteres se rechaza con
400 { "error": "idempotency_key_invalid" }; nunca se trunca. Un encabezado
vacío o con solo espacios se considera ausente. La forma del cuerpo de la
respuesta no cambia en ningún caso.
Genere una clave por cada intento de incorporación de un cliente
Un UUID nuevo (crypto.randomUUID()) creado justo antes de la llamada y
reutilizado solo por los reintentos de esa llamada. No use una clave por
proceso, por API key, por día ni una constante. Con una clave tan amplia, al
segundo cliente que incorpore se le devolvería la conexión del primero en
lugar de la suya.
Idempotencia en los envíos
POST /messages recibe un idempotencyKey en el cuerpo (no en un
encabezado). Envíe siempre uno: un UUID por cada envío lógico.
- Ante cualquier error o tiempo de espera agotado, reintente con la misma clave. Una clave nueva significa un segundo mensaje real de WhatsApp en el teléfono de alguien.
- Ante un
409 in_progress, consulte con la misma clave: respeteRetry-Aftercuando esté presente; si no, espere unos 5 s. - Un envío lento no es un envío fallido. Configure su tiempo de espera HTTP en al menos 180 s.