Sign inGet Started

Mengirim email

POST /v1/email/messages mengirim satu email. Sediakan pengirim, penerima, dan konten dalam payload JSON. API mengembalikan 202 Accepted dengan message ID, lalu mengirim email secara asinkron. Lihat referensi API untuk skema lengkapnya.

Pengiriman minimal

Payload valid terkecil adalah from, minimal satu penerima to, sebuah subject, dan body (html, text, atau keduanya). Alamat from harus berada di domain yang sudah Anda verifikasi di workspace ini, atau di domain onboarding.
const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  subject: "Hello from Bird",
  html: "<p>My first Bird email.</p>",
});
console.log(msg.id, msg.status); // "em_…", "accepted"
Gunakan host regional Anda (https://us1.platform.bird.com atau https://eu1.platform.bird.com) dengan kunci bk_{region}_... yang sesuai.
Contoh pengiriman menggunakan delivered@messagebird.dev, sebuah alamat sandbox yang selalu menerima email. API menolak domain placeholder dengan 422: example.com, example.net, example.org, example.edu, test.com, dan apa pun di bawah TLD cadangan .test, .example, .invalid, atau .localhost. Pengiriman ke domain ini hanya akan bounce, yang merugikan reputasi pengirim Anda.

Mengirim sebelum Anda memverifikasi domain

Selama onboarding, Anda dapat mengirim dari domain onboarding bersama kami, onboarding@messagebird.dev. Pengiriman tersebut melewati pemeriksaan domain tetapi hanya menjangkau anggota terverifikasi di workspace Anda sendiri dan alamat sandbox, dengan batas penerima harian. Quickstart memuat aturan dan batas pastinya.

Menyusun payload

Penerima

to, cc, dan bcc masing-masing menerima hingga 50 alamat, dan to membutuhkan minimal satu. Setiap entri berupa string email biasa, string mailbox RFC 5322 (Jane <jane@acme.com>), atau objek dengan display name opsional.
Penerima yang ada di daftar supresi workspace tidak membuat permintaan gagal. Permintaan tetap mengembalikan 202, dan setiap penerima yang disupresi muncul di endpoint baca sebagai status: rejected dengan alasan recipient_suppressed, termasuk saat semua penerima pada pengiriman tersebut disupresi.

Konten

subject wajib untuk pengiriman inline, maksimal 998 karakter. Sediakan html, text, atau keduanya, masing-masing maksimal 524.288 karakter. Kirim keduanya jika memungkinkan: klien yang tidak dapat merender HTML akan menggunakan bagian teks.
Untuk mempersonalisasi konten inline, taruh token {{ variable }} di subject atau body dan kirim nilainya di parameters, maksimal 16 KB setelah diserialisasi. Satu set nilai berlaku untuk semua penerima pengiriman, dan token tanpa key yang cocok dirender kosong. Untuk konten yang Anda gunakan berulang, kirim template sebagai gantinya.
Sertakan parameters, bahkan sebagai objek kosong ({}), agar subject dan body diproses sebagai Liquid. Hilangkan untuk mengirim token seperti {{ animal }} apa adanya. Setiap nama parameter adalah satu kata, seperti first_name; nama bertitik dan nama cadangan bird ditolak. Sintaks Liquid yang tidak valid serta tag atau filter yang tidak didukung mengembalikan 422.
Nilai yang disisipkan ke HTML di-escape agar tidak mengubah markup di sekitarnya. Untuk URL link atau gambar yang lengkap, gunakan {{ link }} tanpa url_encode. Untuk nilai di dalam query URL, encode nilai tersebut secara eksplisit, misalnya https://example.com/search?q={{ query | url_encode }}.

Reply-to dan header kustom

reply_to menerima 1 hingga 25 alamat, dalam format yang sama seperti penerima. Setiap balasan penerima dikirim ke semua alamat tersebut, jadi biasanya satu atau dua saja.
headers adalah objek string-ke-string untuk header Anda sendiri, misalnya {"X-Campaign": "spring-2026"}, maksimal 25 header dengan nilai hingga 998 karakter. Tiga jenis header dikembalikan sebagai 422:
  • Header alamat dan platform. Atur alamat pesan melalui field khusus (from, to, cc, bcc, reply_to, subject). Nama-nama tersebut, dan header yang kami buat untuk Anda (Content-Type, Content-Transfer-Encoding, DKIM-Signature, Received, Return-Path), tidak dapat diatur di sini.
  • List-Unsubscribe dan List-Unsubscribe-Post pada pengiriman marketing. Kami mengatur header berhenti berlangganan sekali klik yang sesuai standar pada pengiriman tersebut. Pada pengiriman transactional, kami membiarkan header Anda persis seperti yang Anda atur.
  • Nilai apa pun yang mengandung carriage return atau line feed.

Pelacakan

track_opens dan track_clicks keduanya default ke true. Atur salah satu ke false untuk melewatkan penyisipan open-pixel atau penulisan ulang link pada pengiriman ini. Pelacakan dan metrik membahas perubahan yang dilakukan masing-masing pada pesan.

Kategori dan IP pool

category mengklasifikasikan konten dan mengatur kebijakan supresi: marketing memblokir pengiriman pada setiap alasan supresi dan opt-out apa pun, dan transactional tetap mengirim meskipun ada supresi keluhan atau opt-out khusus marketing (opt-out yang berlaku untuk semua pesan tetap memblokirnya). Nilai default-nya adalah kategori template pada pengiriman template dan marketing untuk yang lain, jadi atur transactional secara eksplisit untuk tanda terima, reset kata sandi, dan email operasional lainnya. Kategori membahas pilihannya. Email yang dikirim melalui SMTP mengambil kategorinya dari konfigurasi SMTP pada key tersebut.
ip_pool_id memilih pool pengiriman: pool ID (ipp_...), atau ipp_shared untuk merutekan melalui pool bersama secara eksplisit. Hilangkan untuk menggunakan pool default organisasi Anda. Pool yang tidak dikenal, atau pool tanpa IP khusus yang tersedia untuk mengirim, ditolak dengan 422.

Referensi field

FieldTipeWajibBatas dan catatan
fromaddressyaHarus di domain terverifikasi, atau domain onboarding
toaddress[]ya1 hingga 50
cc, bccaddress[]tidakMasing-masing hingga 50
subjectstringpengiriman inlineMaksimal 998 karakter; hilangkan pada pengiriman template
html, textstringminimal satuMasing-masing maksimal 524.288 karakter; hilangkan pada pengiriman template
reply_toaddress[]tidak1 hingga 25; balasan masuk ke setiap alamat yang tercantum
headersobject (string → string)tidakMaksimal 25; nama cadangan ditolak (lihat header kustom)
parametersobjecttidakNilai untuk {{ tokens }} di konten inline; maksimal 16 KB setelah diserialisasi; dibagikan ke semua penerima
tags{name, value}[]tidakMaksimal 20; nama ≤ 32 karakter, nilai ≤ 64 karakter; hanya [A-Za-z0-9_-]; nama unik per pengiriman
metadataobjecttidakJSON arbitrer, maksimal 2 KB setelah diserialisasi
track_opensbooleantidakDefault true
track_clicksbooleantidakDefault true
categorystringtidakmarketing atau transactional; default ke kategori template pada pengiriman template, selain itu marketing
ip_pool_idstringtidakipp_... atau ipp_shared; hilangkan untuk pool default organisasi Anda
templateobjecttidakKirim template yang dipublikasikan berdasarkan id atau slug, dengan parameters untuk variabelnya dan language opsional
attachmentsobject[]tidakMaksimal 20; lihat lampiran
scheduled_atRFC 3339 timestamptidakJadwalkan konten inline atau template; lihat pengiriman terjadwal

Mengirim dengan template

Alih-alih konten inline, kirim template yang sudah dipublikasikan: atur template ke objek yang menamainya berdasarkan id (emt_...) atau berdasarkan slug, tepat salah satu dari keduanya, dengan nilai variabelnya di template.parameters. Hilangkan subject, html, dan text, karena template sudah memilikinya.
const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  category: "transactional",
  template: {
    slug: "welcome-email",
    parameters: { first_name: "Jane" },
  },
});
console.log(msg.id, msg.status);
Konten template adalah Liquid, jadi selain substitusi {{ variable }} biasa, template dapat menggunakan filter, kondisional {% if %}, dan loop {% for %}. Personalisasi dengan variabel mencantumkan beberapa konstruksi yang ditolak saat publikasi. template.parameters adalah tempat Anda menaruh nilai untuk parameter template itu sendiri, diindeks berdasarkan nama. Hilangkan satu dan pengiriman ditolak dengan 422 yang menyebutkan namanya. Semua aspek pengiriman lainnya berperilaku sama seperti inline, termasuk penerima, tags, metadata, pelacakan, dan lampiran. Yang khusus untuk pengiriman template:
  • Inline atau templated, tidak keduanya. Mengirim template bersamaan dengan subject, html, atau text ditolak dengan 422. API juga menolak nilai variabel di field parameters tingkat atas; pada pengiriman template, nilai tersebut ditempatkan di template.parameters.
  • bird adalah satu-satunya nama cadangan. Path placeholder yang dimulai dengan bird. merujuk data kami sendiri, seperti link berhenti berlangganan atau catatan kontak penerima, sehingga key template.parameters tidak boleh bernama bird. Semua key lain bebas Anda tentukan, dan masing-masing berupa satu kata: {"order_number": "A-1043"} mengisi {{ order_number }}.
  • Template dapat dikirim sekarang atau nanti. Tambahkan scheduled_at untuk menjadwalkan pengiriman. Kami mengunci versi yang dipublikasikan, bahasa yang dipilih, dan nilai parameter saat permintaan diterima. Jika Anda menghapus template sebelum waktu pengiriman, pesan ditolak dengan generation_failure.
  • Pengiriman menggunakan versi template yang dipublikasikan. Draf tidak pernah dikirim. Template yang tidak dikenal ditolak dengan 404, dan template tanpa versi yang dipublikasikan ditolak dengan 422.
  • language memilih salah satu bahasa template. Hilangkan untuk mengirim bahasa default template. Minta bahasa yang tidak dimiliki template, dan pengaturan on_missing_language pada template itu sendiri yang menentukan apakah kecocokan terdekat yang dikirim atau pengiriman ditolak. Template yang mengatur language_source_required menolak pengiriman yang tidak menyebutkan bahasa sama sekali.
  • Kategori template adalah default, dan milik Anda menimpanya. Hilangkan category dan pengiriman mewarisi kategori template, sehingga template transaksional tidak perlu mengulangnya di setiap panggilan.
Template email membahas pembuatan, publikasi, dan konstruksi yang dapat dimuat template.

Tag vs metadata

Keduanya melampirkan data Anda sendiri ke pengiriman, dan perbedaannya terletak pada cara Anda mengkuerinya nanti:
  • tags adalah pasangan {name, value} terstruktur: maksimal 20 per pengiriman, nama maksimal 32 karakter, nilai maksimal 64, hanya huruf ASCII, angka, underscore, dan tanda hubung, dan nama unik dalam satu pengiriman. Tag adalah dimensi filter, sehingga Anda dapat memfilter daftar pesan berdasarkan tag dan memecah analitik serta rollup dasbor berdasarkan tag. Gunakan untuk label berkardinalitas rendah seperti campaign, experiment_variant, atau source.
  • metadata adalah objek JSON arbitrer, maksimal 2 KB setelah diserialisasi. Kami menyimpannya, mengembalikannya pada pembacaan API, dan mengirimkannya di setiap event webhook, sehingga cocok untuk konteks yang ingin Anda terima kembali: ID internal, foreign key, payload terstruktur.
Setiap event webhook menyertakan keduanya bersama ID korelasi (email_id, recipient_id), sehingga Anda dapat mencocokkan dengan catatan Anda sendiri tanpa pencarian tambahan. Nama tag dan key metadata tingkat atas yang dimulai dengan __bird ditolak. Anda tidak perlu menyandikan perangkat, geografi, penyedia mailbox, tipe bounce, atau domain penerima ke salah satu field, karena kami sudah menangkap masing-masing sebagai dimensi analitik.
Contoh kode
{
  "tags": [{ "name": "campaign", "value": "onboarding" }],
  "metadata": { "user_id": "usr_12345", "order_id": "ord_98765" }
}

Lampiran

attachments menerima hingga 20 file per pesan, sebagai byte yang di-encode base64 secara inline. Kami menolak pengiriman yang estimasi ukuran pesan yang dihasilkan melampaui 20 MB, diukur setelah encoding base64, jadi jaga konten lampiran mentah pada atau di bawah 15 MB untuk ruang cadangan. Lampiran memuat kontrak field, gambar inline, tipe file yang diblokir, dan cara mengunduh kembali lampiran.

Arti respons 202

Pengiriman yang berhasil mengembalikan 202 Accepted dengan message ID berawalan em_ dan status: accepted:
Contoh kode
{
  "id": "em_01ky7ma8y2es1s2akzk53tmjn0",
  "status": "accepted",
  "category": "marketing",
  "from": { "email": "hello@yourdomain.com" },
  "to": [{ "email": "delivered@messagebird.dev" }],
  "subject": "Hello from Bird",
  "accepted_count": 1,
  "processed_count": 0,
  "delivered_count": 0,
  "deferred_count": 0,
  "bounced_count": 0,
  "complained_count": 0,
  "rejected_count": 0,
  "open_count": 0,
  "click_count": 0,
  "track_opens": true,
  "track_clicks": true,
  "created_at": "2026-07-23T13:58:20.866Z"
}
202 berarti kami telah menerima pengiriman secara permanen. Kegagalan yang dapat Anda perbaiki dikembalikan langsung pada request sebagai 422: domain pengirim yang belum diverifikasi, atau field yang tidak valid. Hasil per penerima (delivered, bounced, deferred, complained) tiba setelahnya melalui webhook dan endpoint pembacaan pesan.
Dua hal yang mengikuti dari itu:
  • Pembacaan mengembalikan status tanpa body. GET /v1/email/messages/{message_id} mengembalikan status pesan dan penerima, tidak pernah body html atau text. Jika penyimpanan konten diaktifkan untuk workspace, body yang disimpan tetap tersedia hingga 30 hari dari GET /v1/email/messages/{message_id}/content.
  • Pembacaan bisa sedikit tertinggal dari pengiriman. 404 pada endpoint pembacaan tepat setelah 202 berarti pesan belum terlihat, jadi coba lagi sesaat kemudian.

Mencoba ulang dengan aman

Kirim header Idempotency-Key dengan nilai unik per pengiriman logis. Jika request berhasil tetapi Anda tidak menerima responsnya, ulangi dengan kunci yang sama. API mengembalikan hasil asli alih-alih mengirim email kedua dan menyertakan header Idempotency-Replay. Idempotensi memuat format kunci dan masa retensinya.

Pengiriman batch

Untuk mengurangi request API, POST /v1/email/batches menerima hingga 100 pesan independen dan memvalidasinya sebagai satu unit. Memanggil endpoint pengiriman tunggal dalam loop juga didukung. Setiap item batch menggunakan payload di halaman ini, termasuk scheduled_at, sehingga satu batch dapat mencampur pesan langsung dan terjadwal.

Penagihan

Pengiriman email dihitung per penerima terhadap kuota bulanan paket Anda, jadi satu pesan ke tiga penerima mengonsumsi tiga pengiriman. Penagihan dan penggunaan membahas model pengukuran dan pembacaan penggunaan secara langsung.

Langkah selanjutnya

Sumber daya terkait

Lanjutkan dengan dokumentasi, panduan, dan contoh untuk topik ini. Sumber daya tersedia dalam bahasa Inggris.

Coba praktiknya dan dapatkan ringkasan implementasi