Whapier

Entwickler

API-Dokumentation

Eine REST-API mit Token-Authentifizierung für Nachrichten, Vorlagen, Kontakte, Kampagnen, Flows sowie Zustellstatus und Kosten je Nachricht. Legen Sie unter Entwicklerwerkzeuge in Ihrem Konto einen API-Schlüssel an und authentifizieren Sie jeden Aufruf mit Authorization: Bearer <token>.

Vollständige Beispiele in PHP, Node.js, Python, Java und Ruby finden Sie in der Dokumentation in der App, sobald Sie ein Konto erstellen.

Maschinenlesbare Referenz: OpenAPI 3.1 (JSON) · Postman-Sammlung

Bevor Sie beginnen

Authentifizierung

Jede Anfrage trägt einen API-Schlüssel als Bearer-Token im Authorization-Header. Schlüssel werden unter Entwicklertools > API-Schlüssel erstellt und nur einmal angezeigt.

Ein Schlüssel hat Scopes: read (jedes GET), send (die Sende-Endpunkte, Kampagnen und Flow-Starts) und manage (Anlegen, Ändern und Löschen von Kontakten, Gruppen, automatischen Antworten, Webhooks und Vorlagen sowie die Inbox-Aktionen). Ein Schlüssel ohne den Scope erhält 403 mit dem Namen des fehlenden Scopes.

Ein Schlüssel kann ablaufen: ein abgelaufener Schlüssel erhält 401 mit "This API key has expired". Ein fehlendes oder unbekanntes Token ist ebenfalls 401.

Ein Sandbox-Schlüssel validiert jede Anfrage, speichert die Nachricht mit dem Status "sandbox" und sendet nichts an WhatsApp - entwickeln Sie gegen die echte API ohne WhatsApp-Leitung und ohne Kosten.

Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>
Rate-Limit

60 Anfragen pro Minute je API-Schlüssel; Anfragen ohne Schlüssel werden je IP-Adresse gezählt.

Jede Antwort trägt X-RateLimit-Limit und X-RateLimit-Remaining. Über dem Limit ist die Antwort 429 mit statusCode 429, einer message und einem Retry-After-Header in Sekunden.

GET /api/usage meldet das Limit unter rate_limit.per_minute. /api und /api/v2 teilen sich ein Kontingent je Schlüssel.

HTTP/1.1 429 Too Many Requests
Retry-After: 42
{"statusCode": 429, "message": "Too many requests. Try again in 42 seconds."}
Idempotenz

Senden Sie einen Idempotency-Key-Header (1 bis 128 Zeichen, eindeutig je Vorgang) an die POST-Endpunkte, die etwas anlegen: die Sendungen, Kampagnen, Kontakte, Gruppen und automatischen Antworten.

Derselbe Schlüssel mit derselben Anfrage innerhalb von 24 Stunden liefert die gespeicherte Antwort mit dem Header Idempotent-Replayed: true, und nichts wird erneut ausgeführt. Ein Client, der nach einem Timeout erneut sendet, sendet nicht mehr doppelt.

Derselbe Schlüssel mit einer anderen Anfrage ist 422; derselbe Schlüssel, während die erste Anfrage noch läuft, ist 409. Nur 2xx- und 4xx-Antworten werden gespeichert, ein 5xx kann also mit demselben Schlüssel wiederholt werden.

Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Datumsangaben und Zeitzonen

Jedes Datum, das die API zurückgibt, ist UTC in ISO-8601 mit Offset, unabhängig von der Zeitzone, die die Organisation im Dashboard verwendet.

Datumsangaben, die Sie senden (scheduled_at, since), werden als UTC gelesen, sofern sie keinen Offset tragen.

"created_at": "2026-10-05T09:30:00+00:00"
Fehler

Jede Antwort ist JSON mit statusCode und message; ein abgelehnter Payload ergänzt errors, eine Zuordnung von Feldname zur Liste der Probleme.

400 ungültige Eingabe; 401 Schlüssel fehlt, ungültig oder abgelaufen; 403 Scope, Abonnement, Planlimit oder Konto in Prüfung; 404 unbekannte uuid oder eine, die zu einem anderen Arbeitsbereich gehört; 409 Konflikt (ein nicht möglicher Kampagnenübergang, ein noch laufender Idempotency-Key); 422 durch eine Regel abgelehnt (das 24-Stunden-Fenster, STOP, Vorlagenvariablen); 429 Rate-Limit; 500 unser Fehler.

Die Inbox-Aktionen (assign, close und reopen auf /api/conversations/{contact_uuid}) antworten 409, solange das Ticketing unter Einstellungen > Tickets ausgeschaltet ist; die Konversation lesen und eine Notiz hinzufügen funktionieren in jedem Fall.

Auf /api (v1) ist eine Ablehnung durch WhatsApp selbst ein 200 mit data.success false und dem Grund in data.data.error (code, message, type). Auf /api/v2 ist dieselbe Ablehnung ein HTTP 422 - siehe Versionierung.

{"statusCode": 400, "message": "The given data was invalid.", "errors": {"phone": ["The phone number is not valid."]}}
Paginierung

Die Listen-Endpunkte nehmen page (ab 1) und per_page (Standard 10, max. 100; /api/messages standardmäßig 25) und sind nach neuesten zuerst sortiert.

Kontakte, Gruppen, automatische Antworten, Vorlagen, Kampagnen und Kampagnenprotokolle antworten mit data, links und meta (current_page, last_page, per_page, total). /api/messages antwortet mit statusCode, data und meta (page, per_page, total, last_page).

Eine Konversation wird stattdessen per Cursor geblättert: GET /api/contacts/{uuid}/messages und GET /api/conversations/{contact_uuid} antworten neueste zuerst mit next_before; übergeben Sie es als before, um die älteren Nachrichten zu erhalten.

Eine Vorlage senden

Ein Vorlagenversand muss genau so viele Parameter tragen, wie die genehmigte Vorlage Platzhalter hat; eine Abweichung lehnt Meta mit dem Fehler 132000 ab.

GET /api/templates/{uuid} liefert example_payload: einen vollständigen Body für POST /api/send/template mit der richtigen Zahl von Parametern für Header, Body und URL-Buttons - ersetzen Sie die Werte und senden Sie ihn.

POST /api/templates reicht eine Vorlage aus einer flachen JSON-Form bei Meta ein und antwortet mit Metas Begründung, wenn sie abgelehnt wird; POST /api/templates/sync holt die Vorlagen nach einer Änderung im Meta Business Manager von Meta.

GET https://whapier.com/api/templates/{{uuid}}
{"data": {"name": "order_update", "variables": {"header": 0, "body": 1, "buttons": 0}, "example_payload": {"phone": "+40721000001", "template": {"name": "order_update", "language": {"code": "en"}, "components": [{"type": "body", "parameters": [{"type": "text", "text": "Ana"}]}]}}}}
Webhooks

Ausgehende Webhooks werden unter Entwicklertools > Webhooks oder über die API (POST /api/webhooks) eingerichtet: eine https-URL und die zu empfangenden Ereignisse. Das Signatur-Secret wird für Sie erzeugt und einmal gezeigt. Jede Zustellung ist ein POST mit einem JSON-Body, der event und data trägt.

Der X-Whapier-Signature-Header ist "sha256=" gefolgt vom HMAC-SHA256 des rohen Request-Bodys mit diesem Secret, in Hex. Berechnen Sie ihn über die empfangenen Bytes neu und vergleichen Sie, bevor Sie dem Payload vertrauen.

Antworten Sie innerhalb von 15 Sekunden mit 2xx. Eine fehlgeschlagene Zustellung wird zweimal wiederholt, nach 60 Sekunden und nach 5 Minuten; nach dem dritten Fehlschlag wird das Ereignis verworfen.

Die Ereignisse: message.received und message.sent; message.status, wenn Meta eine Nachricht als delivered, read oder failed meldet (mit dem Fehler und der Kampagne, aus der sie stammt); campaign.finished mit den Endzahlen; ticket.created und ticket.closed; contact.opted_out und contact.opted_in; contact, group und autoreply created, updated und deleted; template.status.update, template.quality.update und account.update, wie Meta sie sendet. GET /api/webhooks/events listet sie mit einer Beschreibung auf, und POST /api/webhooks/{uuid}/test liefert ein Beispiel.

X-Whapier-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
{"event": "message.status", "data": {"uuid": "64968a32-fdd9-4c1d-8941-b8e538036616", "wam_id": "wamid.HBgM...", "status": "delivered", "timestamp": "2026-10-05T09:30:00+00:00", "failure": null, "contact": {"uuid": "81a2d165-41e2-43f2-847e-d69e08cba0e0", "phone": "+40721000001"}, "campaign": null}}
{"event": "campaign.finished", "data": {"uuid": "3f1c2d0e-5b7a-4c8d-9e0f-1a2b3c4d5e6f", "name": "October offers", "status": "completed", "counts": {"contacts": 120, "sent": 118, "delivered": 110, "read": 64, "failed": 2}, "finished_at": "2026-10-05T09:30:00+00:00"}}
message.received
message.sent
message.status
message.status.update
contact.created
contact.updated
contact.deleted
contact.opted_out
contact.opted_in
group.created
group.updated
group.deleted
autoreply.created
autoreply.updated
autoreply.deleted
campaign.finished
ticket.created
ticket.closed
template.status.update
template.quality.update
account.update
Versionierung: v1 und v2

/api (Version 1) bleibt unverändert unterstützt. /api/v2 bietet dieselben Endpunkte, Payloads und Felder mit einem Unterschied: der HTTP-Status trägt das Ergebnis.

Auf v2 ist eine Ablehnung durch WhatsApp bei einer Sendung ein HTTP 422, dessen Body statusCode 422, die message, error (Code, Nachricht und Typ von WhatsApp) und data (die v1-Antwort) enthält, statt eines 200 mit data.success false. Immer wenn statusCode in einem Body vom HTTP-Status abweicht, folgt der HTTP-Status dem statusCode.

Alles andere - Authentifizierung, Scopes, Rate-Limit, Idempotenz, Datumsangaben, Paginierung - ist identisch, und derselbe Schlüssel funktioniert auf beiden.

POST https://whapier.com/api/v2/send
{"statusCode": 422, "message": "Template name does not exist", "error": {"code": 132001, "message": "Template name does not exist", "type": "OAuthException"}, "data": {"success": false, "message": "Template name does not exist", "data": {"error": {"code": 132001}}}}

Verifizierung

GET /api/verify API-Schlüssel prüfen
# Bestätigt, dass das Bearer-Token gültig und das Abonnement der Organisation aktiv ist, bevor Sie andere Endpunkte aufrufen.
# HTTP 200: Token in Ordnung. 401: Token fehlt/ungültig. 403: Abonnement inaktiv.

curl -X GET \
https://whapier.com/api/verify \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Kontakte

GET /api/contacts Kontaktliste abrufen
# Optionale Query-Parameter: ?page=1&per_page=10 (per_page höchstens 100).
# Neueste zuerst. Antwort: data (Kontaktobjekte), links und meta (current_page, last_page, per_page, total).
# Ein Kontakt: id, uuid, phone, first_name, last_name, email, address, metadata, groups (uuid, name), source, opted_in_at, opted_out_at, created_at, updated_at.
# Suchfilter, mit AND kombiniert: phone (jedes Format, das das Land der Organisation lesen kann; 400, wenn es keine Nummer ist), email (exakt, Groß-/Kleinschreibung egal), q (2 bis 128 Zeichen, gesucht in Name, E-Mail und Nummer), group (die uuid einer Kontaktgruppe; 400, wenn unbekannt), opted_out (true | false), updated_since (ein Datum, UTC), source (api, manual, import, entry point...).

curl -X GET \
"https://whapier.com/api/contacts?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/contacts/{uuid} Einen Kontakt abrufen
# Das Kontaktobjekt von Kontaktliste abrufen plus unread_messages, last_message_at und ticket (status, assigned_to: name, email).
# ticket ist null, solange das Ticketing unter Einstellungen > Tickets ausgeschaltet ist oder die Konversation noch kein Ticket hat. 404, wenn die uuid unbekannt oder gelöscht ist oder zu einem anderen Arbeitsbereich gehört.

curl -X GET \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/contacts Kontakt hinzufügen
# Felder im JSON-Body:
#   phone (Pflichtfeld) — internationale Nummer; wird validiert und als E.164 gespeichert. Muss je Organisation eindeutig sein (400 bei Duplikat).
#   first_name, last_name, email (optional) — weglassen, null oder "" für Kontakte ohne Namen.
#   street, city, state, zip, country (optional) — werden im address-JSON gespeichert.
#   metadata (optional) — beliebiger JSON-serialisierbarer Wert.
#   group (optional) — Array mit UUID-Strings von Kontaktgruppen.
#   marketing_opt_in (optional, boolean) — true erfasst beim Kontakt eine Marketing-Einwilligung (DSGVO-Einwilligungsnachweis, source: api); false erfasst einen Opt-out. Weglassen, um die Einwilligung unverändert zu lassen.
# Antworten: 200 Erfolg { statusCode, id, message }; 400 Validierungsfehler; 403 Abonnement inaktiv oder Kontaktlimit erreicht.
# Akzeptiert einen Idempotency-Key-Header (siehe Bevor Sie beginnen).

curl -X POST \
https://whapier.com/api/contacts \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "first_name": "Ana",
    "last_name": "Pop",
    "email": "ana@example.com",
    "group": [
        "d746e4c5-db24-4fb2-be03-590421344d69"
    ],
    "marketing_opt_in": true
}'
POST /api/contacts/bulk Kontakte in Masse anlegen oder aktualisieren
# contacts (erforderlich, 1 bis 500 Objekte) mit den Feldern von Kontakt hinzufügen pro Zeile. Eine Zeile, deren phone der Arbeitsbereich schon hat, wird mit den vorhandenen Feldern aktualisiert (wie bei Kontakt bearbeiten); eine neue Nummer wird angelegt.
# Jede Zeile steht für sich: eine fehlerhafte Zeile scheitert allein, die anderen gehen durch. Antwort: { statusCode, created, updated, failed: [ { index, phone, errors } ], limit_reached, message }.
# Das Anlegen endet am Kontaktlimit des Plans: limit_reached ist dann true, und die Zeilen, die nicht mehr passten, stehen in failed. Aktualisierungen zählen nie gegen das Limit. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/contacts/bulk \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "contacts": [
        {
            "phone": "+40721000001",
            "first_name": "Ana",
            "last_name": "Pop",
            "email": "ana@example.com"
        },
        {
            "phone": "0721 000 002",
            "first_name": "Ion",
            "group": [
                "d746e4c5-db24-4fb2-be03-590421344d69"
            ]
        },
        {
            "phone": "not-a-phone",
            "first_name": "Nobody"
        }
    ]
}'
PUT /api/contacts/{uuid} Kontakt bearbeiten
# Dieselben JSON-Felder wie bei „Kontakt hinzufügen“. Der Pfadparameter {uuid} ist die Kontakt-ID, die beim Anlegen zurückgegeben wurde.
# phone ist bei einer Aktualisierung optional; wenn Sie die Nummer ändern, darf sie keinem anderen Kontakt gehören (400 Duplikat).
# Eine Aktualisierung mit derselben phone, die dieser Kontakt bereits hat, ist erlaubt.
# Weggelassene Felder behalten ihren Wert; senden Sie ein Feld als null oder "", um es zu leeren. Gesendete metadata-Schlüssel werden mit den gespeicherten zusammengeführt, die übrigen bleiben erhalten.
# marketing_opt_in (optional, boolean) — true erfasst eine Marketing-Einwilligung (source: api), false einen Opt-out; ohne das Feld bleibt die Einwilligung unverändert.
# 404, wenn die uuid unbekannt oder gelöscht ist oder zu einem anderen Arbeitsbereich gehört.

curl -X PUT \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "first_name": "Ana",
    "last_name": "Popescu",
    "metadata": {
        "plan": "platinum"
    }
}'
DELETE /api/contacts/{uuid} Kontakt löschen
# Löscht den Kontakt per Soft-Delete; er verschwindet sofort aus jeder Liste. 404, wenn die uuid unbekannt oder bereits gelöscht ist.
# Antwort: { statusCode, id, message }.

curl -X DELETE \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Kontaktgruppen

GET /api/contact-groups Liste der Kontaktgruppen abrufen
# Optionale Query-Parameter: ?page=1&per_page=10 (per_page höchstens 100).
# Jede Gruppe: uuid, name, contacts_count (aktive Mitglieder), created_at, updated_at.

curl -X GET \
"https://whapier.com/api/contact-groups?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/contact-groups Kontaktgruppe hinzufügen
# name (Pflichtfeld) muss unter den Gruppen der Organisation eindeutig sein (400, wenn vergeben).
# Antwort: { statusCode, id, message }. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/contact-groups \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Lead 5"
}'
PUT /api/contact-groups/{uuid} Kontaktgruppe bearbeiten
# Derselbe Body wie bei „Kontaktgruppe hinzufügen“. 404 bei unbekannter uuid.

curl -X PUT \
https://whapier.com/api/contact-groups/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Lead 5"
}'
DELETE /api/contact-groups/{uuid} Kontaktgruppe löschen
# Entfernt die Gruppe und ihre Mitgliedschaften; die Kontakte selbst bleiben erhalten. 404 bei unbekannter uuid.

curl -X DELETE \
https://whapier.com/api/contact-groups/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Automatische Antworten

GET /api/canned-replies Liste der automatischen Antworten abrufen
# Optionale Query-Parameter: ?page=1&per_page=10 (per_page höchstens 100).
# Jede Antwort: uuid, name, trigger, match_criteria, response_type, response (der Text, oder null bei Medien), file (name, url) oder null, created_at, updated_at.

curl -X GET \
"https://whapier.com/api/canned-replies?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/canned-replies Automatische Antwort hinzufügen
# Body: name und trigger (max. 255), match_criteria (exact match | contains), response_type (text | image | audio), response.
# Bei text ist response die Antwort (max. 4096). Bei image oder audio senden Sie multipart/form-data mit der Datei als response (png/jpg bis 5 MB; mp3/aac/ogg/amr/opus/m4a bis 16 MB); ohne Datei ist die Anfrage ein 400.
# Antwort: { statusCode, id, message }. 403, wenn das Limit des Plans für automatische Antworten erreicht ist. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/canned-replies \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "About Us",
    "trigger": "what do you do?",
    "match_criteria": "contains",
    "response_type": "text",
    "response": "We sell shoes"
}'
PUT /api/canned-replies/{uuid} Automatische Antwort bearbeiten
# Dieselben Felder wie bei „Automatische Antwort hinzufügen“. Eine Aktualisierung ohne Datei behält die vorhandenen Medien. 404 bei unbekannter uuid.

curl -X PUT \
https://whapier.com/api/canned-replies/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "About Us",
    "trigger": "what do you do?",
    "match_criteria": "contains",
    "response_type": "text",
    "response": "We sell shoes and clothes"
}'
DELETE /api/canned-replies/{uuid} Automatische Antwort löschen
# 404 bei unbekannter uuid. Antwort: { statusCode, id, message }.

curl -X DELETE \
https://whapier.com/api/canned-replies/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

WhatsApp-Leitungen

GET /api/whatsapp-connections Verbindungen auflisten
# Gibt für jede Leitung die uuid zurück (als whatsapp_connection bei /api/send verwenden). Keine internen Datenbank-IDs.
# Jede Zeile: uuid, type, name, phone, display_phone_number und, bei einer WhatsApp-Business-Leitung, verified_name und number_status. 403, wenn keine Leitung verbunden ist.

curl -X GET \
https://whapier.com/api/whatsapp-connections \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Nachrichten

POST /api/send Nachricht senden
# Optional: whatsapp_connection (UUID aus GET /api/whatsapp-connections). Weglassen, um die Standardleitung der Organisation zu verwenden.
# phone (Pflichtfeld) — beliebiges Format; wird mit dem Land der Organisation zu E.164 normalisiert. Eine neue Nummer wird zum Kontakt (first_name, last_name, email optional).
# message (Pflichtfeld, max. 4096); header und footer (optional, max. 60); buttons (optional, bis zu 3 vom Typ { id, title }).
# Freitextnachrichten brauchen ein offenes 24-Stunden-Fenster: 422, wenn die letzte Nachricht des Kunden älter als einen Tag ist. 403: Abonnement, Planlimit, tägliches Testkontingent oder ein Konto in Prüfung.
# Antwort: 200 { statusCode, data: { success, data: { chat: { uuid, wam_id, status, type, created_at, contact } } } }. Eine Ablehnung durch WhatsApp ist auf /api ein 200 mit data.success false und data.data.error; auf /api/v2 ein HTTP 422.
# Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/send \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Hello Ana, how are you?",
    "whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "header": "Example Shoes",
    "footer": "Reply STOP to opt out",
    "buttons": [
        {
            "id": "yes",
            "title": "Fine"
        },
        {
            "id": "no",
            "title": "Not well"
        }
    ]
}'
POST /api/send/media Medien senden
# Optional: whatsapp_connection (UUID aus GET /api/whatsapp-connections). Weglassen, um die Standardleitung der Organisation zu verwenden.
# media_type (image | video | audio | document | sticker); media_url (https, ein öffentlicher Host; wird mit einer HEAD-Anfrage gegen die Größen- und Typgrenzen von WhatsApp geprüft - andernfalls 400 mit dem Grund); caption (optional, nicht bei audio); file_name (Pflicht bei document).
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/media \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "media_type": "image",
    "media_url": "https://cdn.example.com/offers/october.jpg",
    "caption": "Our October offers"
}'
POST /api/send/template Vorlagennachricht senden
# Optional: "whatsapp_connection": "<uuid>" für eine bestimmte WABA-Leitung (UUID aus GET /api/whatsapp-connections).
# template.name und template.language ("en" oder { "code": "en" }) sind Pflicht; components folgen dem Aufbau von WhatsApp (header, body, Button-Parameter).
# Funktioniert außerhalb des 24-Stunden-Fensters. Ein Kontakt, der sich abgemeldet hat (STOP), erhält keine MARKETING-Vorlage: 422. Utility- und Authentifizierungsvorlagen werden weiterhin gesendet.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/template \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "template": {
        "name": "order_update",
        "language": {
            "code": "en"
        },
        "components": [
            {
                "type": "header",
                "parameters": [
                    {
                        "type": "text",
                        "text": "48213"
                    }
                ]
            },
            {
                "type": "body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "Ana"
                    },
                    {
                        "type": "text",
                        "text": "48213"
                    },
                    {
                        "type": "date_time",
                        "date_time": {
                            "fallback_value": "October 7, 2026"
                        }
                    }
                ]
            },
            {
                "type": "button",
                "sub_type": "url",
                "index": "0",
                "parameters": [
                    {
                        "type": "text",
                        "text": "48213"
                    }
                ]
            }
        ]
    }
}'
POST /api/send/location Standort senden
# latitude (-90 bis 90) und longitude (-180 bis 180) sind Pflicht; name und address optional.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/location \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "latitude": 46.77120000000000032969182939268648624420166015625,
    "longitude": 23.623599999999999710098563809879124164581298828125,
    "name": "Example Shoes",
    "address": "Str. Memorandumului 12, Cluj-Napoca"
}'
POST /api/send/contacts Kontaktkarten senden
# contacts (1 bis 10 Karten) im contacts[]-Aufbau von WhatsApp: name.formatted_name Pflicht; phones[], emails[], addresses[], org optional.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/contacts \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "contacts": [
        {
            "name": {
                "formatted_name": "Example Shoes Support",
                "first_name": "Support"
            },
            "phones": [
                {
                    "phone": "+40700000000",
                    "type": "WORK"
                }
            ],
            "emails": [
                {
                    "email": "support@example.com",
                    "type": "WORK"
                }
            ]
        }
    ]
}'
POST /api/send/reaction Reaktion senden
# message_id (die wam_id der Nachricht, auf die reagiert wird) und emoji (Pflicht; "" entfernt die Reaktion).
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/reaction \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message_id": "wamid.HBgMNDA3MjEwMDAwMDEVAgARGBI5QkY2RkE3RDlCMjc2RjI2QkEA",
    "emoji": "👍"
}'
POST /api/send/location-request Standort anfordern
# message (Pflichtfeld, max. 1024): der Text über der Schaltfläche „Standort senden“.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/location-request \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Where should we deliver?"
}'
POST /api/send/request-contact-info Kontaktdaten anfordern
# message (Pflichtfeld, max. 1024): bittet einen WhatsApp-Nutzer, der nur über einen Benutzernamen erreichbar ist, seine Telefonnummer zu teilen.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/request-contact-info \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Could you share your number so we can call you back?"
}'
POST /api/send/carousel Karussell senden
# message (Pflichtfeld, max. 1024) und cards (2 bis 10): header { type: image | video, link } Pflicht; body (max. 160), url_button { text, url } und quick_replies (bis zu 3 vom Typ { id, title }) optional.
# Dieselben Prüfungen und dieselbe Antwort wie bei „Nachricht senden“.

curl -X POST \
https://whapier.com/api/send/carousel \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Our new arrivals",
    "cards": [
        {
            "header": {
                "type": "image",
                "link": "https://cdn.example.com/shoes/1.jpg"
            },
            "body": "Runner, 89 EUR",
            "url_button": {
                "text": "See it",
                "url": "https://example.com/shoes/1"
            }
        },
        {
            "header": {
                "type": "image",
                "link": "https://cdn.example.com/shoes/2.jpg"
            },
            "body": "Trail, 119 EUR",
            "quick_replies": [
                {
                    "id": "trail",
                    "title": "Tell me more"
                }
            ]
        }
    ]
}'

Flows

POST /api/flows/{uuid}/start Flow starten
# contact (Pflichtfeld): die uuid oder phone des Kontakts (normalisiert mit dem Land der Organisation).
# 200 { statusCode, success: true, message }; 404 Flow oder Kontakt unbekannt; 422 Flow nicht veröffentlicht; 409 der Kontakt befindet sich bereits in einer Flow-Sitzung.
# Alles, was der Flow sendet, unterliegt dem 24-Stunden-Fenster, sofern er keine Vorlagen-Knoten verwendet.

curl -X POST \
https://whapier.com/api/flows/{{uuid}}/start \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "contact": "+40721000001"
}'

Kampagnen

GET /api/campaigns Kampagnen auflisten
# Optionale Query-Parameter: ?page=1&per_page=10&search=
# Jede Kampagne: uuid, name, status, scheduled_at, created_at, template (uuid, name, language, category, status), whatsapp_connection (uuid, name, type), audience (type: all | group | segment, uuid, name), counts (contacts, sent, delivered, read, failed).

curl -X GET \
"https://whapier.com/api/campaigns?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/campaigns Kampagne anlegen (WABA-Vorlage mit Variablen)
# Verwenden, wenn whatsapp_connection eine WhatsApp-Cloud-Leitung (WABA) aus GET /api/whatsapp-connections ist.
#
# VORAUSSETZUNGEN
# - template: UUID einer Zeile aus GET /api/templates (auf die Organisation bezogen), NICHT der öffentliche Name der Vorlage als String.
# - Die Anzahl der Variablen muss zu Ihrer genehmigten Vorlage passen: Öffnen Sie die Metadaten der Vorlage in der Oberfläche oder bei Meta — BODY verwendet {{1}}, {{2}}, … der Reihe nach.
# - Sie müssen für jeden BODY-Platzhalter genau einen body-Parameter liefern, in derselben Reihenfolge. Eine Anzahl, die nicht zur genehmigten Vorlage passt, wird vorab abgelehnt (422), nicht erst von WhatsApp.
#
# HINWEISE ZU DEN FELDERN
# - contacts: "all" oder die uuid einer Kontaktgruppe; oder segment: die uuid eines gespeicherten Segments (eines von beiden, nicht beide). send_immediately: true, oder scheduled_at (ein Datum, als UTC gelesen).
# - header: optionales Objekt; weggelassen bedeutet { "format": "TEXT", "parameters": [] }.
# - body: Für Variablen body.parameters[] verwenden. API-Format (empfohlen): { "type": "text", "value": "literal for {{1}}" } je Platzhalter.
#   Alternative (wie im Dashboard): { "selection": "static", "value": "..." } oder { "selection": "dynamic", "value": "first name" } (ordnet Kontaktfelder zu).
# - footer / buttons: optional; [] oder {} verwenden, wenn nicht genutzt. Vorlagen mit URL- oder Quick-Reply-Variablen brauchen buttons[] im selben Aufbau wie das Kampagnenformular im Web.
# - Medien-Header (IMAGE|VIDEO|DOCUMENT): header.parameters[] mit type (IMAGE|VIDEO|DOCUMENT), "selection": "link", "value": "https://..." (öffentliche URL; die API kann keine Dateien hochladen).
#
# ANTWORT: 200 { "statusCode": 200, "uuid": "...", "message": "..." }. Fragen Sie GET /api/campaigns/{uuid} für den Bericht und GET /api/campaigns/{uuid}/logs für den Status je Empfänger ab, oder abonnieren Sie den Webhook campaign.finished.
# 403, wenn das Kampagnenlimit des Plans erreicht ist. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/campaigns \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Billing reminder blast",
    "whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "contacts": "all",
    "send_immediately": true,
    "template": "281a3383-985c-4084-bcb0-9ec523c952de",
    "header": {
        "format": "TEXT",
        "parameters": []
    },
    "body": {
        "parameters": [
            {
                "type": "text",
                "value": "Ana"
            },
            {
                "type": "text",
                "value": "48213"
            },
            {
                "type": "text",
                "value": "7 October 2026"
            }
        ]
    },
    "footer": {},
    "buttons": []
}'
GET /api/campaigns/{uuid} Eine Kampagne mit ihrem Bericht abrufen
# Das Kampagnenobjekt von Kampagnen auflisten plus report: counts (contacts, sent, delivered, read, failed, pending), failure_reasons (code, title, count - die zehn häufigsten), started_at, finished_at (null, bis die Kampagne beendet ist), paused_reason, paused_detail und paused_at (null, außer der Status ist paused).
# paused_reason ist user (aus dem Dashboard oder über die API pausiert), admin, failing, failure_rate oder quality (von der Plattform pausiert; paused_detail sagt, warum). 404 bei unbekannter Kampagne.

curl -X GET \
https://whapier.com/api/campaigns/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/campaigns/{uuid}/pause Kampagne pausieren
# Kein Body. Nur eine Kampagne mit Status scheduled oder ongoing kann pausiert werden: sonst 409 mit dem Status, in dem die Kampagne ist. Die Protokolle bleiben, wie sie sind, und das Fortsetzen nimmt sie wieder auf.
# Antwort: { statusCode, status, message } - status ist der neue Status der Kampagne. 404 bei unbekannter Kampagne.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/pause \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/campaigns/{uuid}/resume Kampagne fortsetzen
# Kein Body. Nur eine Kampagne mit Status paused kann fortgesetzt werden: sonst 409. Eine vor ihrer Stunde pausierte Kampagne geht zurück auf scheduled; eine während des Versands pausierte zurück auf ongoing.
# Antwort: { statusCode, status, message }. 404 bei unbekannter Kampagne.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/resume \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/campaigns/{uuid}/cancel Kampagne abbrechen
# Kein Body. Eine Kampagne mit Status scheduled, ongoing oder paused kann abgebrochen werden: sonst 409. Was nicht gesendet wurde, bleibt ungesendet; der Bericht zeigt weiterhin, wer erreicht wurde.
# Antwort: { statusCode, status, message }. 404 bei unbekannter Kampagne.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/cancel \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
GET /api/campaigns/{uuid}/logs Kampagnenprotokoll
# Optional: ?page=1&per_page=10&search= (Suche nach Name/Telefonnummer des Kontakts).
# Jede Zeile: contact (uuid, phone, first_name, last_name), status, message (uuid, wam_id, status) oder null, error (code, title, reason) oder null, retry_count, created_at, updated_at. 404 bei unbekannter Kampagne.

curl -X GET \
"https://whapier.com/api/campaigns/{{uuid}}/logs?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Vorlagen

GET /api/templates Vorlagen auflisten
# Optionale Query-Parameter: ?page=1&per_page=10 (per_page höchstens 100).
# Jede Vorlage: uuid, name, language, category, status, components (so, wie WhatsApp sie genehmigt hat), variables (header, body, buttons: wie viele Platzhalter jeder Teil hat), rejection (Grund der Ablehnung, oder null), quality_score, updated_at.

curl -X GET \
"https://whapier.com/api/templates?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/templates/{uuid} Eine Vorlage mit einem sendefertigen Beispiel abrufen
# Das Vorlagenobjekt von Vorlagen auflisten plus example_payload: ein vollständiger Body für POST /api/send/template mit einem Parameter je Platzhalter (die Beispiele, mit denen die Vorlage eingereicht wurde, sonst ein Wert, der die Stelle benennt), ein Link für einen Medien-Header und ein Suffix für jeden URL-Button mit Variable.
# Optionale Query: whatsapp_connection (die uuid einer Leitung), wenn dieselbe Vorlage auf mehreren Leitungen existiert. 404 bei unbekannter uuid.

curl -X GET \
https://whapier.com/api/templates/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/templates Vorlage erstellen
# name (Kleinbuchstaben, Ziffern und Unterstriche), category (MARKETING | UTILITY) und language (ein Meta-Sprachcode wie en oder pt_BR) sind erforderlich; whatsapp_connection (die uuid einer WhatsApp-Business-Leitung) ist optional - sonst die Standardleitung.
# header (optional): { format: TEXT, text (max. 60, ein {{1}} erlaubt), examples } oder { format: IMAGE | VIDEO | DOCUMENT, media_url: ein öffentlicher https-Link zu einer Beispieldatei }.
# body.text (erforderlich, max. 1024, Platzhalter {{1}}, {{2}}, ...) mit body.examples, eines je Platzhalter; footer (optional, max. 60); buttons (optional, bis zu 10): { type: QUICK_REPLY | URL | PHONE_NUMBER | COPY_CODE, text, url, phone_number, example }.
# Antwort: 200 { statusCode, uuid, status, message } - status ist PENDING, bis Meta sie geprüft hat (der Webhook template.status.update meldet es). 400 mit Metas Begründung, wenn Meta sie ablehnt; AUTHENTICATION-Vorlagen können noch nicht über die API eingereicht werden. Ein Sandbox-Schlüssel kann nicht einreichen (403). Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/templates \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "order_update",
    "category": "UTILITY",
    "language": "en",
    "header": {
        "format": "TEXT",
        "text": "Order {{1}}",
        "examples": [
            "48213"
        ]
    },
    "body": {
        "text": "Hi {{1}}, your order {{2}} ships on {{3}}.",
        "examples": [
            "Ana",
            "48213",
            "October 7"
        ]
    },
    "footer": "Example Shoes",
    "buttons": [
        {
            "type": "URL",
            "text": "Track",
            "url": "https://example.com/track/{{1}}",
            "example": "48213"
        },
        {
            "type": "QUICK_REPLY",
            "text": "Stop updates"
        }
    ]
}'
POST /api/templates/sync Vorlagen von Meta synchronisieren
# Kein Body. Holt die Vorlagen jeder WhatsApp-Business-Leitung von Meta, wie es die Aktualisierung im Dashboard tut, damit eine im Meta Business Manager geänderte Vorlage auch hier erscheint.
# Antwort: { statusCode, synced, message } - synced ist die Zahl der hinzugefügten oder geänderten Vorlagen. Ein Sandbox-Schlüssel kann nicht synchronisieren (403); 400, wenn Meta die Anfrage abgelehnt hat.

curl -X POST \
https://whapier.com/api/templates/sync \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'

Webhooks

GET /api/webhooks Webhooks auflisten
# Jede Zeile: uuid, url, events, secret_preview (die letzten sechs Zeichen des Signatur-Secrets), created_at, updated_at. Das vollständige Secret wird einmal gezeigt, in der Antwort auf Webhook hinzufügen.
# 403, wenn das Webhooks-Modul nicht im Plan enthalten ist.

curl -X GET \
https://whapier.com/api/webhooks \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/webhooks/events Ereignisse auflisten
# Jedes Ereignis, das ein Webhook empfangen kann: data (name, description). Die Webhooks-Seite im Dashboard liest denselben Katalog.
# Eine Zustellung ist { event, data }; die Form von data je Ereignis steht unter Bevor Sie beginnen > Webhooks, und POST /api/webhooks/{uuid}/test liefert ein Beispiel für jedes davon.

curl -X GET \
https://whapier.com/api/webhooks/events \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/webhooks Webhook hinzufügen
# url (erforderlich, https, eindeutig je Organisation) und events (erforderlich, ein oder mehrere Namen aus GET /api/webhooks/events).
# Antwort: { statusCode, uuid, secret, message } - das einzige Mal, dass das vollständige Secret zurückgegeben wird; speichern Sie es, um X-Whapier-Signature zu prüfen. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/webhooks \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "url": "https://example.com/hooks/whapier",
    "events": [
        "message.received",
        "message.status",
        "campaign.finished"
    ]
}'
PUT /api/webhooks/{uuid} Webhook bearbeiten
# Gleicher Body wie bei Webhook hinzufügen. Die Liste events ersetzt die gespeicherte; das Secret bleibt, wie es ist. 404 bei unbekannter uuid.

curl -X PUT \
https://whapier.com/api/webhooks/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "url": "https://example.com/hooks/whapier",
    "events": [
        "message.received",
        "message.status"
    ]
}'
DELETE /api/webhooks/{uuid} Webhook löschen
# Entfernt den Endpunkt und seine Abonnements; es wird nichts mehr an ihn zugestellt. Antwort: { statusCode, uuid, message }. 404 bei unbekannter uuid.

curl -X DELETE \
https://whapier.com/api/webhooks/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/webhooks/{uuid}/test Testereignis senden
# event (erforderlich): ein Name aus GET /api/webhooks/events. Der Beispiel-Payload wird per POST als { event, data, test: true } an die url geschickt, mit dem Secret in X-Whapier-Signature signiert.
# Antwort: { statusCode, event, delivered, http_status, message } - delivered ist false mit dem Status, den Ihr Endpunkt geantwortet hat, oder http_status null, wenn er nicht erreichbar war. 404 bei unbekannter uuid.

curl -X POST \
https://whapier.com/api/webhooks/{{uuid}}/test \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "event": "message.status"
}'

Nachrichtenstatus

GET /api/messages Nachrichten auflisten
# Optionale Query-Parameter: status (sent | delivered | read | failed | accepted | played), direction (inbound | outbound), since und until (Datumswerte, UTC), contact (die uuid eines Kontakts), campaign (die uuid einer Kampagne: die Nachrichten, die sie erzeugt hat), wam_id (eine Nachricht nach WhatsApp-ID), api_key (die uuid eines Schlüssels, oder current: die Nachrichten, die mit dem anfragenden Schlüssel gesendet wurden), page, per_page (Standard 25, max. 100).
# Antwort: { statusCode, data: [ message ], meta: { page, per_page, total, last_page } }. 404, wenn contact, campaign oder api_key unbekannt ist.
# Eine Nachricht: uuid, wam_id, direction, status, type, content, created_at, delivered_at, read_at, failed_at, failure (code, title, reason, retryable) oder null, pricing (category, model, billable, amount, currency, country), api_key (uuid, name) oder null, wenn sie nicht über die API gesendet wurde, contact (uuid, phone, first_name, last_name).
# content je type - text: body, header, footer, buttons (type, text); template: name, language, body; image, video, audio, document, sticker: caption, media (type, url, filename); interactive und button: text, payload (was der Kunde gedrückt hat); location: latitude, longitude, name, address; contacts: contacts (name, phones); reaction: emoji, wam_id.

curl -X GET \
"https://whapier.com/api/messages?status=failed&per_page=25" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/contacts/{uuid}/messages Konversation mit einem Kontakt
# Dieselben Nachrichtenobjekte wie bei Nachrichten auflisten, für einen Kontakt, neueste zuerst. Optionale Query: per_page (Standard 25, max. 100), before (die uuid der ältesten Nachricht, die Sie schon haben).
# Antwort: { statusCode, data: [ message ], meta: { per_page, has_more, next_before } } - übergeben Sie next_before als before, um die älteren Nachrichten zu erhalten. 404 bei unbekanntem Kontakt oder Cursor.

curl -X GET \
"https://whapier.com/api/contacts/{{uuid}}/messages?per_page=25" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/messages/{uuid} Eine Nachricht abrufen
# Dasselbe Nachrichtenobjekt plus history: eine Liste von { status, timestamp, recorded_at }, jede von WhatsApp gemeldete Statusänderung. 404 bei unbekannter uuid.

curl -X GET \
https://whapier.com/api/messages/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Nutzung

GET /api/usage Plan und Nutzung
# Antwort data: plan (name, status, valid_until), limits (contacts, messages, campaigns: used, limit; limit null = unbegrenzt), trial_daily_messages (nur Testkonten), messages_sent (today, last_7_days, last_30_days), estimated_cost (last_30_days: amount, currency), rate_limit (per_minute).

curl -X GET \
https://whapier.com/api/usage \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Inbox

GET /api/conversations/{contact_uuid} Eine Konversation abrufen
# Antwort data: contact (uuid, phone, first_name, last_name), ticketing (ob Einstellungen > Tickets eingeschaltet ist), ticket (status, assigned_to: name, email; opened_at, waiting_since, resolved_at) oder null, messages (uuid, wam_id, direction, type, text, status, created_at - die 50 neuesten, neueste zuerst), next_before.
# Optionale Query: before (die uuid der ältesten Nachricht, die Sie haben) für die älteren Nachrichten; 400, wenn der Cursor keine Nachricht dieses Kontakts ist. 404 bei unbekanntem Kontakt.

curl -X GET \
https://whapier.com/api/conversations/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/conversations/{contact_uuid}/assign Konversation zuweisen
# user_email (erforderlich, darf null sein): die E-Mail eines aktiven Mitglieds der Organisation; null hebt die Zuweisung des Tickets auf. Eine Konversation ohne Ticket erhält eines.
# Antwort: { statusCode, data: ticket, message } mit dem Ticket, wie Eine Konversation abrufen es zeigt. 409, solange das Ticketing ausgeschaltet ist; 422, wenn kein aktives Mitglied der Organisation diese E-Mail hat; 404 bei unbekanntem Kontakt.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/assign \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "user_email": "maria@example.com"
}'
POST /api/conversations/{contact_uuid}/close Konversation schließen
# Kein Body. Löst das Ticket (status closed, resolved_at gesetzt), wie der Button in der Inbox. Antwort: { statusCode, data: ticket, message }.
# 409, solange das Ticketing ausgeschaltet ist; 404 bei unbekanntem Kontakt.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/close \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/conversations/{contact_uuid}/reopen Konversation wieder öffnen
# Kein Body. Öffnet ein geschlossenes Ticket wieder (status open, resolved_at gelöscht); ein offenes Ticket wird unverändert zurückgegeben. Antwort: { statusCode, data: ticket, message }.
# 409, solange das Ticketing ausgeschaltet ist; 404 bei unbekanntem Kontakt.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/reopen \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/conversations/{contact_uuid}/notes Interne Notiz hinzufügen
# note (erforderlich, max. 5000): wird den Agenten im Verlauf angezeigt und nie an den Kontakt gesendet. Funktioniert mit ein- wie ausgeschaltetem Ticketing.
# Antwort: { statusCode, uuid, created_at, message }. 404 bei unbekanntem Kontakt. Akzeptiert einen Idempotency-Key-Header.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/notes \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "note": "Customer called; wants the order delivered on Friday."
}'

In zwei Minuten zum API-Schlüssel

Kostenlos testen, ohne Kreditkarte — der Entwicklerbereich ist in jedem Plan enthalten.

Kostenlos testen