API v2 (beta)
API v2
L'API v2 è la nuova API REST di WbizTool: una chiave per app con solo l'accesso di cui ha bisogno, URL orientati alle risorse, codici di stato HTTP reali, webhook JSON firmati e nuovi tentativi sicuri. Questa pagina descrive ciò che tutte le richieste hanno in comune. Le pagine delle risorse descrivono ogni endpoint.
URL di base#
https://wbiztool.com/api/v2
I percorsi non hanno la barra finale (/api/v2/messages), ma viene accettata anche con la barra. Un indirizzo che non esiste risponde 404 con il codice not_found.
Esempio rapido#
Verifica la tua chiave con GET /me. Funziona con qualsiasi scope e non invia nulla:
curl https://wbiztool.com/api/v2/me \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"import os
import requests
response = requests.get(
"https://wbiztool.com/api/v2/me",
headers={"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}"},
timeout=30,
)
print(response.status_code, response.json())// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v2/me", {
headers: { Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}` },
});
console.log(response.status, await response.json());<?php
$ch = curl_init('https://wbiztool.com/api/v2/me');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), "\n";
print_r($body);
curl_close($ch);{
"workspace": { "id": 5012, "name": "Acme Bakery" },
"key": {
"id": 7,
"name": "Order system",
"mode": "live",
"scopes": ["messages:send", "messages:read"],
"limited_to_numbers": false,
"number_ids": [],
"expires_at": null
},
"plan": { "name": "Starter" },
"limits": {
"requests_per_minute": 60,
"requests_per_day": 10000,
"messages_per_number_per_day": 1000,
"messages_remaining": null
}
}
messages_remaining è null quando il piano invia messaggi illimitati. plan è null quando lo spazio di lavoro non ha un piano attivo.
Chiavi#
Invia la tua chiave nell'header Authorization in ogni richiesta:
Authorization: Bearer wbz_live_…
Non c'è un client_id: la chiave indica il proprio spazio di lavoro. Una chiave v2 inizia con wbz_live_ o wbz_test_, seguito da 38 lettere e cifre. Le chiavi v1 non funzionano con la v2 (ricevono v1_key_on_v2) e le chiavi v2 non funzionano con la v1.
Creare una chiave#
I Proprietari creano le chiavi in Impostazioni → Chiavi API, nella scheda Chiavi API v2: fai clic su Crea chiave v2, poi scegli:
- Nome: l'app che la userà, fino a 50 caratteri.
- Tipo di chiave: Reale invia messaggi veri; Test controlla tutto e non invia nulla (vedi Modalità test).
- Cosa può fare: gli scope, oppure Tutto.
- Numeri che può usare: tutti i numeri, anche quelli aggiunti in seguito, oppure solo alcuni (vedi Chiavi limitate ad alcuni numeri).
- Scadenza: mai, oppure tra 30 giorni, 90 giorni o 1 anno.
La chiave viene mostrata una sola volta. Copiala subito e conservala sul tuo server, per esempio in una variabile d'ambiente. WbizTool conserva solo un hash della chiave e i suoi ultimi quattro caratteri, quindi una chiave persa non può essere mostrata di nuovo: revocala e creane una nuova.
Uno spazio di lavoro può avere fino a 10 chiavi v2 non revocate. La scheda mostra per ogni chiave gli ultimi quattro caratteri, gli scope, i numeri, la scadenza, e quando e da quale indirizzo IP è stata usata l'ultima volta. Revoca blocca subito una chiave e, con essa, gli endpoint dei webhook che ha creato. Una chiave oltre la data di scadenza riceve api_key_expired.
Scope#
Ogni chiave può fare solo ciò che i suoi scope consentono. Una richiesta al di fuori di essi risponde 403 con missing_scope, e required_scope nell'errore indica quale scope serve.
| Scope | Cosa consente |
|---|---|
messages:send | Inviare messaggi e batch e annullare i messaggi in attesa: POST /messages, POST /messages/batch, DELETE /messages/{id} |
messages:read | Leggere i messaggi e il loro stato (GET /messages, GET /messages/{id}) e gestire gli endpoint dei webhook |
reminders | Creare, elencare, modificare, mettere in pausa ed eliminare promemoria |
numbers | Elencare i numeri, vederne la connessione e collegare numeri WhatsApp |
media | Caricare, elencare ed eliminare file nella Directory media |
contacts | Verifiche dei numeri (gli endpoint per i contatti arriveranno più avanti) |
GET /me non richiede uno scope particolare. Per inviare a un contatto salvato con to.contact_id basta messages:send.
Chiavi limitate ad alcuni numeri#
Una chiave limitata ad alcuni numeri funziona solo con quelli:
- Invia solo da quei numeri, ed elenca, legge e annulla solo i loro messaggi. Un altro numero in
fromricevenumber_not_allowed. GET /numberselenca solo quei numeri. Può ricollegarli, ma non può aggiungere un nuovo numero.- Vede e modifica solo i promemoria che inviano da quei numeri, e un nuovo promemoria deve indicarne uno come
from. - Non può gestire gli endpoint dei webhook, perché ricevono gli eventi dell'intero spazio di lavoro.
GET /me mostra limited_to_numbers e i number_ids che la chiave può usare.
Richieste#
- JSON in ingresso e in uscita. Invia i body come
Content-Type: application/json. L'unica eccezione è il caricamento di un file, che usamultipart/form-data. Ogni risposta è in JSON, errori compresi. - I nomi dei campi sono in
snake_casee i campi sconosciuti vengono rifiutati: un errore di battitura cometxtrispondevalidation_failedinvece di essere ignorato. - I numeri di telefono sono in formato internazionale con
+(E.164), per esempio+919876543210. Spazi e trattini sono consentiti; un numero senza+viene rifiutato coninvalid_phone. - Gli orari sono in ISO 8601 con un offset, per esempio
2026-10-20T09:30:00+05:30o2026-10-20T04:00:00Z. Un orario senza offset viene rifiutato coninvalid_datetime. Gli orari nelle risposte sono in UTC e terminano conZ, trannenext_run_atdi un promemoria, che è nel fuso orario del promemoria. - Gli ID sono numeri interi, come l'
iddi un numero (fromquando invii) o l'iddi un messaggio. - I codici di stato significano ciò che dicono:
200OK,201creato,202accettato (in coda),400la richiesta è errata,401la chiave è errata,402nessun messaggio rimasto,403non consentito,404non trovato,409conflitto,413troppo grande,415tipo di contenuto errato,422un valore non può essere usato,429troppe richieste,5xxproblema da parte nostra.
Le risposte contengono Cache-Control: no-store.
Errori#
Ogni errore ha lo stesso formato:
{
"error": {
"code": "invalid_phone",
"message": "This is not a valid phone number. Write it in international format with +, e.g. +919876543210.",
"field": "to.phone",
"docs": "https://wbiztool.com/docs/api/v2/errors/#invalid_phone",
"request_id": "req_4f1c2a9b8e7d6c5b4a392817"
}
}
codeè stabile: usalo nel tuo codice per decidere cosa fare.messageè un testo in inglese per lo sviluppatore e può cambiare.fieldindica il campo a cui si riferisce l'errore (to.phone,to[3].phone,schedule.cron), oppure ènull.docsrimanda al codice nella pagina degli errori.request_idè uguale all'headerX-Request-Id. Indicalo se ci contatti.- Alcuni errori aggiungono dettagli, per esempio
statusinnot_cancellableoppureusedelimitinstorage_full. Quando una richiesta ha più problemi,errorselenca gli altri, ciascuno confieldemessage.
Ogni codice, il suo stato HTTP e cosa fare sono nella pagina degli errori.
Idempotency-Key#
Un errore di rete o un timeout ti lascia nel dubbio se una richiesta sia andata a buon fine. Invia un header Idempotency-Key con una POST che crea qualcosa, e potrai inviarla di nuovo in tutta sicurezza:
curl -X POST https://wbiztool.com/api/v2/messages \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-ready" \
-d '{"to": {"phone": "+919876543210"}, "text": "Hi Asha, your order #1042 is ready."}'
- Il valore lo scegli tu: qualsiasi stringa univoca da 1 a 255 caratteri stampabili, come un UUID o il tuo ID d'ordine. Creane uno nuovo per ogni nuova richiesta e riusalo solo per un nuovo tentativo della stessa richiesta.
- Un nuovo tentativo riceve la prima risposta con l'header
Idempotent-Replayed: true. Niente viene fatto due volte: nessun secondo messaggio, promemoria, file o endpoint. - Le chiavi durano 24 ore dalla prima richiesta e appartengono alla tua chiave API: un'altra chiave API dello spazio di lavoro può usare lo stesso valore senza conflitti.
- Stessa chiave, richiesta diversa: una richiesta con una chiave già usata per un metodo, un percorso o un body diversi risponde
422idempotency_key_reused. - Ancora in corso: mentre la prima richiesta con quella chiave è ancora in elaborazione, un nuovo tentativo risponde
409idempotency_in_progressconRetry-After: 1. Attendi un momento e inviala di nuovo. - Gli errori non vengono conservati. Se la prima richiesta ha risposto con un errore, non viene salvato nulla: correggi la richiesta e inviala di nuovo con la stessa chiave.
- I secret non vengono ripetuti. La ripetizione di
POST /webhooksomette ilsecretdell'endpoint, che viene mostrato solo nella prima risposta.
Funziona con POST /messages, POST /messages/batch, POST /numbers, POST /reminders, POST /media, POST /number-checks e POST /webhooks, ed è facoltativo in ciascuna. Le altre richieste ignorano l'header. Un valore vuoto o troppo lungo risponde 400 invalid_idempotency_key.
Limiti di richieste#
Ogni chiave può fare 60 richieste al minuto e 10.000 richieste al giorno. Sono finestre fisse: la finestra del minuto inizia allo scoccare del minuto, quella del giorno alle 00:00 UTC. Oltre un limite, la richiesta risponde 429 rate_limited.
Le risposte alle richieste con una chiave valida contengono questi header:
| Header | Significato |
|---|---|
RateLimit-Limit | Richieste consentite nella finestra corrente (60, oppure 10000 una volta raggiunto il limite giornaliero) |
RateLimit-Remaining | Richieste rimaste in quella finestra |
RateLimit-Reset | Secondi prima che quella finestra ricominci |
RateLimit-Policy | Entrambi i limiti: 60;w=60, 10000;w=86400 |
Retry-After | Con un 429: secondi da attendere prima di riprovare |
Indipendentemente da questi:
- Chiavi errate: oltre 30 richieste al minuto con una chiave errata da un indirizzo IP rispondono
429too_many_auth_failuresconRetry-After: 60. - Messaggi per numero: un numero invia al massimo 1.000 messaggi in 24 ore (uso corretto). Un invio oltre questo limite risponde
429number_daily_cap_reached.
Paginazione#
Gli elenchi che possono crescere (GET /messages, /reminders, /media, /number-checks e /results di una verifica) arrivano in pagine, dal più recente:
{
"data": [ … ],
"next_cursor": "eyJpZCI6OTgxNzI2MywidCI6IjIwMjYtMTAtMThUMTA6MTU6MDIuMzExWiIsImYiOiI0NGIxMzZmYTM1NWIifQ"
}
limitimposta la dimensione della pagina, da 1 a 100 (predefinito 25).- Per ottenere la pagina successiva, invia la stessa richiesta con
cursorimpostato alnext_cursordell'ultima pagina.next_cursorènullnell'ultima pagina. - Mantieni invariati gli altri filtri: un cursore usato con filtri diversi risponde
400invalid_cursor. Ricomincia senza cursore. - Tratta il cursore come una stringa opaca. Gli elementi aggiunti mentre scorri le pagine non spostano le pagine.
curl "https://wbiztool.com/api/v2/messages?limit=100&cursor=eyJpZCI6OTgxNzI2MywidCI6..." \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"
GET /numbers e GET /webhooks restituiscono tutto in un unico elenco data.
ID delle richieste#
Ogni risposta, errori compresi, ha un header X-Request-Id come req_4f1c2a9b8e7d6c5b4a392817. Gli errori riportano lo stesso valore come request_id. Registralo nei tuoi log e indicalo se ci contatti: ci permette di trovare la richiesta nei nostri log, che registrano l'id della tua chiave ma mai la chiave stessa.
Se invii un tuo X-Request-Id (fino a 100 caratteri stampabili), torna indietro come X-Client-Request-Id, così puoi abbinare le risposte ai tuoi log.
Modalità test#
Una chiave di test (wbz_test_…) ti permette di sviluppare e provare un'integrazione senza inviare nulla. Creane una in Impostazioni → Chiavi API con Tipo di chiave: Test. GET /me mostra "mode": "test".
Cosa fa una chiave di test come una chiave live:
POST /messagesePOST /messages/batchcontrollano tutto ciò che controlla un invio live: il destinatario, il testo, i media,send_atedexpires_at, il numero mittente, e gli scope e i numeri della chiave. Gli stessi errori ricevono le stesse risposte di errore.- Scope, numeri, limiti di richieste e
Idempotency-Keyfunzionano allo stesso modo. - Ogni lettura del resto dello spazio di lavoro (
GET /me,/numbers,/reminders,/media,/number-checks,/webhooks) mostra i dati reali, in sola lettura.
Cosa cambia:
- Non viene inviato nulla. Un invio di test viene invece conservato come messaggio di test e non consuma i messaggi del piano né i 1.000 giornalieri del numero, quindi non riceve mai
no_creditsonumber_daily_cap_reached. - Il suo stato avanza da solo:
queued, poisent5 secondi dopo edelivered15 secondi dopo la creazione (contati dasend_atper un messaggio pianificato). Un messaggio il cuiexpires_atarriva prima dell'invio diventaexpired. I messaggi di test non diventano maireadofailed. - Una chiave di test vede solo i propri messaggi di test.
GET /messageseGET /messages/{id}mostrano solo quelli, eDELETE /messages/{id}ne annulla uno finché èqueuedoscheduled. Le chiavi live non vedono mai i messaggi di test. Il filtrostatusdiGET /messagesnon è supportato per le chiavi di test e rispondetest_mode_unsupported;number,sinceeuntilfunzionano. - Le altre scritture vengono rifiutate con
403test_mode_unsupported: collegare un numero, creare, modificare o eliminare promemoria, caricare o eliminare media, avviare una verifica dei numeri e aggiungere, rimuovere, ruotare o testare endpoint dei webhook. - Nessun evento webhook viene inviato per i messaggi di test.
- I messaggi di test vengono conservati per 30 giorni.
Risorse#
- Messaggi: invia ora o più tardi, invia fino a 1.000 destinatari, leggi la cronologia, annulla.
- Numeri: elenca i tuoi numeri WhatsApp e account Telegram e collega un numero WhatsApp con codice QR o codice di abbinamento.
- Promemoria: messaggi ricorrenti con una pianificazione cron.
- File multimediali: carica i file una volta e inviali tramite
media_id. - Verifiche dei numeri: scopri quali numeri sono su WhatsApp.
- Webhook: eventi firmati quando un messaggio viene inviato, non riesce, viene annullato o scade.
- Errori: tutti i codici di errore.
- Passare dalla v1 alla v2: ogni endpoint e campo della v1 e il suo equivalente nella v2.
