API v2 (beta)
Passare dalla v1 alla v2
L'API v2 fa ciò che fa la v1, con chiavi più sicure, un unico stile di URL, veri codici di stato HTTP e webhook JSON firmati. Questa pagina mette in corrispondenza ogni endpoint e campo della v1 con il suo equivalente nella v2. Le novità della v2 sono descritte nella panoramica.
Cosa cambia ovunque#
- Chiavi:
client_id+api_keydella v1 diventano un unico header,Authorization: Bearer wbz_live_…. Crea una chiave v2 in Impostazioni → Chiavi API, nella scheda Chiavi API v2, solo con gli scope di cui l'app ha bisogno. Le chiavi v1 non funzionano sulla v2, e le chiavi v2 non funzionano sulla v1. - Solo JSON: niente campi di un modulo. I file si caricano con
POST /media(multipart) e si inviano tramitemedia_id. - Metodi e URL:
GETper leggere,POSTper creare,PATCHper modificare,DELETEper annullare o eliminare, sottohttps://wbiztool.com/api/v2. - Codici di stato HTTP al posto di
"status": 0o1(vedi Risposte ed errori). - Numeri di telefono in formato internazionale con
+, senzacountry_code. - Orari in ISO 8601 con un offset, invece di campi separati per data, ora e fuso orario.
- Webhook: sono endpoint che aggiungi una volta per lo spazio di lavoro, con eventi JSON firmati, invece di un URL
webhooksu ogni messaggio.
Endpoint per endpoint#
I percorsi v2 sono relativi a https://wbiztool.com/api/v2.
Invio, campo per campo#
| v1 | v2 | Note |
|---|---|---|
client_id + api_key (body o Authorization: Bearer) | Authorization: Bearer wbz_live_… | Una nuova chiave v2; niente client_id |
phone + country_code | to.phone | Un numero in formato E.164 con +: "9876543210" con "country_code": "91" diventa {"phone": "+919876543210"}. Il prefisso internazionale non viene aggiunto automaticamente |
phone con un @username (Telegram) | to.username | @name, t.me/name oppure tg: seguito da un id, da un account Telegram |
group_name | to.group | Il nome esatto del gruppo |
| (non presente nella v1) | to.contact_id | Un contatto salvato |
whatsapp_client | from | L'id del numero; facoltativo quando è collegato un solo numero, come prima |
msg (o message) | text | Fino a 3.000 caratteri, come prima |
msg_type 0, 1, 2 | nessuno | Un messaggio con media è un messaggio multimediale; media.type (image o file) quando il link non lo indica |
img_url / file_url | media.url | Un link pubblico http(s) |
file (caricato nella stessa richiesta) | media.media_id | Caricalo prima, poi invia l'id tutte le volte che vuoi |
file_name | media.file_name | Per i file |
date + time + timezone di schedule_msg/ | send_at | Un unico orario con il suo offset: 24/12/2026, 10:30 e Asia/Kolkata diventano "2026-12-24T10:30:00+05:30" |
expire_after_seconds | expires_at | Un orario, non una durata: adesso più i secondi, con il suo offset |
webhook | endpoint dei webhook | Aggiunti una sola volta con POST /webhooks, per tutti i messaggi dello spazio di lavoro |
msg_id nella risposta | id | Viene restituito il Messaggio stesso, con il suo status |
Lo stesso invio nella v1 e nella v2:
# v1
curl -X POST https://wbiztool.com/api/v1/send_msg/ \
-H "Authorization: Bearer YOUR_V1_KEY" \
-H "Content-Type: application/json" \
-d '{"whatsapp_client": 101, "msg_type": 1, "country_code": "91", "phone": "9876543210",
"img_url": "https://example.com/offers/diwali-sale.jpg", "msg": "Our Diwali sale starts today",
"expire_after_seconds": 3600}'
# v2
curl -X POST https://wbiztool.com/api/v2/messages \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: diwali-9876543210" \
-d '{"from": 101, "to": {"phone": "+919876543210"},
"media": {"url": "https://example.com/offers/diwali-sale.jpg"}, "text": "Our Diwali sale starts today",
"expires_at": "2026-10-20T11:30:00+05:30"}'
Alcuni comportamenti della v1 sono stati eliminati di proposito:
- Nessuna supposizione sui prefissi internazionali. La v1 anteponeva
country_codeal numero (con91, sempre davanti a un numero di 10 cifre). La v2 prende il numero esattamente come è scritto, con+. - Nessun download del file durante la chiamata. La v1 scaricava
img_urlefile_urldurante la richiesta. La v2 controlla che il link sia pubblico e scarica il file quando il messaggio viene inviato; un link non valido si presenta come messaggiofailed. - Nessuna riga fallita in caso di rifiuto. Quando la v1 rifiuta un invio oltre il limite giornaliero di 1.000, salva comunque il messaggio come fallito. La v2 non salva nulla quando rifiuta un invio.
- I campi sconosciuti vengono rifiutati invece di essere ignorati.
Stati#
I numeri e le parole della v1 diventano un unico campo status:
| v1 | status v2 |
|---|---|
0 Created / Pending | queued, oppure scheduled finché il suo send_at è nel futuro |
1 Sent | sent, delivered o read (le spunte di WhatsApp) |
2 Failed | failed |
3 Cancelled | cancelled |
4 Expired | expired |
Gli eventi webhook sono message.sent, message.failed, message.cancelled e message.expired, corrispondenti a SENT, FAILED, CANCELLED ed EXPIRED della v1.
Risposte ed errori#
La v1 risponde a molti errori con HTTP 200 o 400 e "status": 0, e al successo con "status": 1. La v2 usa il codice di stato HTTP:
- Il successo è
200,201(creato) o202(in coda), e il body è l'oggetto stesso, ad esempio il Messaggio. Non c'è nessun involucrostatus: 1. - Gli errori sono
4xxo5xxcon un'unica struttura:{"error": {"code", "message", "field", "docs", "request_id"}}. Basa le condizioni sucode, non sulmessagein inglese. Tutti i codici sono nella pagina degli errori.
# v1
result = response.json()
if result.get("status") == 1:
msg_id = result["msg_id"]
# v2
if response.status_code == 202:
message_id = response.json()["id"]
else:
error = response.json()["error"]
if error["code"] == "number_daily_cap_reached":
... # try again tomorrow
Alcuni messaggi della v1 e i relativi codici v2:
| Messaggio v1 | Codice v2 |
|---|---|
Auth Error: invalid api key | 401 invalid_api_key, api_key_revoked o api_key_expired |
Invalid phone number / Invalid Contact Number "…" | 422 invalid_phone |
Msg cant be null | 400 text_required |
Message length is too long | 400 text_too_long |
Invalid whatsapp client | 422 number_not_found |
Invalid whatsapp client id. | 422 from_required |
Not enough credits | 402 no_credits |
Daily limit reached: … | 429 number_daily_cap_reached |
Demo Account can not access apis | 403 demo_account |
Account Disabled | 403 account_disabled |
Invalid JSON format: … | 400 invalid_json |
Webhook#
Nella v1, ogni messaggio può avere un URL webhook che riceve un msg_id=…&status=SENT codificato come modulo. Nella v2:
- Aggiungi un endpoint una sola volta con
POST /webhookse conserva il suosecret. - Riceve eventi JSON per tutti i messaggi dello spazio di lavoro, con l'intero Messaggio in
data.message. Abbinali ai tuoi record tramitedata.message.id. - Verifica la firma: lo stesso schema della v1 (
WbizTool-Timestamp,WbizTool-Signature: v1=…), ma con il secret dell'endpoint invece di quello dello spazio di lavoro. - Scarta i duplicati con
WbizTool-Event-Id. I nuovi tentativi continuano per circa 23 ore, non 4 tentativi in pochi minuti come nella v1, e anche le risposte4xxvengono ritentate.
Gli eventi di collegamento della v1 (webhook_url su whatsapp/connect/) non hanno ancora un evento v2: interroga invece GET /numbers/{id}.
Una checklist#
Crea una chiave v2 per ogni app
In Impostazioni → Chiavi API, solo con gli scope di cui ha bisogno. Provala prima con una chiave di test, che controlla tutto e non invia nulla.
Modifica le richieste
Nuovi URL e metodi, body JSON,
to/from/text/media, numeri di telefono con+, orari con offset. Aggiungi unIdempotency-Keya ogni invio.Modifica la gestione degli errori
Controlla lo stato HTTP, poi
error.code. Gestisci il429aspettandoRetry-After.Sposta i webhook
Aggiungi un endpoint, verifica le firme con il suo secret e scarta i duplicati tramite l'id dell'evento.
Passa alla v2 e revoca
Quando l'app funziona sulla v2, elimina la sua chiave v1 in Impostazioni → Chiavi API.
