Zum Inhalt springen
WbizTool

API v2 (Beta)

API v2

API v2 ist die neue REST-API von WbizTool: ein Schlüssel pro App mit genau dem Zugriff, den sie braucht, ressourcenorientierte URLs, echte HTTP-Statuscodes, signierte JSON-Webhooks und sichere Wiederholungen. Diese Seite beschreibt, was alle Requests gemeinsam haben. Die einzelnen Endpoints finden Sie auf den Ressourcenseiten.

Basis-URL#

https://wbiztool.com/api/v2

Pfade haben keinen abschließenden Schrägstrich (/api/v2/messages), einer wird aber ebenfalls akzeptiert. Eine Adresse, die es nicht gibt, antwortet mit 404 und dem Code not_found.

Kurzes Beispiel#

Prüfen Sie Ihren Schlüssel mit GET /me. Das funktioniert mit jedem Scope und sendet nichts:

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 ist null, wenn der Plan unbegrenzt viele Nachrichten sendet. plan ist null, wenn der Arbeitsbereich keinen aktiven Plan hat.

Schlüssel#

Senden Sie Ihren Schlüssel bei jedem Request im Header Authorization:

Authorization: Bearer wbz_live_…

Eine client_id gibt es nicht: Der Schlüssel bestimmt seinen Arbeitsbereich. Ein v2-Schlüssel beginnt mit wbz_live_ oder wbz_test_, gefolgt von 38 Buchstaben und Ziffern. v1-Schlüssel funktionieren nicht mit v2 (sie erhalten v1_key_on_v2), und v2-Schlüssel funktionieren nicht mit v1.

Schlüssel erstellen#

Inhaber erstellen Schlüssel unter Einstellungen → API-Schlüssel in der Karte API-v2-Schlüssel: Klicken Sie auf v2-Schlüssel erstellen und wählen Sie dann:

  • Name: die App, die ihn nutzen wird, bis zu 50 Zeichen.
  • Art des Schlüssels: Live sendet echte Nachrichten; Test prüft alles und sendet nichts (siehe Testmodus).
  • Was er darf: die Scopes oder Alles.
  • Nummern, die er nutzen darf: alle Nummern, auch später hinzugefügte, oder nur einige (siehe Auf einige Nummern beschränkte Schlüssel).
  • Läuft ab: nie oder in 30 Tagen, 90 Tagen oder 1 Jahr.

Der Schlüssel wird nur einmal angezeigt. Kopieren Sie ihn sofort und speichern Sie ihn auf Ihrem Server, zum Beispiel in einer Umgebungsvariablen. WbizTool speichert nur einen Hash und seine letzten vier Zeichen, ein verlorener Schlüssel kann also nicht erneut angezeigt werden: Widerrufen Sie ihn und erstellen Sie einen neuen.

Ein Arbeitsbereich kann bis zu 10 nicht widerrufene v2-Schlüssel haben. Die Karte zeigt für jeden Schlüssel die letzten vier Zeichen, Scopes, Nummern, das Ablaufdatum und wann und von welcher IP-Adresse er zuletzt verwendet wurde. Widerrufen sperrt einen Schlüssel sofort und mit ihm die Webhook-Endpunkte, die er angelegt hat. Ein Schlüssel nach seinem Ablaufdatum erhält api_key_expired.

Scopes#

Jeder Schlüssel darf nur, was seine Scopes erlauben. Ein Request außerhalb davon antwortet mit 403 und missing_scope, und required_scope im Fehler nennt den benötigten Scope.

ScopeWas er erlaubt
messages:sendNachrichten und Batches senden und wartende Nachrichten stornieren: POST /messages, POST /messages/batch, DELETE /messages/{id}
messages:readNachrichten und ihren Status lesen (GET /messages, GET /messages/{id}) und Webhook-Endpunkte verwalten
remindersErinnerungen erstellen, auflisten, ändern, pausieren und löschen
numbersNummern auflisten, ihre Verbindung sehen und WhatsApp-Nummern verbinden
mediaDateien im Medienverzeichnis hochladen, auflisten und löschen
contactsNummernprüfungen (Kontakt-Endpoints folgen später)

GET /me braucht keinen bestimmten Scope. Für das Senden an einen gespeicherten Kontakt mit to.contact_id genügt messages:send.

Auf einige Nummern beschränkte Schlüssel#

Ein Schlüssel, der auf einige Nummern beschränkt ist, funktioniert nur mit diesen:

  • Er sendet nur von diesen Nummern und listet, liest und storniert nur ihre Nachrichten. Eine andere Nummer in from erhält number_not_allowed.
  • GET /numbers listet nur diese Nummern auf. Er kann sie neu verbinden, aber keine neue Nummer hinzufügen.
  • Er sieht und ändert nur die Erinnerungen, die von diesen Nummern senden, und eine neue Erinnerung muss eine davon als from angeben.
  • Webhook-Endpunkte kann er gar nicht verwalten, weil diese die Ereignisse des gesamten Arbeitsbereichs empfangen.

GET /me zeigt limited_to_numbers und die number_ids, die der Schlüssel nutzen darf.

Requests#

  • JSON hin und zurück. Senden Sie Bodys als Content-Type: application/json. Die einzige Ausnahme ist das Hochladen einer Datei, das multipart/form-data verwendet. Jede Antwort ist JSON, auch Fehler.
  • Feldnamen sind snake_case, und unbekannte Felder werden abgelehnt: Ein Tippfehler wie txt antwortet mit validation_failed, statt ignoriert zu werden.
  • Telefonnummern stehen im internationalen Format mit + (E.164), zum Beispiel +919876543210. Leerzeichen und Bindestriche sind erlaubt; eine Nummer ohne + wird mit invalid_phone abgelehnt.
  • Zeiten sind ISO 8601 mit Offset, zum Beispiel 2026-10-20T09:30:00+05:30 oder 2026-10-20T04:00:00Z. Eine Zeit ohne Offset wird mit invalid_datetime abgelehnt. Zeiten in Antworten sind in UTC und enden auf Z, außer next_run_at einer Erinnerung, das in der Zeitzone der Erinnerung angegeben ist.
  • IDs sind Ganzzahlen, etwa die id einer Nummer (from beim Senden) oder die id einer Nachricht.
  • Statuscodes bedeuten, was sie sagen: 200 OK, 201 erstellt, 202 angenommen (in der Warteschlange), 400 der Request ist fehlerhaft, 401 der Schlüssel ist falsch, 402 keine Nachrichten mehr übrig, 403 nicht erlaubt, 404 nicht gefunden, 409 Konflikt, 413 zu groß, 415 falscher Content-Type, 422 ein Wert kann nicht verwendet werden, 429 zu viele Requests, 5xx ein Fehler auf unserer Seite.

Antworten enthalten Cache-Control: no-store.

Fehler#

Jeder Fehler hat dasselbe Format:

{
  "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 ist stabil: Verzweigen Sie in Ihrem Code danach. message ist englischer Text für Entwickler und kann sich ändern.
  • field nennt das Feld, um das es im Fehler geht (to.phone, to[3].phone, schedule.cron), oder ist null.
  • docs verlinkt den Code auf der Fehlerseite.
  • request_id ist derselbe Wert wie im Header X-Request-Id. Geben Sie ihn an, wenn Sie uns kontaktieren.
  • Manche Fehler enthalten zusätzliche Angaben, zum Beispiel status bei not_cancellable oder used und limit bei storage_full. Hat ein Request mehrere Probleme, listet errors die übrigen auf, jeweils mit field und message.

Alle Codes, ihr HTTP-Status und was zu tun ist, stehen auf der Fehlerseite.

Idempotency-Key#

Nach einem Netzwerkfehler oder Timeout wissen Sie nicht, ob ein Request funktioniert hat. Senden Sie bei einem POST, der etwas erstellt, einen Header Idempotency-Key mit, dann können Sie ihn gefahrlos erneut senden:

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."}'
  • Den Wert bestimmen Sie: eine beliebige eindeutige Zeichenfolge aus 1 bis 255 druckbaren Zeichen, etwa eine UUID oder Ihre eigene Bestellnummer. Erzeugen Sie für jeden neuen Request einen neuen Wert und verwenden Sie ihn nur für eine Wiederholung desselben Requests erneut.
  • Eine Wiederholung erhält die erste Antwort zurück, mit dem Header Idempotent-Replayed: true. Nichts wird doppelt ausgeführt: keine zweite Nachricht, Erinnerung, Datei oder kein zweiter Endpunkt.
  • Keys gelten 24 Stunden ab dem ersten Request und gehören zu Ihrem API-Schlüssel: Ein anderer API-Schlüssel des Arbeitsbereichs kann denselben Wert ohne Konflikt verwenden.
  • Gleicher Key, anderer Request: Ein Request mit einem Key, der bereits für eine andere Methode, einen anderen Pfad oder Body verwendet wurde, antwortet mit 422 idempotency_key_reused.
  • Noch in Bearbeitung: Solange der erste Request mit dem Key noch bearbeitet wird, antwortet eine Wiederholung mit 409 idempotency_in_progress und Retry-After: 1. Warten Sie einen Moment und senden Sie ihn erneut.
  • Fehler werden nicht gespeichert. Hat der erste Request mit einem Fehler geantwortet, wird nichts gespeichert: Korrigieren Sie den Request und senden Sie ihn mit demselben Key erneut.
  • Secrets werden nicht wiederholt. Eine Wiederholung von POST /webhooks lässt das secret des Endpunkts weg, das nur in der ersten Antwort angezeigt wird.

Das funktioniert bei POST /messages, POST /messages/batch, POST /numbers, POST /reminders, POST /media, POST /number-checks und POST /webhooks und ist jeweils optional. Andere Requests ignorieren den Header. Ein leerer oder zu langer Wert antwortet mit 400 invalid_idempotency_key.

Rate-Limits#

Jeder Schlüssel kann 60 Requests pro Minute und 10.000 Requests pro Tag stellen. Das sind feste Zeitfenster: Das Minutenfenster beginnt mit der vollen Minute, das Tagesfenster um 00:00 UTC. Über einem Limit antwortet der Request mit 429 rate_limited.

Antworten auf Requests mit gültigem Schlüssel enthalten diese Header:

HeaderBedeutung
RateLimit-LimitIm aktuellen Fenster erlaubte Requests (60, oder 10000, sobald das Tageslimit erreicht ist)
RateLimit-RemainingVerbleibende Requests in diesem Fenster
RateLimit-ResetSekunden, bis dieses Fenster neu beginnt
RateLimit-PolicyBeide Limits: 60;w=60, 10000;w=86400
Retry-AfterBei einem 429: Sekunden, die Sie vor dem nächsten Versuch warten sollten

Unabhängig davon gilt:

  • Falsche Schlüssel: Mehr als 30 Requests pro Minute mit einem falschen Schlüssel von einer IP-Adresse antworten mit 429 too_many_auth_failures und Retry-After: 60.
  • Nachrichten pro Nummer: Eine Nummer sendet höchstens 1.000 Nachrichten in 24 Stunden (Fair Use). Ein Senden darüber hinaus antwortet mit 429 number_daily_cap_reached.

Seitenweise Abfrage#

Listen, die wachsen können (GET /messages, /reminders, /media, /number-checks und die /results einer Prüfung), kommen in Seiten, die neuesten zuerst:

{
  "data": [ … ],
  "next_cursor": "eyJpZCI6OTgxNzI2MywidCI6IjIwMjYtMTAtMThUMTA6MTU6MDIuMzExWiIsImYiOiI0NGIxMzZmYTM1NWIifQ"
}
  • limit legt die Seitengröße fest, von 1 bis 100 (Standard 25).
  • Für die nächste Seite senden Sie denselben Request mit cursor, gesetzt auf den next_cursor der letzten Seite. Auf der letzten Seite ist next_cursor null.
  • Lassen Sie die übrigen Filter gleich: Ein Cursor mit anderen Filtern antwortet mit 400 invalid_cursor. Beginnen Sie dann ohne Cursor neu.
  • Behandeln Sie den Cursor als undurchsichtige Zeichenfolge. Einträge, die während des Blätterns hinzukommen, verschieben die Seiten nicht.
curl "https://wbiztool.com/api/v2/messages?limit=100&cursor=eyJpZCI6OTgxNzI2MywidCI6..." \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

GET /numbers und GET /webhooks liefern alles in einer einzigen data-Liste.

Request-IDs#

Jede Antwort, auch jeder Fehler, hat einen Header X-Request-Id wie req_4f1c2a9b8e7d6c5b4a392817. Fehler enthalten denselben Wert als request_id. Protokollieren Sie ihn und geben Sie ihn an, wenn Sie uns kontaktieren: Damit finden wir den Request in unseren Logs, die die ID Ihres Schlüssels speichern, aber nie den Schlüssel selbst.

Wenn Sie eine eigene X-Request-Id senden (bis zu 100 druckbare Zeichen), kommt sie als X-Client-Request-Id zurück, sodass Sie Antworten Ihren eigenen Logs zuordnen können.

Testmodus#

Mit einem Testschlüssel (wbz_test_…) entwickeln und testen Sie eine Integration, ohne etwas zu senden. Erstellen Sie ihn unter Einstellungen → API-Schlüssel mit Art des Schlüssels: Test. GET /me zeigt "mode": "test".

Was ein Testschlüssel wie ein Live-Schlüssel tut:

  • POST /messages und POST /messages/batch prüfen alles, was auch ein echtes Senden prüft: den Empfänger, den Text, Medien, send_at und expires_at, die sendende Nummer sowie die Scopes und Nummern des Schlüssels. Dieselben Fehler ergeben dieselben Fehlermeldungen.
  • Scopes, Nummern, Rate-Limits und Idempotency-Key funktionieren genauso.
  • Jeder Lesezugriff auf den übrigen Arbeitsbereich (GET /me, /numbers, /reminders, /media, /number-checks, /webhooks) zeigt die echten Daten, nur lesend.

Was anders ist:

  • Nichts wird gesendet. Ein Testversand wird stattdessen als Testnachricht gespeichert und verbraucht weder die Nachrichten des Plans noch die täglichen 1.000 der Nummer. Er erhält also nie no_credits oder number_daily_cap_reached.
  • Der Status ändert sich von selbst: queued, dann sent 5 Sekunden und delivered 15 Sekunden nach dem Erstellen (bei einer geplanten Nachricht ab send_at gezählt). Eine Nachricht, deren expires_at vor dem Senden liegt, wird expired. Testnachrichten werden nie read oder failed.
  • Ein Testschlüssel sieht nur seine eigenen Testnachrichten. GET /messages und GET /messages/{id} zeigen diese und sonst nichts, und DELETE /messages/{id} storniert eine, solange sie queued oder scheduled ist. Live-Schlüssel sehen Testnachrichten nie. Der Filter status von GET /messages wird für Testschlüssel nicht unterstützt und antwortet mit test_mode_unsupported; number, since und until funktionieren.
  • Andere Schreibzugriffe werden abgelehnt, mit 403 test_mode_unsupported: eine Nummer verbinden, Erinnerungen erstellen, ändern oder löschen, Medien hochladen oder löschen, eine Nummernprüfung starten sowie Webhook-Endpunkte hinzufügen, entfernen, rotieren oder testen.
  • Keine Webhook-Ereignisse werden für Testnachrichten gesendet.
  • Testnachrichten werden 30 Tage aufbewahrt.

Ressourcen#

  • Nachrichten: jetzt oder später senden, an bis zu 1.000 Empfänger senden, den Verlauf lesen, stornieren.
  • Nummern: Ihre WhatsApp-Nummern und Telegram-Konten auflisten und eine WhatsApp-Nummer per QR-Code oder Kopplungscode verbinden.
  • Erinnerungen: wiederkehrende Nachrichten nach einem Cron-Zeitplan.
  • Medien: Dateien einmal hochladen und per media_id senden.
  • Nummernprüfungen: herausfinden, welche Nummern WhatsApp nutzen.
  • Webhooks: signierte Ereignisse, wenn eine Nachricht gesendet wird, fehlschlägt, storniert wird oder abläuft.
  • Fehler: alle Fehlercodes.
  • Von v1 zu v2 wechseln: jeder v1-Endpoint und jedes v1-Feld mit seiner Entsprechung in v2.