Errori e idempotenza
Ragioni sul codice di errore, non sullo stato. E rendi sicuro ogni nuovo tentativo che comporta un costo.
Ragiona sul codice, non sullo stato
Gli errori tornano nella forma { "error": "<code>" }. Lo stato da solo non basta
per decidere cosa fare: due risposte 403 possono richiedere rimedi opposti.
| Stato | Codice | Cosa significa e cosa fare |
|---|---|---|
| 401 | invalid_key | Chiave sconosciuta o revocata. Ne crei una nuova; riprovare non servirà mai. |
| 403 | ip_not_allowed | La chiave ha una allowlist di IP e questo indirizzo non è incluso. La chiave è valida: aggiunga l'indirizzo in developers.wasync.app/keys. Non la ruoti. |
| 403 | insufficient_scope | La credenziale non ha lo scope richiesto da questo endpoint. |
| 403 | forbidden_portal_kind | POST /connections su un portale Bitrix24. Lì le connessioni vengono create dall'amministratore del portale. |
| 400 | invalid_phone_number | phoneNumber deve contenere solo cifre, senza + iniziale. |
| 400 | invalid_webhook | L'URL deve essere HTTPS su un host raggiungibile pubblicamente. |
| 402 | — | La licenza della connessione è scaduta. Vedi Licenze e prova. |
| 409 | already_connected | La sessione è attiva; non c'è nulla da associare. |
| 409 | not_supported_for_provider | Un'operazione riservata a qr eseguita su un numero cloud_api. Permanente: non riprovi. |
| 422 | recipient_not_on_whatsapp | WhatsApp non ha trovato un account per il destinatario. Verifichi che il numero sia in formato internazionale (prima il prefisso del paese, senza zero iniziale) e che la persona usi WhatsApp. Permanente per quel numero: non riprovi senza modifiche. |
| 502 | send_failed | WhatsApp non ha potuto consegnare per un motivo non legato al destinatario (sessione o provider). Riprovi dopo una breve attesa; se il problema persiste, controlli lo stato della connessione. |
| 429 | warmup_limited | Limite orario di warm-up su un nuovo numero qr. Attenda alcuni minuti prima di riprovare. |
| 429 | rate_limited | Limitatore anti-abuso. Rispetti Retry-After se presente; mantenga comunque un'attesa predefinita. |
| 502 | pairing_code_unavailable | Un esito ordinario, non un'interruzione del servizio: ripieghi sul QR. |
Retry-After non è garantito in ogni risposta 409/429, quindi non faccia mai
dipendere l'attesa da questo header.
Idempotenza su POST /connections
Creare una connessione predispone una sessione WhatsApp e consuma uno slot a
pagamento. Un client che va in timeout e riprova creerebbe altrimenti una
seconda connessione, e lei pagherebbe senza accorgersene due slot per un solo
cliente. L'header facoltativo Idempotency-Key chiude questa falla. È
supportato solo su POST /connections; se lo omette, il comportamento resta
quello di sempre.
Una chiave è una qualsiasi stringa opaca fino a 255 caratteri, limitata al suo workspace (due partner che usano la stessa stringa non entrano mai in conflitto) e dura 24 ore dalla prima richiesta che l'ha usata.
201 Created.200 OK più l'header di risposta Idempotency-Replayed: true. Il qr in quella risposta viene recuperato al momento, non è il codice salvato alla prima creazione: i codici di associazione cambiano circa ogni 20 secondi, quindi un QR obsoleto riproposto non sarebbe scansionabile. Consideri il 200 un successo, non un errore.400 { "error": "idempotency_key_reuse" }. Il confronto usa un hash del corpo canonico, quindi l'ordine delle chiavi JSON non conta.409 { "error": "idempotency_in_progress" } con Retry-After: 1. Lo rispetti e riprovi con la stessa chiave.Una chiave più lunga di 255 caratteri viene rifiutata con
400 { "error": "idempotency_key_invalid" }, mai troncata. Un header vuoto o
composto solo da spazi equivale a un header assente. La struttura del corpo della
risposta non cambia in nessun caso.
Generi una chiave per ogni tentativo di onboarding del cliente
Un UUID nuovo (crypto.randomUUID()) creato subito prima della chiamata e
riutilizzato solo dai nuovi tentativi di quella chiamata. Non usi una chiave
per processo, per API key, per giorno né una costante. Con una chiave così
generica, il secondo cliente che avvia riceve indietro la connessione del
primo invece della propria.
Idempotenza sugli invii
POST /messages accetta un idempotencyKey nel corpo (non in un header).
Ne invii sempre uno: un UUID per ogni invio logico.
- In caso di qualsiasi errore o timeout, riprovi con la stessa chiave. Una chiave nuova significa un secondo messaggio WhatsApp reale sul telefono di qualcuno.
- Con
409 in_progress, interroghi con la stessa chiave: rispettiRetry-Afterse presente, altrimenti attenda circa 5 s. - Un invio lento non è un invio fallito. Imposti il timeout HTTP ad almeno 180 s.