Vai al contenuto
WbizTool

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"
{
  "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.

ScopeCosa consente
messages:sendInviare messaggi e batch e annullare i messaggi in attesa: POST /messages, POST /messages/batch, DELETE /messages/{id}
messages:readLeggere i messaggi e il loro stato (GET /messages, GET /messages/{id}) e gestire gli endpoint dei webhook
remindersCreare, elencare, modificare, mettere in pausa ed eliminare promemoria
numbersElencare i numeri, vederne la connessione e collegare numeri WhatsApp
mediaCaricare, elencare ed eliminare file nella Directory media
contactsVerifiche 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 from riceve number_not_allowed.
  • GET /numbers elenca 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 usa multipart/form-data. Ogni risposta è in JSON, errori compresi.
  • I nomi dei campi sono in snake_case e i campi sconosciuti vengono rifiutati: un errore di battitura come txt risponde validation_failed invece 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 con invalid_phone.
  • Gli orari sono in ISO 8601 con un offset, per esempio 2026-10-20T09:30:00+05:30 o 2026-10-20T04:00:00Z. Un orario senza offset viene rifiutato con invalid_datetime. Gli orari nelle risposte sono in UTC e terminano con Z, tranne next_run_at di un promemoria, che è nel fuso orario del promemoria.
  • Gli ID sono numeri interi, come l'id di un numero (from quando invii) o l'id di un messaggio.
  • I codici di stato significano ciò che dicono: 200 OK, 201 creato, 202 accettato (in coda), 400 la richiesta è errata, 401 la chiave è errata, 402 nessun messaggio rimasto, 403 non consentito, 404 non trovato, 409 conflitto, 413 troppo grande, 415 tipo di contenuto errato, 422 un valore non può essere usato, 429 troppe richieste, 5xx problema 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.
  • field indica il campo a cui si riferisce l'errore (to.phone, to[3].phone, schedule.cron), oppure è null.
  • docs rimanda al codice nella pagina degli errori.
  • request_id è uguale all'header X-Request-Id. Indicalo se ci contatti.
  • Alcuni errori aggiungono dettagli, per esempio status in not_cancellable oppure used e limit in storage_full. Quando una richiesta ha più problemi, errors elenca gli altri, ciascuno con field e message.

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 422 idempotency_key_reused.
  • Ancora in corso: mentre la prima richiesta con quella chiave è ancora in elaborazione, un nuovo tentativo risponde 409 idempotency_in_progress con Retry-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 /webhooks omette il secret dell'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:

HeaderSignificato
RateLimit-LimitRichieste consentite nella finestra corrente (60, oppure 10000 una volta raggiunto il limite giornaliero)
RateLimit-RemainingRichieste rimaste in quella finestra
RateLimit-ResetSecondi prima che quella finestra ricominci
RateLimit-PolicyEntrambi i limiti: 60;w=60, 10000;w=86400
Retry-AfterCon 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 429 too_many_auth_failures con Retry-After: 60.
  • Messaggi per numero: un numero invia al massimo 1.000 messaggi in 24 ore (uso corretto). Un invio oltre questo limite risponde 429 number_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"
}
  • limit imposta la dimensione della pagina, da 1 a 100 (predefinito 25).
  • Per ottenere la pagina successiva, invia la stessa richiesta con cursor impostato al next_cursor dell'ultima pagina. next_cursor è null nell'ultima pagina.
  • Mantieni invariati gli altri filtri: un cursore usato con filtri diversi risponde 400 invalid_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 /messages e POST /messages/batch controllano tutto ciò che controlla un invio live: il destinatario, il testo, i media, send_at ed expires_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-Key funzionano 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_credits o number_daily_cap_reached.
  • Il suo stato avanza da solo: queued, poi sent 5 secondi dopo e delivered 15 secondi dopo la creazione (contati da send_at per un messaggio pianificato). Un messaggio il cui expires_at arriva prima dell'invio diventa expired. I messaggi di test non diventano mai read o failed.
  • Una chiave di test vede solo i propri messaggi di test. GET /messages e GET /messages/{id} mostrano solo quelli, e DELETE /messages/{id} ne annulla uno finché è queued o scheduled. Le chiavi live non vedono mai i messaggi di test. Il filtro status di GET /messages non è supportato per le chiavi di test e risponde test_mode_unsupported; number, since e until funzionano.
  • Le altre scritture vengono rifiutate con 403 test_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.