Sign inGet Started

Pengiriman terjadwal

Atur scheduled_at untuk menahan pesan hingga waktu tertentu. Saat waktu itu tiba, pesan memasuki siklus pengiriman normal dan menghasilkan event yang sama seperti pengiriman langsung. Aplikasi Anda tidak perlu menjalankan scheduler sendiri.

Menjadwalkan pengiriman

Tambahkan timestamp scheduled_at ke pengiriman POST /v1/email/messages biasa. Tidak ada yang berubah pada payload selain itu.

const msg = await bird.email.send({
  from: "news@yourdomain.com",
  to: ["delivered@messagebird.dev"],
  subject: "Your weekly digest",
  html: '<p>Here is what happened this week...</p><p><a href="{{ bird.unsubscribe_url }}">Unsubscribe</a></p>',
  category: "marketing",
  scheduled_at: "2027-01-15T09:00:00Z",
});
console.log(msg.id, msg.status); // "em_…", "accepted"

Panggilan ini langsung mengembalikan 202 Accepted dengan message ID berawalan em_ dan status: accepted. Objek pesan yang dikembalikan sama dengan yang dihasilkan pengiriman langsung, ditambah scheduled_at dalam UTC, sehingga Anda dapat mengonfirmasi waktu kirim tanpa pembacaan tambahan. Penerimaan bersifat sinkron; pengiriman ditunda. Hilangkan scheduled_at dari permintaan dan pesan langsung terkirim, serta responsnya tidak memuat key scheduled_at.

Hasil pembacaan diperbarui secara asinkron. Pesan yang baru Anda jadwalkan pada awalnya dapat mengembalikan 404 melalui Ambil pesan dan belum muncul di daftar pesan atau dasbor. Konten berukuran besar atau lampiran dapat memperpanjang waktu tunggu ini selama kami menyimpannya. Simpan ID dan scheduled_at dari respons 202, lalu ulangi pembacaan menggunakan ID tersebut dengan jeda antarpercobaan. Anda juga dapat membatalkan menggunakan ID ini sebelum pesan muncul.

Jika pesan muncul saat masih menunggu untuk dikirim, hasil pembacaan menampilkan status: scheduled dan scheduled_at pesan tersebut:

Contoh kode
{
  "id": "em_01ky7q24hafjgvzfg02v3m177p",
  "status": "scheduled",
  "scheduled_at": "2027-01-15T09:00:00Z",
  "category": "marketing"
}

Saat waktunya tiba, kami melepas pesan dan statusnya bergerak melalui state biasa (accepted, lalu processed, lalu delivered, dan seterusnya). scheduled_at tetap terisi setelahnya, sehingga Anda selalu dapat melihat kapan pesan dijadwalkan.

Pengiriman pesan dapat dimulai sebelum hasil pembacaan diperbarui, sehingga status yang lebih lanjut mungkin muncul lebih dahulu. Tidak ada durasi tunggu tetap yang menjamin pembacaan akan menampilkan pesan setelahnya.

Penjadwalan mengonsumsi satu unit dari kuota email terjadwal organisasi Anda untuk periode penagihan tersebut. Melebihi kuota ini ditolak dengan 422 (E10003).

Jadwalkan konten inline atau templat

Gunakan scheduled_at dengan konten inline atau templat tersimpan, yang disusun seperti pengiriman templat langsung. Kami menetapkan versi yang dipublikasikan, bahasa yang dipilih, serta nilai parameter saat menerima permintaan dan mengirim versi tersebut pada waktu yang dijadwalkan. Mempublikasikan versi yang lebih baru tidak mengubah pilihan tersebut. Jika templat dihapus sebelum waktu yang dijadwalkan, pesan ditolak tanpa dikirim.

Pesan kategori marketing mendapatkan tautan berhenti berlangganan berupa footer kecil di akhir isi pesannya. Untuk menempatkan tautan sendiri, letakkan {{ bird.unsubscribe_url }} di setiap isi pesan yang Anda berikan, atau di isi pesan templat untuk pengiriman templat.

Item batch menerima scheduled_at dengan ketentuan yang sama, sehingga satu batch dapat mencampur pesan terjadwal dan langsung. Setiap item terjadwal mengonsumsi unit kuota masing-masing, dan seluruh batch ditolak jika waktu salah satu item di luar rentang. Setiap item terjadwal membawa scheduled_at sendiri dalam respons batch, dan item yang langsung terkirim tidak memiliki key scheduled_at; referensi batch menunjukkan keduanya dalam satu respons.

Payload pengiriman langsung tetap bisa terlalu besar untuk dijadwalkan. Jika body, daftar penerima, atau metadata melebihi batas penjadwalan, API mengembalikan 422. Kurangi field tersebut atau kirim pesan secara langsung.

Memilih waktu kirim

scheduled_at adalah timestamp absolut RFC 3339. Dua aturan mengaturnya:

  • Harus antara 30 detik dan 30 hari ke depan. Kurang dari 30 detik atau lebih dari 30 hari ditolak dengan 422. Batas bawah ini mencegah jadwal bersaing dengan pengiriman langsung. Tiga puluh hari adalah horizon terjauh kami menahan pesan.
  • Berikan momen yang tepat. Sertakan Z UTC (2027-01-15T09:00:00Z) atau offset eksplisit (2026-07-30T09:00:00-04:00, momen yang sama dengan 13:00:00Z). Kami membandingkan momen tersebut terhadap waktu saat ini dan tidak pernah menginterpretasi waktu lokal tanpa offset atau menerapkan zona waktu penerima. Untuk mengirim pukul 9 pagi di waktu lokal masing-masing penerima, hitung momen tersebut sendiri dan jadwalkan satu pengiriman per zona waktu.

Ekspresi relatif seperti "in 2 hours" tidak diterima. Kirim timestamp yang sudah di-resolve.

Melihat daftar pesan terjadwal

Filter daftar pesan berdasarkan status untuk melihat pesan yang sudah muncul dan masih menunggu untuk dikirim. Jadwal yang baru diterima dapat belum muncul saat kontennya sedang diunggah atau hasil pembacaan sedang diperbarui:

for await (const message of bird.email.list({ status: "scheduled" })) {
  console.log(message.id, message.scheduled_at);
}

status=canceled menampilkan pesan yang Anda batalkan sebelum terkirim. Setelah pesan terjadwal dilepas, pesan masuk ke pipeline dan muncul dengan status pengiriman, sama seperti pengiriman lainnya. Log email di dashboard menyediakan filter Scheduled dan Canceled yang sama.

Membatalkan pengiriman terjadwal

Batalkan pesan kapan saja sebelum mulai terkirim dengan POST /v1/email/messages/{message_id}/cancel:

await bird.email.cancel("em_abc123");

Pembatalan yang berhasil mengembalikan 204 No Content. Status pesan menjadi canceled, pesan tidak pernah terkirim, dan webhook email.canceled aktif. Empat hal yang perlu diketahui:

  • Hanya pesan yang masih terjadwal yang dapat dibatalkan. Pesan yang sudah mulai terkirim, sudah terkirim, atau sudah dibatalkan mengembalikan 409:

    Contoh kode
    {
      "error": {
        "type": "conflict_error",
        "code": "E10005",
        "name": "EmailNotCancelable",
        "message": "This message cannot be canceled.",
        "remediation": "Only a scheduled message that has not started sending can be canceled. Once sending begins there is no way to pull it back."
      }
    }

    Saat waktu kirim tiba, pembatalan juga bisa kalah cepat dari pengiriman itu sendiri dan mengembalikan 409 dengan alasan yang sama.

  • Anda dapat membatalkan saat konten masih diunggah. Pengiriman terjadwal dengan lampiran atau isi pesan yang besar mungkin masih menyimpan konten setelah respons 202. Pembatalan yang berhasil tetap berlaku meskipun unggahan selesai kemudian.

  • Pembatalan tidak mengembalikan kuota email terjadwal. Unit yang Anda konsumsi saat menjadwalkan tetap terpakai, dan inilah yang mencegah pola jadwalkan-lalu-batalkan untuk mengelabui kuota. Kuota pengiriman reguler Anda tidak terpengaruh, karena kuota itu baru dikenakan saat pesan benar-benar terkirim.

  • Pembatalan aman untuk dicoba lagi dengan Idempotency-Key, seperti operasi tulis lainnya.

Untuk memindahkan pengiriman terjadwal ke waktu lain, batalkan lalu kirimkan pengiriman baru dengan scheduled_at yang baru. Anda mendapatkan ID em_ baru.

Apa yang terjadi saat waktu kirim

Penjadwalan hanya mengubah kapan pesan dilepas. Konstruksi dan aturannya tetap sama. Lampiran, kategori, tag, dan metadata semuanya berperilaku persis seperti pada pengiriman langsung, dan ditampilkan pada event webhook dengan cara yang sama. Lima pemeriksaan terbagi di dua momen:

  • Validasi payload dan domain dilakukan di awal. Pengiriman terjadwal yang salah format gagal pada panggilan API dengan 422, sehingga Anda mengetahuinya sekarang, bukan saat pukul 9 pagi.
  • Domain pengirim diperiksa ulang saat waktu kirim. Jika domain from Anda sudah tidak terverifikasi saat waktu terjadwal tiba, pesan tidak dikirim. Penerimanya dikembalikan sebagai rejected dengan alasan, alih-alih menerima email dari domain yang tidak terverifikasi. Pastikan domain tetap terverifikasi selama seluruh jendela waktu.
  • Kuota pengiriman dikenakan saat waktu kirim. Kuota pengiriman reguler dikonsumsi saat pesan dilepas. Penjadwalan tidak mengubah kuota. Jika kuota habis saat waktu kirim, penerima ditolak.
  • Supresi dievaluasi saat waktu kirim, berdasarkan daftar supresi Anda pada saat itu, sehingga seseorang yang berhenti berlangganan antara penjadwalan dan pengiriman tetap dihormati.
  • Templat tersimpan harus masih ada saat waktu kirim. Jika Anda menghapus templat setelah menjadwalkan, pesan tidak dikirim. Penerimanya dikembalikan sebagai rejected dengan generation_failure.

Error

StatusKodeKapan
422E10003Kuota email terjadwal organisasi Anda untuk periode penagihan sudah habis
422scheduled_at kurang dari 30 detik atau lebih dari 30 hari ke depan
422Payload terlalu besar untuk ditahan; kurangi body, penerima, atau metadata, atau kirim sekarang
409E10005Pesan tidak dapat dibatalkan lagi: sudah mulai terkirim, sudah terkirim, atau sudah dibatalkan
404Pembacaan pesan belum mencerminkan penerimaannya, atau tidak ada pesan dengan ID tersebut di workspace ini

Webhook

Dua event khusus untuk penjadwalan, di atas event pengiriman biasa:

  • email.scheduled melaporkan pesan yang sedang menunggu waktu scheduled_at di masa mendatang. Untuk pengiriman dengan templat, versi yang dipilih dimuat ulang dan kontennya disiapkan saat waktu pengiriman tiba. Peristiwa ini dapat tiba sebelum pekerjaan tersebut selesai.
  • email.canceled aktif saat pesan terjadwal dibatalkan sebelum terkirim.

Saat pesan dilepas, rantai email.accepted normal berjalan tanpa perubahan.

Peristiwa penjadwalan dipublikasikan secara asinkron. Pesan dapat meninggalkan status terjadwal sebelum email.scheduled dipublikasikan. Diterimanya webhook tidak berarti endpoint pembacaan sudah menampilkan status tersebut.

Langkah selanjutnya

Lanjutkan dengan dokumentasi, panduan, dan contoh untuk topik ini.