Mengirim pesan WhatsApp
Panduan ini membahas endpoint pengiriman, POST /v1/whatsapp/messages. Anda menyusun satu payload JSON berisi penerima dan tepat satu jenis konten: template yang sudah disetujui, atau pesan layanan berisi teks, gambar, video, audio, stiker, dokumen, lokasi, kartu kontak, atau elemen yang dapat diketuk. Bird mengembalikan 202 Accepted dengan ID pesan dan melakukan pengiriman secara asinkron. Jenis yang dapat Anda kirim bergantung pada jendela layanan pelanggan. Setiap permintaan mengirim satu pesan ke satu penerima, dan tidak ada endpoint batch.
Pengiriman minimal
Payload valid terkecil terdiri dari penerima to dan template beserta slug-nya. Tambahkan language jika Anda menginginkan bahasa tertentu; jika dihilangkan, template dikirim dalam bahasa default-nya. Isi variabel yang dideklarasikan template melalui parameters.
Panggilan curl menggunakan host AS; jika kunci Anda diawali bk_eu1_, panggil https://eu1.platform.bird.com. SDK membaca region dari kunci Anda, jadi SDK tidak menetapkan host.
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"
}
}
}'Jendela layanan pelanggan
Jenis yang dapat Anda kirim bergantung pada satu kondisi: apakah jendela layanan pelanggan sedang terbuka.
Kontak membuka jendela dengan mengirim pesan atau menelepon nomor bisnis Anda. Jendela tetap terbuka selama 24 jam dan diatur ulang setiap kali kontak mengirim pesan lagi. Selama jendela terbuka, Anda dapat mengirim pesan layanan, yaitu konten bebas apa pun: teks, gambar, video, audio, stiker, dokumen, lokasi, kartu kontak, atau interaktif. Setelah jendela berakhir, hanya template yang sudah disetujui yang dapat menjangkau kontak, dan balasan mereka atas template itu membuka jendela kembali.
Bird melacak jendela untuk Anda, sehingga pesan layanan yang dikirim saat jendela tertutup ditolak sebelum apa pun dibuat atau ditagih: permintaan mengembalikan 422 E15044 WhatsAppServiceWindowClosed. Pemeriksaan ini bersifat upaya terbaik dan meloloskan permintaan jika gagal, jadi 202 tidak membuktikan bahwa jendela benar-benar terbuka saat pengiriman. Jendela yang berakhir antara penerimaan dan pengiriman akan gagal secara asinkron, dengan service_window_expired pada last_error pesan.
Lihat jendela layanan pelanggan untuk siklus lengkapnya: apa yang membukanya, apa yang mengatur ulangnya, dan kaitannya dengan harga.
Menyusun payload
Penerima
to menentukan satu tujuan, berupa nomor telepon, ID pengguna bercakupan bisnis, atau ID grup. Nomor telepon menggunakan format E.164: diawali +, lalu kode negara dan nomor pelanggan, misalnya +14155550100. Kami memvalidasi nomor tersebut, sehingga nilai yang tidak mungkin menjadi nomor nyata yang dapat dihubungi (panjang salah, prefiks belum dialokasikan) ditolak dengan 422 WhatsAppInvalidRecipient sebelum ada biaya apa pun. Tidak ada array penerima dan tidak ada pengiriman massal, jadi untuk menjangkau banyak orang yang tidak berada dalam satu grup, Anda perlu melakukan satu panggilan per penerima.
ID pengguna bercakupan bisnis seperti US.13491208655302741918 menuju kontak yang nomor teleponnya tidak Anda miliki. Dengan cara inilah Anda membalas kontak yang menghubungi Anda tanpa nomor telepon. Ada dua perbedaan: nomor pengirim harus termasuk dalam portofolio bisnis yang sama dengan cakupan ID tersebut, dan template kode verifikasi sekali pakai memerlukan nomor telepon. Template yang dikelola Bird ditolak saat penerimaan dengan 422 WhatsAppRecipientNotSupportedForTemplate. Template autentikasi yang dibuat oleh workspace Anda diterima, lalu gagal, karena Meta mewajibkan nomor telepon untuk template tersebut.
to juga menerima satu bentuk lain: ID grup WhatsApp seperti wag_01krdgeqcxet5s7t44vh8rt9mg, yang mengirim pesan ke setiap peserta obrolan grup tersebut. Pengiriman ke grup tidak menyertakan from dan melaporkan pengirimannya untuk seluruh grup, bukan untuk satu penerima. Karena itu, Mengirim ke grup WhatsApp membahasnya di halaman tersendiri.
Template
template menentukan template yang telah disetujui untuk dikirim:
slug(wajib): slug template, misalnyabird_order_confirmation. Slug harus cocok dengan template di katalog Anda (huruf kecil, angka, dan garis bawah).language: tag bahasa template, misalnyaenataupt-BR. Hilangkan untuk mengirim bahasa default template. Jika Anda menyebut bahasa yang tidak dimiliki template, permintaan mengembalikan422yang mencantumkan bahasa yang tersedia. Pesan yang diterima menampilkan kembali bahasa yang diterapkan.parameters: nilai pengisi variabel template, sebagai satu objek dengan kunci berupa nama (lihat Komponen dan parameter). Hilangkan untuk template tanpa variabel.components: nilai yang sama dalam bentuk komponen Meta, sebagai penggantiparameters. Beberapa template hanya menerima bentuk ini.
Telusuri template Anda, bahasanya, dan pratinjau masing-masing di halaman Templates.
Komponen dan parameter
Template memiliki variabel, baik bernama ({{ref}}, {{amount}}) maupun bernomor ({{1}}, {{2}}). Isi variabel tersebut melalui parameters, dalam satu objek. variables pada versi template mencantumkan kunci yang diterimanya dan menandai kunci yang opsional. Setiap kunci adalah salah satu dari berikut:
- nama variabel bernama itu sendiri, seperti
order_id - nomor variabel bernomor, seperti
1 header_url,header_filename, atauheader_locationuntuk header media atau lokasi, sertaheader_url_1,header_url_2, dan seterusnya untuk header kartu carouselbutton_urluntuk sufiks bernomor pada tombol URL, sertabutton_url_1,button_url_2, dan seterusnya untuk tombol kartu carousel. Sufiks bernama menggunakan namanya sendiri.codeuntuk kode pada template autentikasi, dan untuk nilai tombol salin kode- input yang dibaca oleh binding parameter bahasa tersebut
Setiap nilai berupa string, angka, atau boolean. header_location menerima objek dengan latitude dan longitude. Jika Anda tidak menyertakan header media, sampel template yang telah disetujui akan dikirim. Template yang diimpor dari Meta tidak memiliki sampel, sehingga memerlukan kunci header media. Kunci yang tidak digunakan oleh bahasa tersebut akan diabaikan.
{
"to": "+15551234567",
"from": "+13124495648",
"template": {
"slug": "order_update",
"language": "en",
"parameters": { "order_id": "A-4192", "first_name": "Ava" }
}
}Pada CLI, teruskan objek tersebut dengan --parameters:
bird whatsapp send --to +15551234567 --from +13124495648 \
--template order_update --language en \
--parameters '{"order_id":"A-4192","first_name":"Ava"}'Template autentikasi yang isinya berbunyi {{1}} is your verification code dan tombolnya menyalin kode menerima kode tersebut satu kali sebagai code. Bird mengisikan kode itu ke isi pesan dan tombol sekaligus:
{
"parameters": { "code": "481920" }
}Bahasa yang binding-nya membaca data kontak, seperti bird.contact.first_name, tidak dapat dikirim sebagai pesan tunggal dan mengembalikan E15091. Kirimkan dalam broadcast, tempat data kontak setiap penerima mengisinya. Broadcast melewati penerima yang data kontaknya membuat nilai wajib kosong. Kirim parameters atau components, jangan keduanya. Beberapa template hanya menerima parameters: template yang bahasanya menghitung nilai dengan binding parameter, dan template dengan variabel bernama di kartu carousel atau URL tombol.
Beberapa template hanya menerima components, karena satu kunci tidak dapat membedakan slot-slotnya. Hal ini terjadi ketika template memberi nomor {{1}} di lebih dari satu blok, misalnya di header dan body. Hal ini juga terjadi ketika satu blok memiliki dua tombol url dengan sufiks bernomor, atau variabel {{button_url}} di samping tombol url bernomor. Mengirim template seperti itu dengan parameters akan mengembalikan 422.
Isi template per komponen. components adalah alternatif untuk parameters, dan satu-satunya bentuk untuk template yang tidak dapat dialamatkan dengan satu kunci. Setiap komponen menyebutkan type (header, body, button, atau carousel) dan array parameters. carousel menerima array cards sebagai gantinya, satu entri per kartu yang disetujui, sesuai urutan persetujuan. Setiap kartu memiliki array components sendiri yang berisi entri header, body, dan button. Setiap parameter menyebutkan type miliknya sendiri (text, image, video, gif, document, atau location) dan membawa field yang sesuai: text berupa string biasa, image/video/gif/document berupa https url publik, dan location berupa titik di peta. Template dengan parameter bernama mewajibkan name di setiap parameter, yang sama persis dengan nama yang dideklarasikan template (lihat Referensi kolom). Template posisional tidak menyertakan name dan menerima nilainya berdasarkan urutan {{n}}, sehingga parameter pertama mengisi {{1}}. Dalam kedua kasus, parameter yang tidak sesuai dengan deklarasi template mengembalikan 422 WhatsAppTemplateParameterMismatch. Komponen header pada template yang dikelola Bird dibuang karena tidak ada template yang dikelola Bird yang mendeklarasikan variabel header. Pada template yang dibuat workspace Anda, komponen ini diteruskan, dan dengan cara inilah template utility atau marketing dengan header media mendapatkan gambarnya.
Template kode verifikasi yang sama menerima kode sebagai parameter body sekaligus parameter tombol, secara posisional (tanpa name):
{
"components": [
{ "type": "body", "parameters": [{ "type": "text", "text": "481920" }] },
{ "type": "button", "parameters": [{ "type": "text", "text": "481920" }] }
]
}Kategori dan pengirim
Kategori template (authentication, utility, atau marketing) menentukan cara WhatsApp memperlakukan pesan dan, bersama negara tujuan, biayanya.
Pemilik pengirim menentukan apakah Anda perlu menyebutkannya:
- Template yang dikelola Bird (slug-nya diawali
bird_) dikirim dari nomor yang disediakan Bird untuk kategori tersebut, jadi jangan sertakanfrom. Jika Anda mengisinya, permintaan mengembalikan422WhatsAppSenderNotAllowed. - Selain itu, pesan menyebutkan pengirimnya sendiri di
from: service message jenis apa pun, dan template apa pun yang dibuat workspace Anda. Nomor tersebut harus dimiliki workspace Anda. Jika tidak disertakan, permintaan mengembalikan422WhatsAppSenderRequired, dan nomor yang tidak dapat digunakan workspace untuk mengirim mengembalikan422WhatsAppSenderNotFound. Template yang Anda buat juga harus berada di WhatsApp Business Account yang sama dengan nomornya. Jika tidak, pengiriman mengembalikan422WhatsAppSenderWABAMismatch.
Penyiapan nomor telepon membahas kedua jenis nomor dan cara menghubungkan nomor milik Anda sendiri.
Service message
Sebagai ganti template, sertakan tepat satu dari text, image, video, audio, sticker, document, location, contact_cards, atau interactive. Kesembilannya adalah service message, sehingga memerlukan jendela layanan pelanggan yang terbuka. Semuanya juga mewajibkan from, yaitu nomor yang dimiliki workspace Anda. Nomor yang dikelola Bird tidak dapat mengirimkannya.
text:{ "body": "..." }, hingga 4.096 karakter. Tambahkan"preview_url": trueuntuk menampilkan pratinjau tautan bagi URL pertama dibody.image,video,audio,sticker,document: masing-masing menerima URLhttpspublik yang diambil WhatsApp saat pengiriman (url), sehingga URL bertanda tangan harus tetap berlaku hingga pengiriman selesai. URLhttplangsung ditolak. WhatsApp mengambil file itu sendiri, sehingga URL yang tidak dapat dijangkaunya, URL yang menyajikan jenis yang tidak didukung, atau file yang melebihi batas ukuran untuk jenisnya akan diterima lalu gagal, denganmedia_rejectedpadalast_errorpesan dan alasan dari WhatsApp sendiri didescription.image,video, dandocumentjuga menerimacaptionopsional;documentjuga menerimafilenameopsional;audiomenerima flagvoiceopsional agar ditampilkan sebagai pesan suara.location:{ "latitude": ..., "longitude": ... }(keduanya wajib, dalam derajat desimal) ditambahnamedanaddressopsional.contact_cards: array berisi hingga lima kontak yang dibagikan dalam satu pesan.namesetiap kartu memerlukanformatted_nameditambah setidaknya satu bagian lain (first_name,last_name,middle_name,prefix, atausuffix);phone_numbers,emails,urls, danaddressesmasing-masing menerima hingga sepuluh entri, sedangkanorgdanbirthday(sebagaiYYYY-MM-DD) bersifat opsional. Jikaphone_numberdalam format E.164, kartu tersebut mendapat tombol untuk membuka chat dengan nomor itu.interactive: teks isi ditambah elemen yang dapat diketuk, dalam salah satu dari enam jenis: tombol balasan, menu daftar, tombol tautan, carousel media, atau satu tombol yang meminta lokasi atau nomor telepon penerima. Pesan interaktif menjelaskan struktur payload setiap jenis, balasan yang dihasilkan oleh ketukan, dan batasannya.
{
"to": "+16505551234",
"from": "+13124495648",
"text": { "body": "Your order shipped: https://example.com/track/A1B2C3", "preview_url": true }
}Permintaan tanpa konten, atau dengan lebih dari satu jenis konten, ditolak dengan 422.
Mengutip pesan
Atur in_reply_to_message_id ke ID pesan WhatsApp untuk mengirim pesan Anda sebagai balasan atas pesan tersebut, seperti saat Anda mengetuk balas di aplikasi WhatsApp untuk mengutip pesan. Penerima melihat pesan Anda dengan pesan yang dikutip di atasnya, dan field ini disertakan setiap kali pesan dibaca.
Hal ini juga berlaku sebaliknya: pesan masuk yang ditandai WhatsApp sebagai balasan membawa ID pesan yang dikutip di field yang sama, sehingga Anda dapat mengetahui pesan mana yang dibalas. Pesan masuk yang tidak ditandai WhatsApp tidak membawa ID, dan resolusinya juga bisa gagal. Untuk korelasi yang andal, gunakan identifier balasan interaktif eksplisit bersama status percakapan atau tugas yang disimpan aplikasi Anda. metadata keluar tetap berada pada catatan keluar dan tidak otomatis disalin ke balasan.
Kutipan di-resolve sebelum pengiriman diterima, sehingga kutipan yang tidak dapat ditampilkan membuat permintaan itu sendiri gagal, dan tidak ada yang dibuat atau ditagih. ID yang tidak merujuk ke pesan mana pun di workspace ini, atau yang lebih lama dari 15 hari masa pesan dapat dikutip, menghasilkan 404 E15071 WhatsAppReferencedMessageNotFound. ID yang merujuk ke pesan yang tidak pernah sampai ke WhatsApp, atau ke pesan dari percakapan yang berbeda dengan to dan from pengiriman ini, menghasilkan 422 E15072 WhatsAppMessageNotQuotable. Jika Bird tidak dapat menjangkau penyimpanan yang menjawab pertanyaan ini, pengiriman menghasilkan 503 E15073 WhatsAppMessageLookupUnavailable, yang layak dicoba lagi. Pengutipan berlaku untuk pengiriman template maupun pengiriman bebas format.
{
"to": "+16505551234",
"from": "+13124495648",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"text": { "body": "Yes, that slot is still free." }
}Tag dan metadata
Tiga field opsional melampirkan konteks Anda sendiri ke pesan; ketiganya disertakan saat pembacaan API dan ikut terkirim di setiap event webhook untuk pesan tersebut:
tags: hingga 20 label{ "name": ..., "value": ... }terstruktur untuk dimensi berkardinalitas rendah yang Anda gunakan untuk memfilter dan membuat laporan (misalnya kampanye atau varian eksperimen). Nama dan nilai menggunakan huruf ASCII, angka, garis bawah, dan tanda hubung; nama dibatasi 32 karakter dan harus unik dalam satu pengiriman, sedangkan nilai dibatasi 64 karakter. Filter daftar pesan berdasarkan tag (?tag=campaignatau?tag=campaign:launch-week), dan halaman Metrics merinci pengiriman berdasarkan tag.metadata: satu objek JSON bebas, hingga 2 KB setelah diserialisasi, untuk konteks per pengiriman yang tidak Anda perlukan sebagai dimensi filter (ID pesanan internal, referensi sesi).reference: satu string berisi 1 hingga 255 karakter yang Anda gunakan untuk menemukan pesan, seperti nomor pesanan atau nomor tiket.?reference=pada daftar pesan mencocokkannya secara persis dan peka huruf besar-kecil, dan beberapa pesan dapat memakai nilai yang sama. Isi kolom ini hanya jika Anda perlu mencari berdasarkan nilainya, dan simpan data lainnya dimetadata.
{
"tags": [{ "name": "campaign", "value": "order-confirmations" }],
"metadata": { "order_id": "ord_8271" },
"reference": "ord_8271"
}Referensi kolom
| Kolom | Tipe | Wajib | Batas / catatan |
|---|---|---|---|
to | string | ya | Satu penerima per pesan: nomor telepon E.164, ID pengguna dengan cakupan bisnis, yang tidak diterima oleh template kode verifikasi sekali pakai mana pun, atau ID grup WhatsApp (wag_…), yang mengirim ke setiap peserta grup tersebut |
from | string (E.164) | tidak** | Hilangkan untuk template yang dikelola Bird, yang memilih pengirimnya sendiri, dan untuk pengiriman ke grup, yang menggunakan nomor milik grup itu sendiri; wajib untuk pesan layanan dan untuk template yang dibuat oleh workspace Anda, dan harus berupa nomor milik workspace Anda |
template.slug | string | tidak** | Slug template yang dapat dikirim oleh workspace Anda; slug yang dikelola Bird diawali dengan bird_ |
template.language | string | tidak* | Tag bahasa template (en, pt-BR); hilangkan untuk mengirim bahasa default template |
template.parameters | object | tidak | Mengisi variabel template berdasarkan nama, misalnya ref atau code; maksimal 16 KB, dan bird dicadangkan |
template.components | array | tidak | Alternatif untuk parameters, satu entri per komponen: type bernilai header, body, button, atau carousel, dan carousel menerima cards sebagai pengganti parameters |
template.components[].parameters[].name | string | tidak† | Placeholder yang diisi oleh nilai ini, misalnya ref; wajib dan harus cocok dengan nama yang dideklarasikan template untuk template dengan parameter bernama, dihilangkan untuk template posisional |
text | object | tidak** | Pesan layanan teks biasa {body, preview_url?} (hingga 4.096 karakter); lihat Teks biasa |
image, video, audio, sticker, document | object | tidak** | Pesan layanan media dengan url (serta caption atau filename opsional jika didukung); lihat Pesan layanan |
location | object | tidak** | Penanda lokasi {latitude, longitude, name?, address?}; lihat Lokasi |
contact_cards | array | tidak** | Hingga 5 objek kontak vCard terstruktur; lihat Kartu kontak |
interactive | object | tidak** | Teks isi ditambah satu jenis konten yang dapat diketuk; ini pesan layanan, jadi memerlukan jendela layanan yang terbuka. Lihat Pesan interaktif |
in_reply_to_message_id | string | tidak | ID pesan WhatsApp yang disimpan workspace ini, dikutip dalam pesan yang Anda kirim; dikembalikan saat dibaca. Lihat Mengutip pesan |
tags | array | tidak | Hingga 20 label {name, value}; nama ≤ 32 karakter, nilai ≤ 64, nama harus unik |
reference | string | tidak | 1–255 karakter; dicocokkan persis oleh ?reference= pada daftar pesan |
metadata | object | tidak | JSON bebas, hingga 2 KB setelah diserialisasi |
* language bersifat opsional; jika dihilangkan, template dikirim dalam bahasa default-nya.
† name wajib ada di setiap parameter untuk template dengan parameter bernama. Hilangkan untuk template posisional. Lihat Komponen dan parameter.
** Sertakan tepat satu dari template atau satu field konten pesan layanan (text, image, video, audio, sticker, document, location, contact_cards, interactive); lihat Pesan layanan.
Model asinkron: arti 202
Pengiriman yang berhasil mengembalikan 202 Accepted dengan ID pesan dan status: accepted. 202 hanya dikembalikan setelah pengiriman diterima secara permanen; pengiriman tidak pernah diterima lalu dibuang diam-diam. Kegagalan pasti yang dapat Anda perbaiki langsung gagal dengan 422: penerima tidak valid, slug atau bahasa template yang tidak dikenal, parameter yang tidak cocok, atau pesan layanan yang dikirim saat jendela layanan pelanggan tertutup (WhatsAppServiceWindowClosed). Dompet tanpa saldo tidak termasuk di sini: pengiriman diterima, lalu pesan berakhir rejected dengan insufficient_balance saat Bird mencoba menagihnya. Pengiriman sebenarnya berlangsung secara asinkron: pesan berpindah ke sent saat kami menyerahkannya ke WhatsApp, lalu ke status akhir (delivered atau failed) saat tanda terima tiba, yang dilaporkan melalui event, webhook, dan endpoint baca. Tanda terima baca dilaporkan terpisah sebagai stempel waktu read_at dan event whatsapp.read, bukan sebagai status.
Satu catatan privasi: untuk template kategori authentication, API tidak pernah mengembalikan nilai yang telah diisi. Echo 202 dan setiap pembacaan berikutnya membawa array components kosong untuk pesan tersebut, sehingga kode verifikasi tidak pernah muncul kembali.
Mencoba lagi dengan aman
Kirim header Idempotency-Key dengan nilai unik untuk setiap pengiriman logis, maka percobaan ulang menjadi aman. Jika permintaan pertama Anda berhasil tetapi Anda tidak pernah menerima responsnya (timeout, koneksi terputus), mengirim ulang permintaan dengan kunci yang sama mengembalikan hasil aslinya, bukan mengirim dan menagih pesan duplikat. Respons ulangan membawa header Idempotency-Replay. Lihat idempotensi untuk format dan masa simpan kunci.
Menerima balasan
Pesan masuk tersimpan di resource yang sama dengan pesan keluar, dan setiap pesan masuk mengatur ulang jendela layanan. Menerima pesan WhatsApp menjelaskan cara membacanya melalui API, mengambil media yang dikirim kontak, dan webhook whatsapp.received.
Biaya dan penagihan
WhatsApp dihargai per pesan, berdasarkan kategori template dan negara penerima; lihat harga WhatsApp. Pesan ditagih dalam dua tahap pada dua waktu berbeda, dan objek cost pada pesan melaporkan keduanya:
| Field | Artinya | Kapan muncul |
|---|---|---|
transaction_amount | Biaya Bird untuk menangani pengiriman | Saat Bird memproses pengiriman yang diterima, sebelum dikirimkan |
passthrough_amount | Bagian Meta dari harga pesan, yang diteruskan oleh Bird | Saat tanda terima delivered atau read yang berlaku tiba |
amount | Jumlah komponen yang sudah diberi harga sejauh ini | Bertambah setiap kali satu komponen tercatat |
currency_code | Mata uang dompet organisasi Anda, digunakan oleh kedua komponen | Bersamaan dengan komponen pertama |
Kedua jumlah berupa string desimal, belum termasuk pajak.
Catatan: pesan layanan tidak dikenai bagian Meta hingga 30 September 2026, begitu pula templat utilitas yang dikirim di dalam jendela layanan pelanggan yang terbuka. Mulai 1 Oktober 2026, Meta mengenakan biaya untuk keduanya, kecuali di dalam jendela titik masuk gratis 72 jam, dan dengan 1.000 pesan layanan gratis per nomor telepon bisnis per bulan: Perubahan harga Oktober 2026.
Kedua komponen dihitung harganya berdasarkan masukan yang berbeda. Biaya Bird memakai kategori templat yang Anda kirim dan negara penerima. Negara itu diambil dari kode negara nomor telepon atau, pada pengiriman ke ID pengguna bercakupan bisnis, dari awalan dua huruf pada ID tersebut. Bagian Meta memakai kategori yang dilaporkan Meta sendiri pada tanda terima yang berlaku, dan kategori ini bisa berbeda dari kategori templat: Meta dapat melaporkan authentication-international jika aturan tujuan, lokasi bisnis, dan kelayakannya berlaku. Lihat Tarif authentication-international WhatsApp.
Nilai cost bergantung pada sejauh mana pesan sudah diproses:
- Pada
202,costbernilai null. Belum ada yang dihitung harganya. - Setelah pemrosesan,
transaction_amountterisi danamountsama dengannya.passthrough_amounttetap null. - Setelah tanda terima
deliveredataureadyang berlaku tiba, biaya Meta yang berhasil dicatat mengisipassthrough_amount, danamountmencerminkan komponen yang tercatat.
Komponen bernilai null berarti belum ada jumlah yang tercatat dalam proyeksi tersebut, bukan bukti bahwa pesan itu gratis. Komponen yang secara eksplisit dihargai nol bernilai "0.00000".
Kedua biaya juga gagal dengan cara berbeda. Biaya Bird gagal secara tertutup: jika biaya tidak dapat diproses setelah 202 karena saldo dompet tidak mencukupi atau rute tidak memiliki harga yang dikonfigurasi, pesan berakhir rejected dengan kode kesalahan insufficient_balance atau price_not_found, dan tidak ada biaya yang dikenakan. Pesan rejected tidak pernah sampai ke WhatsApp, dan itulah yang membedakannya dari failed. Bagian Meta gagal secara terbuka: jika saldo dompet kurang atau tarifnya tidak ada saat tanda terima tiba, biaya dilewati tanpa membatalkan status pesan yang teramati. Biaya kedua tidak pernah menahan pengiriman Anda.
Pesan yang sudah dikenai biaya oleh Bird tetap menanggung biaya keluar tersebut meskipun pengiriman kemudian gagal. Biaya Meta diproses dari callback delivered atau read yang berlaku saat Meta melaporkan harga reguler dengan kategori dan tujuan yang dapat ditentukan. Kedua jalur callback memakai identitas biaya yang sama dan mengandalkan deduplikasi layanan penagihan. Cocokkan tanda terima yang diputar ulang dengan catatan penagihan, alih-alih menganggap proyeksi pesan sebagai bukti debit permanen. Harga layanan atau titik masuk gratis dapat membuat komponen Meta bernilai nol; komponen yang belum ditentukan bukan bukti bahwa pesan itu gratis.
Gunakan buku besar penagihan untuk rekonsiliasi keuangan. Kolom cost pada pesan adalah proyeksi biaya dan dapat tertunda atau tetap tidak lengkap. Lihat Metrik WhatsApp untuk perbedaan antara pengamatan pesan dan catatan penagihan.
Peristiwa WhatsApp tidak memuat biaya. Untuk membaca salah satu komponen, baca ulang pesan dengan GET /v1/whatsapp/messages/{id}.
Langkah berikutnya
- Pesan layanan: kirim teks, media, dan konten interaktif di dalam jendela layanan pelanggan
- Template: pilih template dan isi variabelnya
- Menerima pesan WhatsApp: baca balasan dan ambil media masuk
- Webhook status pesan: terima pembaruan pengiriman dan kegagalan
- Idempotensi: coba lagi dengan aman menggunakan header
Idempotency-Key
Sumber daya terkait
Lanjutkan dengan dokumentasi, panduan, dan contoh untuk topik ini.