Odbieranie wiadomości WhatsApp
Wiadomości przychodzące trafiają na ten sam zasób co wychodzące, bez osobnego endpointu skrzynki odbiorczej do odpytywania. Odczytuj je za pomocą listy wiadomości w dashboardzie albo przez API za pomocą GET /v1/whatsapp/messages/{id} po przefiltrowaniu listy do przychodzących.
Każda wiadomość przychodząca wydłuża okno obsługi klienta do 24 godzin od znacznika czasu tej wiadomości, co pozwala dostarczyć Twoją odpowiedź w dowolnej formie. Wiadomość, która dotrze do Bird z opóźnieniem, niesie ze sobą okno faktycznie przyznane przez kontakt, a późniejszy termin już zapisany nigdy nie jest skracany.
Co zawiera wiadomość przychodząca
Każda wiadomość przychodząca ma wspólną kopertę: id, direction: "inbound", kontakt w from, Twój numer w to, status o wartości received oraz created_at. Obok koperty znajduje się dokładnie jedno pole treści wskazujące, co kontakt wysłał:
Przykład kodu
{
"id": "wam_01kya19eknftrs2s6p82asmvnh",
"direction": "inbound",
"from": { "phone_number": "+14155550100" },
"to": { "phone_number": "+13124495569" },
"status": "received",
"text": { "body": "Is my order out for delivery yet?" },
"created_at": "2026-08-25T09:04:11Z"
}from identyfikuje kontakt na podstawie tożsamości zgłaszanej przez WhatsApp: numer E.164 phone_number, bsuid lub oba, a także publikowane username i display_name. Kontakt, który przyjął nazwę użytkownika WhatsApp, może się z Tobą skontaktować bez numeru telefonu; zobacz identyfikatory użytkowników w zakresie firmy, żeby dowiedzieć się, co przechowywać i jak poprosić o numer.
Jedno z tych pól treści, tzw. arm, zawiera to, co kontakt wysłał, i dokładnie jeden arm jest ustawiony w każdej wiadomości. Każdy ma własną stronę z kształtem odczytu, payloadem whatsapp.received i tym, na co uważać:
| Pole | Co zawiera przychodzące |
|---|---|
| text | body, wiadomość wpisana przez kontakt |
| image | id, url, mime_type i ewentualny caption |
| video | Te same pola multimediów, plus ewentualny caption |
| audio | Te same pola multimediów, plus voice w notatce głosowej; podpis nie istnieje |
| sticker | Te same pola multimediów, plus animated |
| document | Te same pola multimediów, plus ewentualny filename i caption |
| location | latitude i longitude, a czasem name, address lub url |
| contact_cards | Jedna lub więcej wizytówek udostępnionych przez kontakt |
| interactive_reply | slug i text przycisku lub wiersza, który kontakt nacisnął |
| unsupported | Typ treści WhatsApp, którego API nie modeluje, np. zamówienie |
Dwa stuknięcia trafiają na arm, którego możesz się nie spodziewać. Żądanie lokalizacji odpowiada jako zwykły przychodzący location, a żądanie danych kontaktu odpowiada jako contact_cards, więc integracja obserwująca tylko interactive_reply w oczekiwaniu na stuknięcie przeoczy oba.
Pobieranie multimediów przychodzących
Przychodzący image, video, audio, sticker lub document dociera jako referencja do pliku przechowywanego przez Bird, a nie jako sam plik:
Przykład kodu
{
"image": {
"id": "waf_01kyb2m4xq7whs0d8n3prv6tez",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"caption": "Is this the right part?"
}
}Pobierz bajty za pomocą metody media kanału, przekazując id wiadomości i id medium:
const media = await bird.whatsapp.messages.media(
"wam_01kya19eknftrs2s6p82asmvnh",
"waf_01kyb2m4xq7whs0d8n3prv6tez",
);
console.log(media.contentType, media.contentLength);media = client.whatsapp.messages.media(
"wam_01kya19eknftrs2s6p82asmvnh", "waf_01kyb2m4xq7whs0d8n3prv6tez"
)
print(media.content_type, media.content_length)media, err := client.Whatsapp.Messages.Media(context.Background(),
"wam_01kya19eknftrs2s6p82asmvnh", "waf_01kyb2m4xq7whs0d8n3prv6tez")
if err != nil {
log.Fatal(err)
}
fmt.Println(media.ContentType, media.ContentLength)$media = $bird->whatsapp->messages->media('wam_01kya19eknftrs2s6p82asmvnh', 'waf_01kyb2m4xq7whs0d8n3prv6tez');
file_put_contents('photo.jpg', $media->data);
echo $media->contentType, ' ', $media->contentLength;bird whatsapp media <message-id> <media-id>curl -L -X GET "https://{region}.platform.bird.com/v1/whatsapp/messages/{message_id}/media/{media_id}" \
-H "Authorization: Bearer $TOKEN"Otrzymujesz bajty z mime_type zadeklarowanym dla nich. Identyfikator, którego Bird nie rozpoznaje, zwraca 404, a wiadomość wychodząca nie ma zapisanych multimediów do serwowania.
Wiadomość jest dostępna do odczytu przez 30 dni od momentu odebrania, a jej multimedia nigdy nie przeżyją samej wiadomości. Ten endpoint odczytuje wiadomość, zanim zaserwuje plik, więc po upływie tego okna oba zwracają 404. Zapisz każdy potrzebny plik na dłużej, dopóki wiadomość jest jeszcze dostępna. Jedyny przypadek, w którym dane znikają wcześniej, to usunięcie przechowywanych bajtów przed upływem okna: pobranie zwraca 410 E15021, a wiadomość wciąż daje się odczytać z mime_type i caption medium.
Pod spodem ten endpoint odpowiada 302 z presigned URL ważnym przez 15 minut. SDK i CLI obsługują to przekierowanie za Ciebie. Przy bezpośrednim wywołaniu presigned URL niesie własne poświadczenie, więc przekierowane żądanie nie może jednocześnie wysyłać nagłówka Authorization. Wysłanie obu kończy się błędem. curl -L sam usuwa nagłówek przy przekierowaniu na inny host; klient przekazujący nagłówki dosłownie musi pobrać Location jako osobne, nieuwierzytelnione żądanie.
Cytowane odpowiedzi
in_reply_to_message_id wskazuje wiadomość, na którą odpowiada wiadomość przychodząca, gdy WhatsApp oznacza ją jako odpowiedź:
Przykład kodu
{
"id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
"direction": "inbound",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"text": { "body": "Yes, that one" }
}WhatsApp nie oznacza każdej odpowiedzi, a nieoznaczona nie niesie żadnego ID. Pole jest również pomijane, gdy cytowanej wiadomości nie da się dopasować do wiadomości przechowywanej przez Bird: wysłanej zanim ten obszar roboczy zaczął je rejestrować albo starszej niż 15 dni, przez które Bird przechowuje identyfikatory wiadomości WhatsApp. Brak dopasowania skutkuje pominięciem pola zamiast zgłoszenia, co wygląda tak samo jak odpowiedź na nic.
Traktuj to pole jako wskazówkę, nie klucz. metadata ustawiony na Twojej własnej wiadomości nie pomaga, ponieważ pozostaje na Twojej wiadomości i nigdy nie trafia do odpowiedzi kontaktu, więc integracja, która musi wiedzieć, do którego pytania należy odpowiedź, sama śledzi ostatnie pytanie zadane danemu kontaktowi. Zobacz Cytowanie wiadomości, aby poznać stronę wychodzącą.
Webhook
Zasubskrybuj whatsapp.received, aby reagować na wiadomość przychodzącą w momencie jej nadejścia, zamiast odpytywać listę. Payload zawiera treść na wierzchu koperty zdarzenia, więc endpoint nie potrzebuje dodatkowego odczytu:
Przykład kodu
{
"type": "whatsapp.received",
"timestamp": "2026-08-25T09:04:11.118Z",
"data": {
"whatsapp_id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
"workspace_id": "ws_01ky7m235keycbnwyajabe1a6b",
"direction": "inbound",
"from": { "phone_number": "+14155550100", "display_name": "Alex Rivera" },
"to": { "phone_number": "+13124495569" },
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"interactive_reply": {
"type": "button",
"button": { "slug": "cancel-booking", "text": "Cancel" }
},
"tags": null,
"metadata": null
}
}Zobacz zdarzenia WhatsApp, aby poznać pełną kopertę i resztę listy zdarzeń.
Następne kroki
- Wiadomości serwisowe: strona wysyłania tych samych armów treści
- Wysyłanie wiadomości WhatsApp: odpowiadanie w oknie serwisowym i cytowanie wiadomości
- Zdarzenia WhatsApp: pełna lista zdarzeń, przez API lub webhooki
- Log WhatsApp: przeglądanie konwersacji w dashboardzie
Powiązane zasoby
Kontynuuj z dokumentacją, przewodnikami i przykładami dotyczącymi tego tematu. Zasoby są w języku angielskim.
Obejrzyj przewodnikConnecting WhatsApp to Bird: from buying a number to a live channelZrozum koncepcjęWhat is the 24-hour customer service window on WhatsApp?Użyj narzędziaWhatsApp message builderPoznaj możliwościWhatsApp
Wypróbuj ćwiczenie i uzyskaj brief wdrożeniowy