Email API

Apa itu Email API?

Email API adalah jalur kirim email aplikasi lewat HTTPS. Satu request JSON membawa satu batch, dan kapasitasnya dirancang untuk volume besar: 18.000 unit per menit, plus pencatatan open dan click yang berjalan otomatis di dalam email HTML Anda.

Terakhir diperbarui · 3 Oktober 2026

Endpoint
POST /email-api/messages
Protokol
HTTPS · JSON
Kuota produk
18.000 unit / menit
Tracking
Open + click
01

Jawaban singkatnya

Email API adalah REST API untuk email aplikasi — notifikasi, invoice, verifikasi, reset password. Aplikasi Anda mengirim satu request JSON per batch ke /email-api/messages, dan RuangMail yang mengurus validasi, penghitungan kredit, antrean kuota, pengiriman, sampai pencatatan open dan click.

Yang diurus RuangMail

  • Autentikasi API key dan pemisahan data per customer
  • Validasi penerima, sender, domain, dan ukuran akhir MIME
  • Debit kredit atomik, plus refund kalau pengiriman gagal
  • Reservasi kuota per menit dan antrean durable saat kuota penuh
  • Karantina bounce, suppression, dan pixel plus redirect tracking

Yang tetap di tangan Anda

  • Isi email, daftar penerima, dan metadata bisnis Anda
  • Membuat API key dengan scope email:send dan email:read
  • Mendaftarkan domain pengirim dan memasang DNS-nya
  • Mengirim Idempotency-Key unik di setiap request

Ini bukan relay SMTP. Kalau aplikasi Anda sudah punya SMTP client dan tidak mau menulis kode HTTP, pakai jalur SMTP — hasilnya sama, titik masuknya berbeda. Buka panduan SMTP by Azure

02

Kirim pertama Anda

Satu request, satu batch. Ganti alamat pengirim dengan sender yang sudah aktif di domain terverifikasi, lalu kirim.

Request
curl -X POST https://api.ruangmail.com/api/v1/email-api/messages \
  -H "Authorization: Bearer rmk_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-202610-000482" \
  -d '{
    "from": "[email protected]",
    "from_name": "Brand Anda",
    "reply_to": "[email protected]",
    "to": [{"email": "[email protected]", "name": "Customer"}],
    "subject": "Invoice INV-202610-000482",
    "html": "<p>Terima kasih, pembayaran Anda sudah kami terima.</p>",
    "metadata": {"invoice_id": "INV-202610-000482"}
  }'
Response 200
{
  "data": {
    "batch_id": "3f9a1c72-1d84-4b60-9a11-7c0e5b2f8d31",
    "status": "sent",
    "message_ids": ["8b2d4e01-5c77-4a19-b3e2-90af6d1c4471"],
    "final_size_bytes": 1420,
    "credit_per_recipient": 1,
    "total_credit_cost": 1
  },
  "meta": { "request_id": "req_9c1f4a" }
}

Untuk volume besar, isi array to dengan sampai 50 penerima unik dalam satu request. Batch 50 penerima berukuran normal memakai 50 kredit dan tetap satu panggilan.

to[]
{
  "from": "[email protected]",
  "to": [
    { "email": "[email protected]" },
    { "email": "[email protected]" },
    { "email": "[email protected]" }
  ],
  "subject": "Pengumuman layanan",
  "html": "<p>Ada pemeliharaan terjadwal malam ini.</p>"
}
03

Skala pengiriman

Kuota Email API dihitung dalam unit, bukan sekadar jumlah email. Satu unit adalah satu potongan berukuran maksimal 2.008.192 byte untuk setiap penerima unik — jadi penerima berukuran normal memakai satu unit, dan lampiran besar bisa memakai lebih.

unit per menit
18.000
penerima per 24 jam berjalan
50.000
penerima per request
50
BatasNilaiCakupan
Laju pengiriman18.000 unit / menitAnggaran produk, dibagi bersama
Volume harian50.000 penerima / 24 jam berjalanAnggaran produk, dibagi bersama
Penerima per request1 – 50Per request
Ukuran satu unit2.008.192 bytePer penerima unik

Reservasi kuota memakai bucket per menit di dalam transaksi database dengan advisory lock, sehingga beberapa instance backend dan worker tidak bisa melewati batas secara bersamaan. Dashboard Email API menampilkan pemakaian menit dan 24 jam berjalan terhadap batas ini.

Kuota penuh bukan kegagalan. Request dijawab 202 dan masuk antrean durable; worker mengirim ulang otomatis dan kredit tidak ditahan selama masih mengantre. Untuk kebutuhan kapasitas di atas anggaran ini, hubungi support.

04

Tracking open & click

RuangMail menyisipkan URL bertanda tangan ke dalam email HTML Anda, jadi Anda tidak perlu menambahkan apa pun. Pixel 1x1 mencatat open, dan setiap tautan diganti dengan redirect yang mencatat click lalu meneruskan penerima ke tujuan aslinya.

MethodPathFungsi
GET/email-api/engagement/open?id=…&sig=…Mengembalikan pixel 1x1 dan mencatat open.
GET/email-api/engagement/click?id=…&url=…&sig=…Memvalidasi tujuan, mencatat click, lalu redirect 302.

Membaca hasilnya

Riwayat pesan mengembalikan open_count, click_count, opened_at, dan clicked_at. Counter menghitung event yang sudah dideduplikasi, dan waktu menunjukkan kejadian pertama.

GET /email-api/messages/{message_id}
{
  "id": "8b2d4e01-5c77-4a19-b3e2-90af6d1c4471",
  "status": "delivered",
  "open_count": 3,
  "click_count": 1,
  "opened_at": "2026-10-03T02:14:07Z",
  "clicked_at": "2026-10-03T02:14:31Z"
}

Hanya untuk email HTML satu penerima

Batch dengan lebih dari satu penerima tidak diberi URL tracking, supaya open dan click tidak salah dikaitkan ke orang lain. Kirim per penerima kalau Anda butuh angkanya.

Tanda tangan yang tidak bisa dipalsukan

Setiap URL membawa HMAC-SHA256 64 karakter atas jenis event dan ID pesan. Permintaan dengan tanda tangan tidak valid tetap mendapat pixel atau redirect, tapi tidak dicatat sebagai event.

Tidak mengubah status, tidak memakai kredit

Open dan click tidak menurunkan atau menaikkan status pengiriman, dan tidak memotong kredit. Counter dideduplikasi per menit supaya refresh tidak menggelembungkan angka.

05

Ukuran, kredit, dan batas

Kredit dihitung dari penerima unik pada To + Cc + Bcc dan ukuran akhir email setelah attachment di-encode, termasuk header MIME. Penerima yang sama muncul dua kali tetap dihitung sekali.

Kredit per penerima

Ukuran akhir MIMEKredit
≤ 300.000 byte (≤ 0,3 MB)1
> 300.000 – 600.000 byte2
> 600.000 – 2.008.192 byte3

Pesan di atas 2.008.192 byte ditolak sebelum kredit dipotong. Karena batas ukuran sudah 2 MB, tier yang lebih tinggi tidak akan pernah terpakai di jalur ini.

Batas teknis per request

ParameterNilai
Penerima unik1 – 50
Panjang subject250 karakter
Panjang body200.000 karakter (html + text)
Attachmentmaksimal 10
Metadata16 KiB
Ukuran akhir MIME2.008.192 byte
Idempotency-Key1 – 160 karakter
06

Status dan antrean

Kode HTTP memberi tahu apa yang terjadi pada request, dan status pesan memberi tahu apa yang terjadi pada emailnya.

HTTPStatusArti
200sentDiterima dan dikirim ke jalur pengiriman.
202queuedMasuk antrean kuota. Worker mengirim ulang otomatis.
402WALLET_INSUFFICIENT_BALANCEKredit tidak cukup.
409idempotency_conflictIdempotency-Key sama dipakai dengan payload berbeda.
502failedPengiriman ditolak atau gagal. Kredit dikembalikan bila refund berhasil.

Alamat yang sedang di-suppress dilewati sebelum pengiriman dipanggil, jadi tidak memakan kredit. Hard bounce atau keluhan spam menambahkan alamat ke daftar suppression, dan setiap event bounce yang unik mengenakan penalti 30 kredit satu kali. Kegagalan sementara tidak langsung menjadi suppression permanen.

07

Catatan yang sering bikin bingung

Hal-hal yang paling sering ditanyakan setelah pengiriman pertama berhasil.

Idempotency-Key wajib, bukan opsional
Tanpa key ini request ditolak. Key yang sama dengan payload yang sama mengembalikan hasil lama dengan reused, sedangkan payload berbeda dengan key yang sama menjawab 409. Jangan pakai ulang key untuk isi yang berubah.
Tracking hilang begitu penerima lebih dari satu
Pixel dan redirect hanya dipasang pada email HTML dengan satu penerima. Kalau angka open penting, kirim satu request per penerima — penerima tetap bisa diisi sampai 50 untuk email yang tidak butuh tracking.
Kuota penuh bukan error
Request dijawab 202 dan masuk antrean durable. Kredit tidak ditahan selama mengantre, dan worker mengirim ulang sendiri. Jangan retry dari sisi Anda hanya karena melihat 202.
Lampiran dihitung setelah base64
Batas 2.008.192 byte berlaku untuk ukuran akhir MIME, termasuk encoding base64, header, dan boundary. Lampiran 1,6 MB mentah bisa melewati batas setelah di-encode, dan pesan ditolak sebelum kredit dipotong.
Bounce tidak cuma gagal
Alamat yang bounce masuk suppression dan pengiriman berikutnya ke alamat itu dilewati sebelum kredit didebit. Setiap event bounce unik juga memotong 30 kredit sekali, dan deduplikasi mencegah penalti ganda.
Reply-To kosong otomatis jadi From
Kalau Anda tidak mengisi reply_to, balasan pelanggan masuk ke alamat pengirim. Isi eksplisit kalau balasan harus diarahkan ke tempat lain.

Lanjut baca

Halaman yang biasanya dibuka setelah yang ini.

Siap mengirim dalam jumlah besar?

Buat API key dengan scope email:send, daftarkan domain pengirim, lalu jalankan request pertama. Kuota menit dan harian langsung terlihat di dashboard.