WhatsApp-berichten versturen
Deze handleiding behandelt het verzendendpoint, POST /v1/whatsapp/messages. Je bouwt één JSON-payload met een ontvanger en precies één type inhoud: een vooraf goedgekeurde template, of een servicebericht met tekst, een afbeelding, video, audio, een sticker, een document, een locatie, contactkaarten of iets om op te tikken. Bird retourneert 202 Accepted met een bericht-ID en levert asynchroon af. Welke van de twee je kunt versturen, hangt af van het klantenservicevenster. Elk verzoek verstuurt één bericht naar één ontvanger, en er is geen batchendpoint.
Een minimale verzending
De kleinste geldige payload bestaat uit een to-ontvanger en een template met de bijbehorende slug. Voeg language toe als je een specifieke taal wilt; laat je het weg, dan wordt de standaardtaal van de template verstuurd. Vul de variabelen die de template declareert in via parameters.
De curl-aanroep gebruikt de Amerikaanse host; begint je sleutel met bk_eu1_, roep dan https://eu1.platform.bird.com aan. De SDK's lezen de regio uit je sleutel af, dus die stellen geen host in.
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"
}
}
}'Het klantenservicevenster
Welke van de twee je kunt versturen, hangt af van één toestand: of het klantenservicevenster open is.
Het contact opent het venster door je bedrijfsnummer een bericht te sturen of te bellen. Het venster blijft 24 uur open en begint opnieuw te lopen telkens wanneer het contact je weer een bericht stuurt. Zolang het open is, kun je een servicebericht sturen, dus elke vrije inhoud: tekst, afbeelding, video, audio, sticker, document, locatie, contactkaarten of interactieve inhoud. Zodra het verloopt, bereikt alleen een vooraf goedgekeurde template het contact, en een antwoord daarop opent het venster opnieuw.
Bird houdt het venster voor je bij, dus een servicebericht dat je in een gesloten venster verstuurt, wordt geweigerd voordat er iets wordt aangemaakt of in rekening gebracht: het verzoek retourneert een 422 E15044 WhatsAppServiceWindowClosed. De controle gebeurt naar beste vermogen en laat bij twijfel door, dus een 202 bewijst niet dat het venster bij verzending echt open was. Verloopt het venster tussen acceptatie en verzending, dan mislukt het bericht asynchroon, met service_window_expired in de last_error van het bericht.
Zie het klantenservicevenster voor de volledige levenscyclus: wat het opent, wat het opnieuw laat beginnen en hoe het samenhangt met de prijzen.
De payload opbouwen
Ontvanger
to geeft één bestemming aan: een telefoonnummer, een business-scoped gebruikers-ID of een groeps-ID. Een telefoonnummer heeft de E.164-notatie: een + vooraan, de landcode en het abonneenummer, zoals +14155550100. Wij valideren het nummer. Een waarde die geen echt, bereikbaar nummer kan zijn (verkeerde lengte, niet-toegewezen prefix) wordt daarom geweigerd met een 422 WhatsAppInvalidRecipient voordat er iets in rekening wordt gebracht. Er is geen array met ontvangers en geen batchverzending. Wil je veel mensen bereiken die niet in één groep zitten, dan doe je één aanroep per ontvanger.
Met een business-scoped gebruikers-ID zoals US.13491208655302741918 bereik je een contact van wie je het telefoonnummer niet hebt. Zo antwoord je een contact dat je zonder nummer heeft benaderd. Er veranderen twee dingen: het verzendende nummer moet bij hetzelfde business portfolio horen als waar de ID bij hoort, en een sjabloon voor eenmalige verificatiecodes heeft een telefoonnummer nodig. Een door Bird beheerd sjabloon wordt bij acceptatie geweigerd met een 422 WhatsAppRecipientNotSupportedForTemplate. Een authenticatiesjabloon dat je werkruimte zelf heeft gemaakt, wordt geaccepteerd en mislukt daarna, omdat Meta er een telefoonnummer voor vereist.
to kent nog één vorm: een WhatsApp-groeps-ID zoals wag_01krdgeqcxet5s7t44vh8rt9mg, waarmee je naar alle deelnemers van die groepschat verzendt. Bij een groepsverzending laat je from weg, en de bezorging wordt voor de hele groep gerapporteerd in plaats van per ontvanger. Daarom staat dit op een eigen pagina: Verzenden naar een WhatsApp-groep.
Sjabloon
template geeft het vooraf goedgekeurde sjabloon aan dat je wilt verzenden:
slug(verplicht): de slug van het sjabloon, zoalsbird_order_confirmation. Deze moet overeenkomen met een sjabloon in je catalogus (kleine letters, cijfers en underscores).language: de taaltag van het sjabloon, zoalsenofpt-BR. Laat dit weg om de standaardtaal van het sjabloon te verzenden. Geef je een taal op die het sjabloon niet heeft, dan krijg je een422met de talen die het wel heeft. Het geaccepteerde bericht geeft de vastgestelde taal terug.parameters: de waarden voor de variabelen van het sjabloon, als één object met de namen als sleutels (zie Componenten en parameters). Laat dit weg bij een sjabloon zonder variabelen.components: dezelfde waarden in de componentvorm van Meta, in plaats vanparameters. Een paar sjablonen accepteren alleen deze vorm.
Op de pagina Templates bekijk je je sjablonen, hun talen en een voorbeeldweergave van elk sjabloon.
Componenten en parameters
Templates bevatten variabelen, met een naam ({{ref}}, {{amount}}) of met een nummer ({{1}}, {{2}}). Je vult ze via parameters, één object. De variables van de templateversie somt de sleutels op die de template accepteert en markeert de optionele. Elke sleutel is een van deze:
- de eigen naam van een benoemde variabele, zoals
order_id - het nummer van een genummerde variabele, zoals
1 header_url,header_filenameofheader_locationvoor een media- of locatieheader, enheader_url_1,header_url_2enzovoort voor de header van een carrouselkaartbutton_urlvoor het genummerde achtervoegsel van een URL-knop, enbutton_url_1,button_url_2enzovoort voor de knop van een carrouselkaart. Een benoemd achtervoegsel gebruikt zijn eigen naam.codevoor de code van een authenticatietemplate en voor de waarde van een kopieercodeknop- een invoer die de parameterkoppelingen van de taal uitlezen
Elke waarde is een string, getal of boolean. header_location accepteert een object met latitude en longitude. Laat je een mediaheader weg, dan wordt het goedgekeurde voorbeeld van de template verstuurd. Een template die uit Meta is geïmporteerd heeft geen voorbeeld, dus daarvoor heb je de sleutel van de mediaheader nodig. Sleutels die de taal niet gebruikt, worden genegeerd.
{
"to": "+15551234567",
"from": "+13124495648",
"template": {
"slug": "order_update",
"language": "en",
"parameters": { "order_id": "A-4192", "first_name": "Ava" }
}
}Geef het object in de CLI mee met --parameters:
bird whatsapp send --to +15551234567 --from +13124495648 \
--template order_update --language en \
--parameters '{"order_id":"A-4192","first_name":"Ava"}'Een authenticatietemplate met de body {{1}} is your verification code en een knop die de code kopieert, krijgt de code één keer mee als code. Bird vult daarmee zowel de body als de knop:
{
"parameters": { "code": "481920" }
}Een taal waarvan de koppelingen contactgegevens uitlezen, zoals bird.contact.first_name, kun je niet als los bericht versturen en geeft E15091 terug. Verstuur zo'n taal in plaats daarvan in een broadcast, waarin het contact van elke ontvanger de waarden invult. Een broadcast slaat een ontvanger over als diens contactgegevens een verplichte waarde leeg laten. Stuur parameters of components, niet allebei. Sommige templates accepteren alleen parameters: een template waarvan de taal de waarden berekent met parameterkoppelingen, en een template met benoemde variabelen in een carrouselkaart of een knop-URL.
Sommige templates accepteren alleen components, omdat één sleutel hun plaatsen niet van elkaar kan onderscheiden. Dat gebeurt wanneer een template {{1}} in meer dan één blok nummert, zoals in de header en de body. Het gebeurt ook wanneer één blok twee url-knoppen met genummerde achtervoegsels heeft, of een {{button_url}}-variabele naast een genummerde url-knop. Verstuur je zo'n template met parameters, dan krijg je 422 terug.
Een template per component vullen. components is het alternatief voor parameters, en de enige vorm voor een template die je niet met één sleutel kunt aanspreken. Elke component noemt een type (header, body, button of carousel) en een parameters-array. Een carousel neemt in plaats daarvan een cards-array, met één item per goedgekeurde kaart, in de volgorde van goedkeuring. Elke kaart bevat een eigen components-array met items voor header, body en button. Elke parameter noemt zijn eigen type (text, image, video, gif, document of location) en bevat het bijbehorende veld: voor text een gewone string, voor image/video/gif/document een openbare https url, en voor location een punt op de kaart. Een template met benoemde parameters vereist een name op elke parameter, die exact overeenkomt met de namen die de template declareert (zie Veldenoverzicht). Een positionele template laat name weg en neemt zijn waarden in plaats daarvan in de volgorde van {{n}}, dus de eerste parameter vult {{1}}. In beide gevallen leveren parameters die niet overeenkomen met wat de template declareert een 422 WhatsAppTemplateParameterMismatch op. Een header-component bij een door Bird beheerde template wordt genegeerd, omdat geen enkele door Bird beheerde template een headervariabele declareert. Bij een template die je werkruimte zelf heeft gemaakt wordt de component doorgestuurd, en zo krijgt een utility- of marketingtemplate met een mediaheader zijn afbeelding.
Dezelfde verificatiecodetemplate neemt de code positioneel aan als zowel bodyparameter als knopparameter (zonder name):
{
"components": [
{ "type": "body", "parameters": [{ "type": "text", "text": "481920" }] },
{ "type": "button", "parameters": [{ "type": "text", "text": "481920" }] }
]
}Categorie en afzender
De categorie van een template (authentication, utility of marketing) bepaalt hoe WhatsApp het bericht behandelt en, samen met het land van bestemming, wat het kost.
Wie eigenaar is van de afzender, bepaalt of je die opgeeft:
- Een door Bird beheerde template (de slug begint met
bird_) wordt verstuurd vanaf het nummer dat Bird voor die categorie aanhoudt, dus laat jefromweg. Stel je het toch in, dan krijg je een422WhatsAppSenderNotAllowedterug. - Al het andere noemt zijn eigen afzender in
from: een servicebericht van elk type en elke template die je werkruimte zelf heeft gemaakt. Het nummer moet eigendom zijn van je werkruimte. Laat je het weg, dan krijg je een422WhatsAppSenderRequiredterug, en een nummer waarvandaan de werkruimte niet kan versturen levert een422WhatsAppSenderNotFoundop. Een zelfgemaakte template moet ook in hetzelfde WhatsApp Business Account staan als het nummer, anders levert het versturen een422WhatsAppSenderWABAMismatchop.
Telefoonnummer instellen behandelt beide soorten nummers en hoe je een eigen nummer koppelt.
Serviceberichten
Gebruik in plaats van template precies één van text, image, video, audio, sticker, document, location, contact_cards of interactive. Alle negen zijn serviceberichten, dus ze hebben een open klantenservicevenster nodig. Elk ervan vereist ook from, een nummer dat eigendom is van je werkruimte; de beheerde nummers van Bird kunnen ze niet versturen.
text:{ "body": "..." }, maximaal 4.096 tekens. Voeg"preview_url": truetoe om een linkvoorbeeld te tonen voor de eerste URL inbody.image,video,audio,sticker,document: elk neemt een openbarehttps-URL die WhatsApp op het moment van verzenden ophaalt (url), dus een ondertekende URL moet langer geldig blijven dan de verzending. Eenhttp-URL wordt direct geweigerd. WhatsApp haalt het bestand zelf op, dus een URL die het niet kan bereiken, een URL die een niet-ondersteund type levert of een bestand boven de maximale grootte voor dat type wordt geaccepteerd en mislukt daarna, metmedia_rejectedin delast_errorvan het bericht en de eigen reden van WhatsApp indescription.image,videoendocumentnemen ook een optionelecaption;documentneemt ook een optionelefilename;audioneemt een optionelevoice-vlag om het als spraakbericht weer te geven.location:{ "latitude": ..., "longitude": ... }(beide verplicht, in decimale graden) plus optioneelnameenaddress.contact_cards: een array van maximaal vijf contacten die in één bericht worden gedeeld. Denamevan elke kaart heeftformatted_namenodig plus minstens één ander onderdeel (first_name,last_name,middle_name,prefixofsuffix);phone_numbers,emails,urlsenaddressesnemen elk maximaal tien items, enorgenbirthday(alsYYYY-MM-DD) zijn optioneel. Met eenphone_numberin E.164 krijgt die kaart een knop die een chat met dat nummer opent.interactive: hoofdtekst plus iets om op te tikken, in een van zes typen: antwoordknoppen, een lijstmenu, een linkknop, een mediacarrousel, of één knop die de ontvanger om zijn locatie of telefoonnummer vraagt. Interactieve berichten beschrijft de structuur van elk type, de antwoorden die een tik oplevert en de limieten.
{
"to": "+16505551234",
"from": "+13124495648",
"text": { "body": "Your order shipped: https://example.com/track/A1B2C3", "preview_url": true }
}Een verzoek zonder inhoud, of met meer dan één type, wordt geweigerd met een 422.
Een bericht citeren
Stel in_reply_to_message_id in op een WhatsApp-bericht-ID om je bericht als antwoord daarop te verzenden, zoals tikken op beantwoorden in de WhatsApp-app een bericht citeert. De ontvanger ziet je bericht met het geciteerde bericht erboven, en het veld komt terug bij elke keer dat je het bericht leest.
Het werkt ook andersom: een inkomend bericht dat WhatsApp als antwoord markeert, bevat de ID van het geciteerde bericht in hetzelfde veld. Zo zie je op welk van je berichten een antwoord reageert. Een inkomend bericht dat WhatsApp niet markeert, bevat geen ID, en het koppelen kan ook mislukken. Gebruik voor betrouwbare koppeling expliciete interactieve antwoord-ID's samen met de gesprek- of taakstatus die je applicatie opslaat. Uitgaande metadata blijven op het uitgaande record staan en worden niet automatisch naar het antwoord gekopieerd.
Het citaat wordt opgezocht voordat de verzending wordt geaccepteerd, dus een citaat dat niet kan worden weergegeven laat het verzoek zelf mislukken en er wordt niets aangemaakt of in rekening gebracht. Een ID die naar geen bericht in deze werkruimte verwijst, of naar een bericht ouder dan de 15 dagen dat een bericht citeerbaar blijft, geeft een 404 E15071 WhatsAppReferencedMessageNotFound. Een ID die naar een bericht verwijst dat WhatsApp nooit heeft bereikt, of naar een bericht uit een ander gesprek dan dat van de to en from van deze verzending, geeft een 422 E15072 WhatsAppMessageNotQuotable. Als Bird de opslag die dit controleert niet kan bereiken, geeft de verzending een 503 E15073 WhatsAppMessageLookupUnavailable, en dan loont het om opnieuw te proberen. Citeren werkt zowel bij het verzenden van een template als bij een vrij bericht.
{
"to": "+16505551234",
"from": "+13124495648",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"text": { "body": "Yes, that slot is still free." }
}Tags en metadata
Met drie optionele velden koppel je je eigen context aan een bericht; alle drie komen terug bij het lezen via API en worden meegestuurd met elk webhook-event voor het bericht:
tags: maximaal 20 gestructureerde{ "name": ..., "value": ... }-labels voor dimensies met weinig verschillende waarden waarop je filtert en rapporteert (een campagne, een variant van een experiment). Namen en waarden bestaan uit ASCII-letters, cijfers, underscores en koppeltekens; namen zijn maximaal 32 tekens en uniek binnen een verzending, waarden maximaal 64. Filter de berichtenlijst op tag (?tag=campaignof?tag=campaign:launch-week), en de pagina Metrics splitst de aflevering uit per tag.metadata: één willekeurig JSON-object van maximaal 2 KB in geserialiseerde vorm, voor context per verzending waarop je niet hoeft te filteren (een intern order-ID, een sessiereferentie).reference: één string van 1 tot 255 tekens waarmee je het bericht wilt terugvinden, zoals een order- of ticketnummer.?reference=op de berichtenlijst zoekt hier exact en hoofdlettergevoelig op, en meerdere berichten kunnen dezelfde waarde hebben. Stel het alleen in als je erop moet zoeken, en zet andere gegevens inmetadata.
{
"tags": [{ "name": "campaign", "value": "order-confirmations" }],
"metadata": { "order_id": "ord_8271" },
"reference": "ord_8271"
}Veldenoverzicht
| Veld | Type | Verplicht | Limieten / opmerkingen |
|---|---|---|---|
to | string | ja | Eén ontvanger per bericht: een E.164-telefoonnummer, een bedrijfsgebonden gebruikers-ID, die geen enkele template voor eenmalige verificatiecodes accepteert, of een WhatsApp-groeps-ID (wag_…), waarmee je naar elke deelnemer van die groep verzendt |
from | string (E.164) | nee** | Laat weg bij een door Bird beheerde template, die zelf een afzender kiest, en bij een groepsbericht, dat het eigen nummer van de groep gebruikt; verplicht voor een servicebericht en voor een template die je werkruimte zelf heeft gemaakt, en moet een nummer zijn dat je werkruimte bezit |
template.slug | string | nee** | Een templateslug die je werkruimte kan verzenden; slugs die door Bird worden beheerd, beginnen met bird_ |
template.language | string | nee* | Taaltag van de template (en, pt-BR); laat weg om de standaardtaal van de template te verzenden |
template.parameters | object | nee | Vult de variabelen van de template op naam, zoals ref of code; maximaal 16 KB, en bird is gereserveerd |
template.components | array | nee | Het alternatief voor parameters, één item per component: type is header, body, button of carousel, en een carousel neemt cards in plaats van parameters |
template.components[].parameters[].name | string | nee† | De placeholder die deze waarde vult, zoals ref; verplicht bij een template met benoemde parameters en moet dan overeenkomen met de namen die de template declareert, weglaten bij een positionele template |
text | object | nee** | {body, preview_url?} servicebericht met platte tekst (maximaal 4.096 tekens); zie Platte tekst |
image, video, audio, sticker, document | object | nee** | Servicebericht met media en url (en optioneel caption of filename waar ondersteund); zie Serviceberichten |
location | object | nee** | {latitude, longitude, name?, address?}-locatiepin; zie Locaties |
contact_cards | array | nee** | Maximaal 5 gestructureerde vCard-contactobjecten; zie Contactkaarten |
interactive | object | nee** | Hoofdtekst plus één type aantikbare inhoud; dit is een servicebericht, dus er moet een servicevenster open zijn. Zie Interactieve berichten |
in_reply_to_message_id | string | nee | Een WhatsApp-bericht-ID die deze werkruimte bewaart en die wordt geciteerd in het bericht dat je verstuurt; wordt teruggegeven bij het uitlezen. Zie Een bericht citeren |
tags | array | nee | Maximaal 20 {name, value}-labels; naam ≤ 32 tekens, waarde ≤ 64, namen uniek |
reference | string | nee | 1–255 tekens; exacte overeenkomst voor ?reference= in de berichtenlijst |
metadata | object | nee | Willekeurige JSON, maximaal 2 KB geserialiseerd |
* language is optioneel; als je het weglaat, wordt de standaardtaal van de template verzonden.
† name is bij een template met benoemde parameters verplicht op elke parameter. Laat het weg bij een positionele template. Zie Componenten en parameters.
** Neem precies één van de volgende op: template of een inhoudsveld voor een servicebericht (text, image, video, audio, sticker, document, location, contact_cards, interactive); zie Serviceberichten.
Het asynchrone model: wat 202 betekent
Een geslaagde verzending retourneert 202 Accepted met een bericht-ID en status: accepted. De 202 wordt pas geretourneerd nadat de verzending duurzaam is geaccepteerd; een verzending wordt nooit geaccepteerd en daarna stilzwijgend verworpen. Harde fouten die je kunt oplossen, falen direct met een 422: een ongeldige ontvanger, een onbekende templateslug of taal, parameters die niet overeenkomen, of een servicebericht dat je verstuurt terwijl het klantenservicevenster gesloten is (WhatsAppServiceWindowClosed). Een wallet zonder saldo hoort daar niet bij: de verzending wordt geaccepteerd en het bericht eindigt als rejected met insufficient_balance zodra Bird probeert het af te rekenen. De daadwerkelijke aflevering gebeurt asynchroon: het bericht gaat naar sent wanneer we het aan WhatsApp overdragen, en daarna naar een eindstatus (delivered of failed) wanneer de ontvangstbevestiging binnenkomt. Dat wordt gemeld via events, webhooks en de leesendpoints. Een leesbevestiging verschijnt apart als een read_at-tijdstempel en een whatsapp.read-event, niet als een status.
Een opmerking over privacy: bij templates in de categorie authentication retourneert de API nooit de ingevulde waarden. De echo van 202 en elke latere leesactie bevatten voor die berichten een lege components-array, zodat een verificatiecode nooit opnieuw opduikt.
Veilig opnieuw proberen
Stuur de header Idempotency-Key mee met een unieke waarde per logische verzending, dan kun je veilig opnieuw proberen. Is je eerste verzoek gelukt maar heb je het antwoord nooit ontvangen (time-out, verbroken verbinding), dan levert een nieuwe poging met dezelfde sleutel het oorspronkelijke resultaat op, in plaats van dat er een dubbel bericht wordt verstuurd en gefactureerd. Het herhaalde antwoord bevat een Idempotency-Replay-header. Zie idempotentie voor het sleutelformaat en de bewaartermijn.
Het antwoord ontvangen
Inkomende berichten komen op dezelfde resource terecht als uitgaande, en elk inkomend bericht reset het servicevenster. WhatsApp-berichten ontvangen beschrijft hoe je ze leest via de API, hoe je media ophaalt die een contact heeft gestuurd, en de whatsapp.received-webhook.
Kosten en facturering
WhatsApp rekent per bericht af, op basis van de categorie van de template en het land van de ontvanger; zie WhatsApp-prijzen. Een bericht wordt in twee stappen afgerekend, op twee verschillende momenten, en het cost-object op het bericht toont beide:
| Veld | Wat het is | Wanneer het verschijnt |
|---|---|---|
transaction_amount | De vergoeding van Bird voor het verwerken van de verzending | Wanneer Bird de geaccepteerde verzending verwerkt, vóór verzending naar de ontvanger |
passthrough_amount | Het aandeel van Meta in de berichtprijs, dat Bird doorberekent | Wanneer een toepasselijke delivered- of read-ontvangstbevestiging binnenkomt |
amount | De som van de tot nu toe geprijsde componenten | Neemt toe naarmate elke component wordt vastgelegd |
currency_code | De valuta van de wallet van je organisatie, gedeeld door beide componenten | Samen met de eerste component |
Beide bedragen zijn decimale strings, exclusief belasting.
Let op: tot en met 30 september 2026 bevat een servicebericht geen aandeel van Meta, en een utility-template dat binnen een open klantenservicevenster wordt afgeleverd evenmin. Vanaf 1 oktober 2026 rekent Meta voor beide, behalve binnen een gratis entry-point-venster van 72 uur, en met 1.000 gratis serviceberichten per zakelijk telefoonnummer per maand: prijswijzigingen van oktober 2026.
De twee componenten worden op basis van verschillende gegevens geprijsd. De vergoeding van Bird gebruikt de categorie van het template dat je hebt verzonden en het land van de ontvanger. Dat land volgt uit de landcode van het telefoonnummer of, bij een verzending aan een business-scoped user ID, uit het voorvoegsel van twee letters in die ID. Het aandeel van Meta gebruikt de categorie die Meta zelf in de betreffende ontvangstbevestiging meldt, en die kan afwijken van die van het template: Meta kan authentication-international melden wanneer de regels voor bestemming, bedrijfslocatie en geschiktheid van toepassing zijn. Zie WhatsApp-tarieven voor authentication-international.
Wat cost bevat, hangt af van hoe ver het bericht is gekomen:
- Bij de
202iscostnull. Er is nog niets geprijsd. - Na verwerking is
transaction_amountingevuld en isamountdaaraan gelijk.passthrough_amountblijft null. - Na een betreffende
delivered- ofread-ontvangstbevestiging vult een succesvol geregistreerde Meta-kostenpostpassthrough_amount, enamountgeeft de geregistreerde componenten weer.
Een null-component betekent dat er in die projectie geen bedrag is geregistreerd; het bewijst niet dat het bericht gratis was. Een component die expliciet op nul is geprijsd, bevat "0.00000".
De twee kostenposten mislukken ook op verschillende manieren. De vergoeding van Bird faalt gesloten: als die na de 202 niet kan worden verwerkt omdat de wallet de verzending niet dekt of de route geen ingestelde prijs heeft, eindigt het bericht als rejected met de foutcode insufficient_balance of price_not_found, en wordt er niets in rekening gebracht. Een rejected-bericht heeft WhatsApp nooit bereikt, en daarin verschilt het van failed. Het aandeel van Meta faalt open: als het saldo van de wallet tekortschiet of het tarief ontbreekt wanneer de ontvangstbevestiging binnenkomt, wordt de kostenpost overgeslagen zonder de waargenomen status van het bericht terug te draaien. De tweede kostenpost houdt je aflevering nooit op.
Een bericht waarvoor Bird kosten heeft gerekend, houdt die uitgaande kostenpost als de aflevering later mislukt. De Meta-vergoeding wordt verwerkt vanuit een betreffende delivered- of read-callback wanneer Meta reguliere prijzen meldt met een herleidbare categorie en bestemming. Beide callbackpaden gebruiken dezelfde vergoedingsidentiteit en vertrouwen op de deduplicatie van de factureringsservice. Stem herhaalde ontvangstbevestigingen af met de factureringsgegevens, en behandel de berichtprojectie niet als een permanent afschrijvingsbewijs. Service- of free-entry-prijzen kunnen de Meta-component op nul zetten; een onopgeloste component bewijst niet dat het bericht gratis was.
Gebruik het factureringsgrootboek voor financiële afstemming. De cost-velden van een bericht zijn projecties van de kostenposten en kunnen achterlopen of onvolledig blijven. Zie WhatsApp-statistieken voor het onderscheid tussen berichtwaarnemingen en factureringsgegevens.
WhatsApp-events bevatten geen kosten. Lees het bericht opnieuw op met GET /v1/whatsapp/messages/{id} om een van beide componenten te zien.
Volgende stappen
- Servicemessages: verstuur tekst, media en interactieve content binnen het klantenservicevenster
- Templates: kies een template en vul de variabelen ervan in
- WhatsApp-berichten ontvangen: lees antwoorden en haal inkomende media op
- Webhooks voor berichtstatus: ontvang updates over aflevering en mislukte berichten
- Idempotentie: probeer veilig opnieuw met de header
Idempotency-Key
Gerelateerde bronnen
Ga verder met de documentatie, handleidingen en voorbeelden voor dit onderwerp.