Sign inGet Started

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);

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, misalnya bird_order_confirmation. Slug harus cocok dengan template di katalog Anda (huruf kecil, angka, dan garis bawah).
  • language: tag bahasa template, misalnya en atau pt-BR. Hilangkan untuk mengirim bahasa default template. Jika Anda menyebut bahasa yang tidak dimiliki template, permintaan mengembalikan 422 yang 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 pengganti parameters. 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, atau header_location untuk header media atau lokasi, serta header_url_1, header_url_2, dan seterusnya untuk header kartu carousel
  • button_url untuk sufiks bernomor pada tombol URL, serta button_url_1, button_url_2, dan seterusnya untuk tombol kartu carousel. Sufiks bernama menggunakan namanya sendiri.
  • code untuk 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.

Contoh kode
{
  "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:

Contoh kode
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:

Contoh kode
{
  "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):

Contoh kode
{
  "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 sertakan from. Jika Anda mengisinya, permintaan mengembalikan 422 WhatsAppSenderNotAllowed.
  • 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 mengembalikan 422 WhatsAppSenderRequired, dan nomor yang tidak dapat digunakan workspace untuk mengirim mengembalikan 422 WhatsAppSenderNotFound. Template yang Anda buat juga harus berada di WhatsApp Business Account yang sama dengan nomornya. Jika tidak, pengiriman mengembalikan 422 WhatsAppSenderWABAMismatch.

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": true untuk menampilkan pratinjau tautan bagi URL pertama di body.
  • image, video, audio, sticker, document: masing-masing menerima URL https publik yang diambil WhatsApp saat pengiriman (url), sehingga URL bertanda tangan harus tetap berlaku hingga pengiriman selesai. URL http langsung 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, dengan media_rejected pada last_error pesan dan alasan dari WhatsApp sendiri di description. image, video, dan document juga menerima caption opsional; document juga menerima filename opsional; audio menerima flag voice opsional agar ditampilkan sebagai pesan suara.
  • location: { "latitude": ..., "longitude": ... } (keduanya wajib, dalam derajat desimal) ditambah name dan address opsional.
  • contact_cards: array berisi hingga lima kontak yang dibagikan dalam satu pesan. name setiap kartu memerlukan formatted_name ditambah setidaknya satu bagian lain (first_name, last_name, middle_name, prefix, atau suffix); phone_numbers, emails, urls, dan addresses masing-masing menerima hingga sepuluh entri, sedangkan org dan birthday (sebagai YYYY-MM-DD) bersifat opsional. Jika phone_number dalam 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.
Contoh kode
{
  "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.

Contoh kode
{
  "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=campaign atau ?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 di metadata.
Contoh kode
{
  "tags": [{ "name": "campaign", "value": "order-confirmations" }],
  "metadata": { "order_id": "ord_8271" },
  "reference": "ord_8271"
}

Referensi kolom

KolomTipeWajibBatas / catatan
tostringyaSatu 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
fromstring (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.slugstringtidak**Slug template yang dapat dikirim oleh workspace Anda; slug yang dikelola Bird diawali dengan bird_
template.languagestringtidak*Tag bahasa template (en, pt-BR); hilangkan untuk mengirim bahasa default template
template.parametersobjecttidakMengisi variabel template berdasarkan nama, misalnya ref atau code; maksimal 16 KB, dan bird dicadangkan
template.componentsarraytidakAlternatif untuk parameters, satu entri per komponen: type bernilai header, body, button, atau carousel, dan carousel menerima cards sebagai pengganti parameters
template.components[].parameters[].namestringtidak†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
textobjecttidak**Pesan layanan teks biasa {body, preview_url?} (hingga 4.096 karakter); lihat Teks biasa
image, video, audio, sticker, documentobjecttidak**Pesan layanan media dengan url (serta caption atau filename opsional jika didukung); lihat Pesan layanan
locationobjecttidak**Penanda lokasi {latitude, longitude, name?, address?}; lihat Lokasi
contact_cardsarraytidak**Hingga 5 objek kontak vCard terstruktur; lihat Kartu kontak
interactiveobjecttidak**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_idstringtidakID pesan WhatsApp yang disimpan workspace ini, dikutip dalam pesan yang Anda kirim; dikembalikan saat dibaca. Lihat Mengutip pesan
tagsarraytidakHingga 20 label {name, value}; nama ≤ 32 karakter, nilai ≤ 64, nama harus unik
referencestringtidak1–255 karakter; dicocokkan persis oleh ?reference= pada daftar pesan
metadataobjecttidakJSON 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:

FieldArtinyaKapan muncul
transaction_amountBiaya Bird untuk menangani pengirimanSaat Bird memproses pengiriman yang diterima, sebelum dikirimkan
passthrough_amountBagian Meta dari harga pesan, yang diteruskan oleh BirdSaat tanda terima delivered atau read yang berlaku tiba
amountJumlah komponen yang sudah diberi harga sejauh iniBertambah setiap kali satu komponen tercatat
currency_codeMata uang dompet organisasi Anda, digunakan oleh kedua komponenBersamaan 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, cost bernilai null. Belum ada yang dihitung harganya.
  • Setelah pemrosesan, transaction_amount terisi dan amount sama dengannya. passthrough_amount tetap null.
  • Setelah tanda terima delivered atau read yang berlaku tiba, biaya Meta yang berhasil dicatat mengisi passthrough_amount, dan amount mencerminkan 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