Wysyłanie wiadomości WhatsApp
Ten przewodnik opisuje endpoint wysyłania, POST /v1/whatsapp/messages. Tworzysz jeden ładunek JSON z odbiorcą i dokładnie jednym typem treści: wstępnie zatwierdzonym szablonem albo wiadomością serwisową zawierającą tekst, obraz, wideo, dźwięk, naklejkę, dokument, lokalizację, karty kontaktowe lub element do kliknięcia. Bird zwraca 202 Accepted z identyfikatorem wiadomości i dostarcza ją asynchronicznie. To, który z tych dwóch typów możesz wysłać, zależy od okna obsługi klienta. Każde żądanie wysyła jedną wiadomość do jednego odbiorcy i nie ma endpointu do wysyłki zbiorczej.
Minimalna wysyłka
Najmniejszy prawidłowy ładunek to odbiorca to oraz template z polem slug. Dodaj language, jeśli chcesz wybrać konkretny język; bez tego pola zostanie wysłany domyślny język szablonu. Uzupełnij zmienne zadeklarowane przez szablon za pomocą parameters.
Wywołanie curl używa hosta w USA; jeśli Twój klucz zaczyna się od bk_eu1_, wywołaj zamiast niego https://eu1.platform.bird.com. SDK odczytują region z klucza, więc nie ustawiają hosta.
const msg = await bird.whatsapp.send({
to: "+15551234567",
template: {
slug: "bird_otp",
parameters: { code: "123456" },
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+15551234567",
template="bird_otp",
language="en",
parameters={"code": "123456"},
)
print(msg.id, msg.status)msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+15551234567",
Template: "bird_otp",
Language: "en",
Parameters: map[string]any{"code": "123456"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)$message = $bird->whatsapp->send(
to: '+15551234567',
template: 'bird_otp',
language: 'en',
parameters: ['code' => '123456'],
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--language en \
--parameters '{"code":"123456"}' \
--template bird_otp \
--to +15551234567curl -X POST "https://{region}.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+15551234567",
"template": {
"slug": "bird_otp",
"language": "en",
"parameters": {
"code": "123456"
}
}
}'Okno obsługi klienta
To, który z tych dwóch typów możesz wysłać, zależy od jednego stanu: czy okno obsługi klienta jest otwarte.
Kontakt otwiera okno, gdy wyśle wiadomość na numer Twojej firmy lub na niego zadzwoni. Okno pozostaje otwarte przez 24 godziny i resetuje się za każdym razem, gdy kontakt ponownie do Ciebie napisze. Gdy jest otwarte, możesz wysłać wiadomość serwisową, czyli dowolną treść: tekst, obraz, wideo, dźwięk, naklejkę, dokument, lokalizację, karty kontaktowe lub treść interaktywną. Po jego wygaśnięciu dotrze do kontaktu tylko wstępnie zatwierdzony szablon, a odpowiedź na niego ponownie otwiera okno.
Bird śledzi okno za Ciebie, więc wiadomość serwisowa wysłana przy zamkniętym oknie zostaje odrzucona, zanim cokolwiek zostanie utworzone lub naliczone: żądanie zwraca 422 E15044 WhatsAppServiceWindowClosed. Sprawdzenie działa w trybie best effort i w razie awarii przepuszcza żądanie, więc 202 nie dowodzi, że okno było faktycznie otwarte w chwili wysyłki. Jeśli okno wygaśnie między przyjęciem a wysyłką, wiadomość kończy się błędem asynchronicznie, z service_window_expired w polu last_error wiadomości.
Pełny cykl życia, czyli co otwiera okno, co je resetuje i jak wpływa na ceny, opisuje strona okno obsługi klienta.
Budowanie ładunku żądania
Odbiorca
to wskazuje jeden cel, podany jako numer telefonu, identyfikator użytkownika w zakresie firmy lub identyfikator grupy. Numer telefonu ma format E.164: początkowy znak +, kod kraju i numer abonenta, na przykład +14155550100. Weryfikujemy numer, więc wartość, która nie może być prawdziwym numerem, pod który da się zadzwonić (zła długość, nieprzydzielony prefiks), zostaje odrzucona z błędem 422 WhatsAppInvalidRecipient, zanim cokolwiek zostanie naliczone. Nie ma tablicy odbiorców ani wysyłki zbiorczej, więc aby dotrzeć do wielu osób spoza jednej grupy, wykonaj jedno wywołanie na każdego odbiorcę.
Identyfikator użytkownika w zakresie firmy, taki jak US.13491208655302741918, adresuje kontakt, którego numeru telefonu nie znasz. W ten sposób odpowiadasz kontaktowi, który napisał do Ciebie bez ujawnienia numeru. Zmieniają się dwie rzeczy: numer nadawcy musi należeć do tego samego portfolio firmowego, do którego przypisany jest identyfikator, a szablon z kodem jednorazowym wymaga numeru telefonu. Szablon zarządzany przez Bird zostaje odrzucony przy przyjęciu z błędem 422 WhatsAppRecipientNotSupportedForTemplate. Szablon uwierzytelniający utworzony przez Twój obszar roboczy zostaje przyjęty, a potem kończy się niepowodzeniem, ponieważ Meta wymaga dla niego numeru telefonu.
to przyjmuje jeszcze jedną postać: identyfikator grupy WhatsApp, taki jak wag_01krdgeqcxet5s7t44vh8rt9mg, który wysyła wiadomość do wszystkich uczestników danego czatu grupowego. Wysyłka do grupy pomija from i raportuje dostarczenie dla całej grupy, a nie dla jednego odbiorcy, dlatego opisuje ją osobna strona Wysyłanie do grupy WhatsApp.
Szablon
template wskazuje zatwierdzony wcześniej szablon do wysłania:
slug(wymagane): slug szablonu, na przykładbird_order_confirmation. Musi odpowiadać szablonowi z Twojego katalogu (małe litery, cyfry i podkreślenia).language: tag języka szablonu, na przykładenlubpt-BR. Pomiń go, aby wysłać domyślny język szablonu. Podanie języka, którego szablon nie ma, zwraca błąd422z listą dostępnych języków. Przyjęta wiadomość zwraca ustalony język.parameters: wartości wypełniające zmienne szablonu, w postaci jednego obiektu z kluczami według nazw (zobacz Komponenty i parametry). Pomiń je w przypadku szablonu bez zmiennych.components: te same wartości w strukturze komponentów Meta, zamiastparameters. Niektóre szablony przyjmują tylko tę postać.
Przeglądaj swoje szablony, ich języki i podgląd każdego z nich na stronie Templates.
Komponenty i parametry
Szablony zawierają zmienne nazwane ({{ref}}, {{amount}}) lub numerowane ({{1}}, {{2}}). Wypełnij je przez parameters, jeden obiekt. Pole variables wersji szablonu wymienia przyjmowane klucze i oznacza te opcjonalne. Każdy klucz jest jednym z poniższych:
- własna nazwa zmiennej nazwanej, na przykład
order_id - numer zmiennej numerowanej, na przykład
1 header_url,header_filenamelubheader_locationdla nagłówka z multimediami lub lokalizacją orazheader_url_1,header_url_2i kolejne dla nagłówka karty karuzelibutton_urldla numerowanego sufiksu przycisku URL orazbutton_url_1,button_url_2i kolejne dla przycisku karty karuzeli. Sufiks nazwany przyjmuje własną nazwę.codedla kodu szablonu uwierzytelniającego oraz dla wartości przycisku kopiowania kodu- dane wejściowe odczytywane przez powiązania parametrów danego języka
Każda wartość jest ciągiem znaków, liczbą lub wartością logiczną. header_location przyjmuje obiekt z polami latitude i longitude. Pomiń nagłówek z multimediami, aby wysłać zatwierdzoną próbkę szablonu. Szablon zaimportowany z Meta nie ma próbki, więc wymaga klucza nagłówka z multimediami. Klucze, których dany język nie używa, są ignorowane.
{
"to": "+15551234567",
"from": "+13124495648",
"template": {
"slug": "order_update",
"language": "en",
"parameters": { "order_id": "A-4192", "first_name": "Ava" }
}
}W CLI przekaż obiekt za pomocą --parameters:
bird whatsapp send --to +15551234567 --from +13124495648 \
--template order_update --language en \
--parameters '{"order_id":"A-4192","first_name":"Ava"}'Szablon uwierzytelniający, którego treść brzmi {{1}} is your verification code, a przycisk kopiuje kod, przyjmuje kod jeden raz jako code. Bird wstawia go zarówno do treści, jak i do przycisku:
{
"parameters": { "code": "481920" }
}Języka, którego powiązania odczytują dane kontaktu, na przykład bird.contact.first_name, nie można wysłać jako pojedynczej wiadomości i zwraca on E15091. Zamiast tego wyślij go w ramach broadcastu, w którym wypełniają go dane kontaktu każdego odbiorcy. Broadcast pomija odbiorcę, którego dane kontaktu pozostawiają wymaganą wartość pustą. Wyślij parameters albo components, nie oba naraz. Niektóre szablony przyjmują tylko parameters: szablon, którego język oblicza wartości za pomocą powiązań parametrów, oraz szablon ze zmiennymi nazwanymi w karcie karuzeli lub w adresie URL przycisku.
Niektóre szablony przyjmują tylko components, ponieważ jeden klucz nie pozwala rozróżnić ich miejsc na wartości. Dzieje się tak, gdy szablon numeruje {{1}} w więcej niż jednym bloku, na przykład w nagłówku i w treści. Dzieje się tak również, gdy jeden blok ma dwa przyciski URL z numerowanymi sufiksami albo zmienną {{button_url}} obok numerowanego przycisku URL. Wysłanie takiego szablonu z parameters zwraca 422.
Wypełnianie szablonu według komponentów. components to alternatywa dla parameters i jedyna forma dla szablonu, którego nie da się zaadresować jednym kluczem. Każdy komponent określa type (header, body, button lub carousel) i tablicę parameters. Komponent carousel przyjmuje zamiast niej tablicę cards, z jednym wpisem na każdą zatwierdzoną kartę, w kolejności zatwierdzenia. Każda karta zawiera własną tablicę components z wpisami header, body i button. Każdy parametr określa własny type (text, image, video, gif, document lub location) i zawiera odpowiadające mu pole: text zwykły ciąg znaków, image/video/gif/document publiczny https url, a location punkt na mapie. Szablon z nazwanymi parametrami wymaga name w każdym parametrze, dokładnie zgodnego z nazwami zadeklarowanymi w szablonie (zobacz Opis pól). Szablon pozycyjny pomija name i przyjmuje wartości w kolejności {{n}}, więc pierwszy parametr wypełnia {{1}}. W obu przypadkach parametry niezgodne z deklaracją szablonu zwracają 422 WhatsAppTemplateParameterMismatch. Komponent header w szablonie zarządzanym przez Bird jest pomijany, ponieważ żaden szablon zarządzany przez Bird nie deklaruje zmiennej nagłówka, ale w szablonie utworzonym w Twoim obszarze roboczym jest przekazywany dalej. W ten sposób szablon użytkowy lub marketingowy z nagłówkiem multimedialnym otrzymuje swój obraz.
Ten sam szablon z kodem weryfikacyjnym przyjmuje kod pozycyjnie (bez name) jednocześnie jako parametr treści i parametr przycisku:
{
"components": [
{ "type": "body", "parameters": [{ "type": "text", "text": "481920" }] },
{ "type": "button", "parameters": [{ "type": "text", "text": "481920" }] }
]
}Kategoria i nadawca
Kategoria szablonu (authentication, utility lub marketing) określa, jak WhatsApp traktuje wiadomość, a wraz z krajem docelowym także jej koszt.
To, kto jest właścicielem nadawcy, decyduje, czy go podajesz:
- Szablon zarządzany przez Bird (jego slug zaczyna się od
bird_) jest wysyłany z numeru, który Bird utrzymuje dla tej kategorii, więc pomińfrom. Ustawienie go zwraca422WhatsAppSenderNotAllowed. - Wszystko inne podaje własnego nadawcę w
from: wiadomość serwisowa dowolnego typu i każdy szablon utworzony w Twoim obszarze roboczym. Numer musi należeć do Twojego obszaru roboczego. Pominięcie go zwraca422WhatsAppSenderRequired, a numer, z którego obszar roboczy nie może wysyłać, zwraca422WhatsAppSenderNotFound. Utworzony szablon musi też należeć do tego samego konta WhatsApp Business Account co numer, w przeciwnym razie wysyłka zwraca422WhatsAppSenderWABAMismatch.
Konfiguracja numeru telefonu opisuje oba typy numerów oraz sposób podłączenia własnego numeru.
Wiadomości serwisowe
Zamiast template przekaż dokładnie jedno z pól: text, image, video, audio, sticker, document, location, contact_cards lub interactive. Wszystkie dziewięć to wiadomości serwisowe, więc wymagają otwartego okna obsługi klienta. Każda z nich wymaga też from, czyli numeru należącego do Twojego obszaru roboczego; numery zarządzane przez Bird nie mogą ich przesyłać.
text:{ "body": "..." }, do 4096 znaków. Dodaj"preview_url": true, aby wyświetlić podgląd linku dla pierwszego adresu URL wbody.image,video,audio,sticker,document: każde z nich przyjmuje publiczny URLhttps, który WhatsApp pobiera w chwili wysyłki (url), więc podpisany URL musi pozostać ważny dłużej niż trwa wysyłka. URLhttpjest od razu odrzucany. WhatsApp sam pobiera plik, więc wiadomość z URL-em, do którego nie może dotrzeć, z URL-em zwracającym nieobsługiwany typ albo z plikiem przekraczającym limit rozmiaru dla danego typu zostaje przyjęta, a następnie kończy się niepowodzeniem, zmedia_rejectedw polulast_errorwiadomości i własnym powodem WhatsApp wdescription.image,videoidocumentprzyjmują też opcjonalnecaption;documentprzyjmuje też opcjonalnefilename;audioprzyjmuje opcjonalną flagęvoice, która wyświetla nagranie jako notatkę głosową.location:{ "latitude": ..., "longitude": ... }(oba wymagane, w stopniach dziesiętnych) oraz opcjonalnienameiaddress.contact_cards: tablica do pięciu kontaktów udostępnianych w jednej wiadomości. Polenamekażdej wizytówki wymagaformatted_nameoraz co najmniej jednej innej części (first_name,last_name,middle_name,prefixlubsuffix);phone_numbers,emails,urlsiaddressesprzyjmują po maksymalnie dziesięć wpisów, aorgibirthday(jakoYYYY-MM-DD) są opcjonalne. Jeśli wizytówka zawieraphone_numberw formacie E.164, otrzymuje przycisk otwierający czat z tym numerem.interactive: tekst główny oraz element do dotknięcia, w jednym z sześciu typów: przyciski odpowiedzi, menu listy, przycisk z linkiem, karuzela multimediów albo pojedynczy przycisk z prośbą o lokalizację lub numer telefonu odbiorcy. Strona Wiadomości interaktywne opisuje strukturę każdego typu, odpowiedzi generowane po dotknięciu oraz limity.
{
"to": "+16505551234",
"from": "+13124495648",
"text": { "body": "Your order shipped: https://example.com/track/A1B2C3", "preview_url": true }
}Żądanie bez treści lub z więcej niż jednym typem treści jest odrzucane z kodem 422.
Cytowanie wiadomości
Ustaw in_reply_to_message_id na identyfikator wiadomości WhatsApp, aby wysłać swoją wiadomość jako odpowiedź na nią, tak jak dotknięcie opcji odpowiedzi w aplikacji WhatsApp cytuje wiadomość. Odbiorca widzi Twoją wiadomość z cytowaną wiadomością nad nią, a pole jest zwracane przy każdym odczycie wiadomości.
Działa to również w drugą stronę: wiadomość przychodząca, którą WhatsApp oznacza jako odpowiedź, zawiera w tym samym polu identyfikator cytowanej wiadomości. Dzięki temu wiesz, na którą z Twoich wiadomości odpowiada. Wiadomość przychodząca, której WhatsApp nie oznacza, nie zawiera identyfikatora, a ustalenie cytowanej wiadomości również może się nie udać. Aby niezawodnie powiązać wiadomości, używaj jawnych identyfikatorów odpowiedzi interaktywnych razem ze stanem rozmowy lub zadania zapisanym w Twojej aplikacji. Wychodzące metadata pozostają w rekordzie wiadomości wychodzącej i nie są automatycznie kopiowane do odpowiedzi.
Cytat jest rozpoznawany przed przyjęciem wysyłki, więc cytat, którego nie da się wyświetlić, powoduje odrzucenie samego żądania i nic nie zostaje utworzone ani naliczone. Identyfikator, który nie wskazuje żadnej wiadomości w tym obszarze roboczym, albo wskazuje wiadomość starszą niż 15 dni, przez które wiadomość można cytować, zwraca 404 E15071 WhatsAppReferencedMessageNotFound. Identyfikator wskazujący wiadomość, która nigdy nie dotarła do WhatsApp, albo wiadomość z innej rozmowy niż ta wyznaczona przez to i from tej wysyłki, zwraca 422 E15072 WhatsAppMessageNotQuotable. Jeśli Bird nie może połączyć się z magazynem danych, który to rozstrzyga, wysyłka zwraca 503 E15073 WhatsAppMessageLookupUnavailable; w takim przypadku spróbuj ponownie. Cytowanie działa zarówno przy wysyłce szablonu, jak i wiadomości o dowolnej treści.
{
"to": "+16505551234",
"from": "+13124495648",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"text": { "body": "Yes, that slot is still free." }
}Tagi i metadane
Trzy opcjonalne pola dołączają do wiadomości Twój własny kontekst; wszystkie trzy są zwracane przy odczytach API i trafiają do każdego zdarzenia webhooka dotyczącego wiadomości:
tags: do 20 ustrukturyzowanych etykiet{ "name": ..., "value": ... }dla wymiarów o małej liczbie wartości, według których filtrujesz i raportujesz (kampania, wariant eksperymentu). Nazwy i wartości mogą zawierać litery ASCII, cyfry, podkreślenie i łącznik; nazwy mają maksymalnie 32 znaki i muszą być unikalne w ramach wysyłki, wartości maksymalnie 64 znaki. Filtruj listę wiadomości według tagu (?tag=campaignlub?tag=campaign:launch-week), a strona Metrics pokazuje dostarczalność w podziale na tagi.metadata: jeden dowolny obiekt JSON, do 2 KB po serializacji, na kontekst pojedynczej wysyłki, którego nie potrzebujesz jako wymiaru filtrowania (wewnętrzny identyfikator zamówienia, odwołanie do sesji).reference: jeden ciąg znaków o długości od 1 do 255 znaków, po którym chcesz wyszukiwać wiadomość, na przykład numer zamówienia lub zgłoszenia.?reference=na liście wiadomości dopasowuje go dokładnie, z rozróżnieniem wielkości liter, a kilka wiadomości może mieć tę samą wartość. Ustawiaj go tylko wtedy, gdy musisz po nim wyszukiwać, a pozostałe dane umieszczaj wmetadata.
{
"tags": [{ "name": "campaign", "value": "order-confirmations" }],
"metadata": { "order_id": "ord_8271" },
"reference": "ord_8271"
}Opis pól
| Pole | Typ | Wymagane | Limity / uwagi |
|---|---|---|---|
to | string | tak | Jeden odbiorca na wiadomość: numer telefonu w formacie E.164, identyfikator użytkownika w zakresie firmy, którego nie akceptuje żaden szablon z jednorazowym kodem weryfikacyjnym, lub identyfikator grupy WhatsApp (wag_…), który wysyła wiadomość do wszystkich uczestników tej grupy |
from | string (E.164) | nie** | Pomiń dla szablonu zarządzanego przez Bird, który sam wybiera nadawcę, oraz dla wysyłki do grupy, która używa numeru tej grupy; wymagane dla wiadomości serwisowej i dla szablonu utworzonego w Twoim obszarze roboczym, a numer musi należeć do Twojego obszaru roboczego |
template.slug | string | nie** | Slug szablonu, który Twój obszar roboczy może wysyłać; slugi zarządzane przez Bird zaczynają się od bird_ |
template.language | string | nie* | Tag języka szablonu (en, pt-BR); pomiń, aby wysłać szablon w jego domyślnym języku |
template.parameters | obiekt | nie | Wypełnia zmienne szablonu według nazwy, np. ref lub code; maksymalnie 16 KB, a bird jest zarezerwowane |
template.components | tablica | nie | Alternatywa dla parameters, jeden wpis na komponent: type to header, body, button lub carousel, a carousel przyjmuje cards zamiast parameters |
template.components[].parameters[].name | string | nie† | Symbol zastępczy, który wypełnia ta wartość, np. ref; w szablonie z nazwanymi parametrami jest wymagany i musi odpowiadać nazwom zadeklarowanym w szablonie, a w szablonie pozycyjnym się go pomija |
text | obiekt | nie** | Wiadomość serwisowa {body, preview_url?} ze zwykłym tekstem (do 4096 znaków); zobacz Zwykły tekst |
image, video, audio, sticker, document | obiekt | nie** | Wiadomość serwisowa z multimediami z url (oraz opcjonalnie caption lub filename, tam gdzie są obsługiwane); zobacz Wiadomości serwisowe |
location | obiekt | nie** | Pinezka {latitude, longitude, name?, address?}; zobacz Lokalizacje |
contact_cards | tablica | nie** | Maksymalnie 5 ustrukturyzowanych obiektów kontaktów vCard; zobacz Wizytówki kontaktów |
interactive | obiekt | nie** | Tekst treści i jeden typ elementu do dotknięcia; to wiadomość serwisowa, więc wymaga otwartego okna obsługi. Zobacz Wiadomości interaktywne |
in_reply_to_message_id | ciąg znaków | nie | Identyfikator wiadomości WhatsApp przechowywanej w tym obszarze roboczym, cytowanej w wysyłanej wiadomości; zwracany przy odczytach. Zobacz Cytowanie wiadomości |
tags | tablica | nie | Do 20 etykiet {name, value}; nazwa ≤ 32 znaki, wartość ≤ 64, nazwy unikalne |
reference | string | nie | 1–255 znaków; dokładne dopasowanie dla ?reference= na liście wiadomości |
metadata | obiekt | nie | Dowolny JSON, do 2 KB po serializacji |
* language jest opcjonalne; jeśli je pominiesz, zostanie wysłany domyślny język szablonu.
† name jest wymagane w każdym parametrze szablonu z nazwanymi parametrami. W szablonie pozycyjnym je pomiń. Zobacz Komponenty i parametry.
** Przekaż dokładnie jedno z dwojga: template albo pole treści wiadomości serwisowej (text, image, video, audio, sticker, document, location, contact_cards, interactive); zobacz Wiadomości serwisowe.
Model asynchroniczny: co oznacza 202
Udane wysłanie zwraca 202 Accepted z identyfikatorem wiadomości i status: accepted. 202 jest zwracany dopiero wtedy, gdy wysyłka zostanie trwale przyjęta; wiadomość nigdy nie jest przyjmowana, a potem po cichu odrzucana. Trwałe błędy, które możesz naprawić, kończą się od razu odpowiedzią 422: nieprawidłowy odbiorca, nieznany slug lub język szablonu, niezgodność parametrów albo wiadomość serwisowa wysłana przy zamkniętym oknie obsługi klienta (WhatsAppServiceWindowClosed). Niezasilony portfel do nich nie należy: wysyłka zostaje przyjęta, a wiadomość kończy się statusem rejected z insufficient_balance, gdy Bird spróbuje ją obciążyć. Faktyczne doręczenie odbywa się asynchronicznie: wiadomość przechodzi w stan sent, gdy przekazujemy ją do WhatsApp, a następnie w status końcowy (delivered lub failed) po nadejściu potwierdzenia. Informują o tym zdarzenia, webhooki i endpointy odczytu. Potwierdzenie odczytu jest udostępniane osobno, jako znacznik czasu read_at i zdarzenie whatsapp.read, a nie jako status.
Uwaga dotycząca prywatności: w przypadku szablonów z kategorii authentication API nigdy nie zwraca wypełnionych wartości. Echo 202 i każdy późniejszy odczyt zawierają dla tych wiadomości pustą tablicę components, więc kod weryfikacyjny nigdy nie pojawia się ponownie.
Bezpieczne ponowne próby
Wysyłaj nagłówek Idempotency-Key z unikalną wartością dla każdej logicznej wysyłki, a ponowne próby staną się bezpieczne. Jeśli pierwsze żądanie się powiodło, ale nie otrzymałeś odpowiedzi (przekroczenie limitu czasu, zerwane połączenie), powtórzenie go z tym samym kluczem zwraca pierwotny wynik zamiast wysyłać zduplikowaną wiadomość i za nią naliczać opłatę. Powtórzona odpowiedź zawiera nagłówek Idempotency-Replay. Format klucza i czas jego przechowywania opisuje strona idempotentność.
Odbieranie odpowiedzi
Wiadomości przychodzące trafiają do tego samego zasobu co wychodzące, a każda z nich resetuje okno obsługi. Strona Odbieranie wiadomości WhatsApp opisuje ich odczyt przez API, pobieranie multimediów wysłanych przez kontakt oraz webhook whatsapp.received.
Koszty i rozliczenia
WhatsApp nalicza opłatę za każdą wiadomość na podstawie kategorii szablonu i kraju odbiorcy; zobacz cennik WhatsApp. Opłata za wiadomość jest naliczana w dwóch krokach, w dwóch różnych momentach, a obiekt cost w wiadomości podaje oba:
| Pole | Co to jest | Kiedy się pojawia |
|---|---|---|
transaction_amount | Opłata Bird za obsługę wysyłki | Gdy Bird przetwarza przyjętą wysyłkę, przed jej nadaniem |
passthrough_amount | Część ceny wiadomości należna Meta, którą Bird przenosi bez zmian | Gdy nadejdzie odpowiednie potwierdzenie delivered lub read |
amount | Suma dotychczas wycenionych składników | Rośnie wraz z pojawieniem się każdego składnika |
currency_code | Waluta portfela Twojej organizacji, wspólna dla obu składników | Razem z pierwszym składnikiem |
Obie kwoty są ciągami dziesiętnymi, podanymi bez podatku.
Uwaga: do 30 września 2026 r. wiadomość serwisowa nie zawiera udziału Meta, podobnie jak szablon użytkowy dostarczony w otwartym oknie obsługi klienta. Od 1 października 2026 r. Meta pobiera opłaty za oba rodzaje wiadomości, z wyjątkiem 72-godzinnego bezpłatnego okna punktu wejścia, a każdy firmowy numer telefonu ma 1000 bezpłatnych wiadomości serwisowych miesięcznie: zmiany cen od października 2026.
Oba składniki są wyceniane na podstawie różnych danych. Opłata Bird zależy od kategorii wysłanego szablonu i kraju odbiorcy. Kraj wynika z numeru kierunkowego kraju w numerze telefonu, a przy wysyłce na identyfikator użytkownika w zakresie firmy z dwuliterowego prefiksu tego identyfikatora. Udział Meta zależy od kategorii, którą Meta sama zgłasza w odpowiednim potwierdzeniu, i może się ona różnić od kategorii szablonu: Meta może zgłosić authentication-international, gdy mają zastosowanie jej reguły dotyczące miejsca docelowego, lokalizacji firmy i uprawnień. Zobacz stawki authentication-international w WhatsApp.
Zawartość cost zależy od tego, jak daleko dotarła wiadomość:
- W momencie
202polecostma wartość null. Nic nie zostało jeszcze wycenione. - Po przetworzeniu pole
transaction_amountjest ustawione, aamountma tę samą wartość.passthrough_amountpozostaje null. - Po odpowiednim potwierdzeniu
deliveredlubreadpomyślnie zarejestrowana opłata Meta wypełniapassthrough_amount, aamountodzwierciedla zarejestrowane składniki.
Składnik o wartości null oznacza, że w tej projekcji nie zarejestrowano żadnej kwoty. Nie dowodzi to, że wiadomość była bezpłatna. Składnik jawnie wyceniony na zero ma wartość "0.00000".
Obie opłaty zawodzą też w różny sposób. Opłata Bird zawodzi w trybie zamkniętym: gdy nie może zostać pobrana po 202, bo portfel nie pokrywa wysyłki lub trasa nie ma skonfigurowanej ceny, wiadomość kończy się stanem rejected z kodem błędu insufficient_balance lub price_not_found i nic nie zostaje pobrane. Wiadomość rejected nigdy nie dotarła do WhatsApp i to odróżnia ją od failed. Udział Meta zawodzi w trybie otwartym: jeśli w chwili nadejścia potwierdzenia w portfelu brakuje środków lub brakuje stawki, opłata zostaje pominięta bez cofania zaobserwowanego stanu wiadomości. Druga opłata nigdy nie wstrzymuje dostarczenia.
Wiadomość obciążona przez Bird zachowuje tę opłatę za wysyłkę, nawet jeśli dostarczenie później się nie powiedzie. Opłata Meta jest przetwarzana z odpowiedniego wywołania zwrotnego delivered lub read, gdy Meta zgłasza zwykłe ceny z kategorią i miejscem docelowym, które da się ustalić. Obie ścieżki wywołań zwrotnych używają tej samej tożsamości opłaty i polegają na deduplikacji w usłudze rozliczeń. Uzgadniaj powtórzone potwierdzenia z rekordami rozliczeniowymi, zamiast traktować projekcję wiadomości jako trwałe potwierdzenie obciążenia. Ceny serwisowe lub ceny bezpłatnego punktu wejścia mogą zerować składnik Meta. Nieustalony składnik nie świadczy o tym, że wiadomość była bezpłatna.
Do uzgodnień finansowych używaj księgi rozliczeń. Pola cost wiadomości są projekcjami opłat i mogą być opóźnione lub niekompletne. Różnicę między obserwacjami wiadomości a rekordami rozliczeniowymi opisuje strona Metryki WhatsApp.
Zdarzenia WhatsApp nie zawierają kosztów. Aby odczytać którykolwiek składnik, pobierz wiadomość ponownie za pomocą GET /v1/whatsapp/messages/{id}.
Dalsze kroki
- Wiadomości serwisowe: wysyłaj tekst, multimedia i treści interaktywne w oknie obsługi klienta
- Szablony: wybierz szablon i podaj wartości jego zmiennych
- Odbieranie wiadomości WhatsApp: odczytuj odpowiedzi i pobieraj multimedia przychodzące
- Webhooki statusu wiadomości: otrzymuj aktualizacje o doręczeniu i błędach
- Idempotentność: bezpiecznie ponawiaj próby z nagłówkiem
Idempotency-Key
Powiązane zasoby
Przejdź do dokumentacji, przewodników i przykładów dotyczących tego tematu.