Brevo API: Panduan Praktis untuk Developer

Panduan API Brevo untuk autentikasi, upsert kontak, webhook, batas laju, dan percobaan ulang yang aman.

Brevo API

Apa jawaban singkatnya?

Gunakan https://api.brevo.com/v3/ dan header api-key untuk autentikasi kunci API standar. Untuk sinkronisasi kontak, pilih ID sumber yang stabil, atribut terdaftar, dan daftar yang jelas sambil mempertahankan status berhenti berlangganan. Periksa hasil serta header batas laju, batasi percobaan ulang setelah 429, dan perlakukan webhook sebagai sinyal terautentikasi yang perlu deduplikasi dan rekonsiliasi.

Pelajari selengkapnya
Di halaman ini

Pembuatan kontak bisa menghasilkan 201 tetapi tetap salah: ID sumber hilang, daftar yang dipilih keliru, atau penolakan sebelumnya diabaikan. Itu keputusan data, bukan sekadar detail HTTP.

Panduan ini mulai dari penulisan kontak yang berjalan, lalu pemeriksaan untuk sinkronisasi kecil yang dapat diulang.

Apa saja yang dicakup Brevo API

Semuanya berada di bawah satu host dan satu path versi. Dokumentasi developer mengelompokkan permukaan API ini ke dalam empat area produk:

  • Messaging: email transaksional, SMS, dan WhatsApp, termasuk pengiriman batch, penjadwalan, dan aktivitas pesan.
  • Marketing platform: kontak, daftar, segmen, dan kampanye email.
  • eCommerce: produk, pesanan, dan pelacakan event pelanggan.
  • Conversations: widget chat dan pengelolaan percakapan secara programatik.

Area-area tersebut berbagi satu akun, satu basis data kontak, dan satu API key. Itu praktis sekaligus kadang berbahaya: skrip yang ditulis dengan asumsi data staging sebenarnya berbicara dengan kontak yang sama seperti yang dikirimi kampanye Anda.

Transaksional versus marketing

Kedua keluarga ini berperilaku cukup berbeda sehingga tertukar di antara keduanya adalah kesalahan desain yang paling umum.

TransaksionalMarketing
Endpoint utamaPOST /v3/smtp/emailPOST /v3/emailCampaigns
Penentuan penerimaPenerima eksplisit di dalam permintaanlistIds atau segmentIds
PemicuAplikasi Anda, secara real-timeTerjadwal atau dikirim sesuai permintaan
Bentuk volume tipikalTerus-menerus, satu pesan sekali kirimMelonjak, satu pengiriman besar
Posisi rate limitSangat tinggi, 1.000 permintaan per detik pada tingkat generalRendah, endpoint kampanye masuk batas umum

Jika Anda masih mempertimbangkan apakah Brevo memang platform yang tepat, ikhtisar platform membahas hal tersebut.

Autentikasi dan pengelolaan kunci

Brevo memakai API key biasa di dalam header khusus. Nama headernya adalah api-key, bukan Authorization, dan tidak ada awalan Bearer. Hal ini menjebak hampir semua orang yang lebih dulu memakai API pesan lain.

OAuth dapat memakai token Bearer untuk operasi yang mendukungnya; kunci API standar tetap dikirim melalui header api-key.

Terminal window
curl https://api.brevo.com/v3/account \
-H "api-key: $BREVO_API_KEY"

Kunci dibuat di aplikasi Brevo pada pengaturan akun, di bagian SMTP dan API, pada tab API keys. Beri setiap kunci nama deskriptif yang terkait dengan sistem yang memakainya. Nilai kunci ditampilkan tepat satu kali saat dibuat, jadi jika Anda kehilangannya, Anda membuat kunci baru dan bukan memulihkan yang lama.

Beberapa aturan praktis:

  • Terbitkan kunci terpisah per target deployment dan per layanan. Mencabut kunci yang bocor tidak boleh sampai mematikan tiga sistem yang tidak berhubungan.
  • API key standar berlaku untuk seluruh akun. Perlakukan kunci apa pun sebagai akses penuh ke kontak, pengiriman, dan data CRM.
  • Brevo juga mendukung OAuth 2.0 untuk aplikasi yang bertindak atas nama akun Brevo lain, dijelaskan bersama alur kunci di authentication schemes.
  • Server MCP yang dipakai asisten AI memakai token terpisah dan memang menggunakan header bearer. Token itu dibuat di layar API keys yang sama, tetapi tidak dapat dipertukarkan dengan kunci REST.

Base URL, versi, dan penulisan pertama Anda

Base URL-nya adalah https://api.brevo.com/v3/. Versi berada di path, bukan di header, dan v3 adalah generasi yang berlaku saat ini. Setiap path dalam panduan ini bersifat relatif terhadap base tersebut.

Untuk penulisan pertama, gunakan alamat uji yang Anda kuasai, ID daftar yang valid, dan ID sumber yang stabil. Buat atribut FNAME di Brevo terlebih dahulu. Dengan kunci asli, contoh ini menulis langsung:

Terminal window
curl -X POST https://api.brevo.com/v3/contacts \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"ext_id": "test-source-contact-1",
"attributes": { "FNAME": "Dev" },
"listIds": [42],
"updateEnabled": true,
"getId": true
}'

Ganti 42 dengan ID daftar uji Anda. Baca ulang kontak dan periksa ID, nama, daftar, serta blokirnya. Respons 2xx saja tidak membuktikan hasil yang diharapkan.

Endpoint yang benar-benar akan Anda pakai

Kontak

POST /v3/contacts membuat kontak. Isi permintaan menerima email, attributes yang terdaftar, listIds, dan ext_id sebagai kunci sumber yang stabil. updateEnabled: true memperbarui kontak yang sudah ada dan getId: true meminta ID akhir. Brevo mendokumentasikan field ini. Pakai ext_id yang sama di setiap eksekusi dan simpan pemetaan ID sumber ke ID Brevo.

Sebelum menulis, tentukan sistem yang memiliki setiap atribut dan daftar yang boleh menerima kontak berizin. Cantumkan listIds secara eksplisit. Jangan kirim emailBlacklisted: false dalam upsert biasa. Brevo memperingatkan bahwa mengubah alamat email kontak yang diblokir dapat menghapus blokir. Tangani perubahan alamat secara terpisah. Periksa blokir dan berhenti berlangganan sebelum menambah daftar pemasaran. Ada celah waktu antara baca dan tulis; untuk jaminan ketat, periksa lagi tepat sebelum pengiriman.

Pembacaan dilakukan melalui GET /v3/contacts, yang melakukan paginasi dengan limit (default 50, maksimum 1000) dan offset, serta mendukung modifiedSince dan createdSince dalam UTC. Sinkronisasi inkremental sebaiknya bertumpu pada modifiedSince, bukan menelusuri seluruh daftar. Perhatikan bahwa parameter filter hanya mendukung operator kesamaan, jadi apa pun yang lebih ekspresif sebaiknya diletakkan dalam segmen.

Untuk pemuatan massal, POST /v3/contacts/import menerima fileUrl, fileBody, atau jsonBody, menargetkan listIds, dan berjalan secara asinkron sambil mengembalikan processId. Brevo mendokumentasikan batas body maksimum 10 MB dan menyarankan tetap di sekitar 8 MB karena proses parsing menggelembungkan payload. Sertakan notifyUrl supaya Anda tahu hasilnya tanpa perlu polling.

Email transaksional

POST /v3/smtp/email adalah tulang punggungnya. Selain sender, to, subject, dan htmlContent, field yang perlu Anda ketahui adalah:

  • templateId bersama params, yang menggantikan konten inline dengan template Brevo beserta substitusi variabelnya. Params per versi dibatasi 100 KB, dan params kumulatif 1000 KB.
  • messageVersions, yang mengirim varian personal dalam satu panggilan, dengan maksimum 99 penerima per versi.
  • tags dapat membantu mengaitkan peristiwa pengiriman dengan alur aplikasi yang menghasilkannya.
  • scheduledAt bersama batchId, untuk pengiriman terjadwal yang mungkin ingin Anda batalkan sebagai satu kelompok.
  • headers, dalam Title-Case, untuk header SMTP kustom.

Satu permintaan menerima maksimum 2.000 penerima. Untuk memahami perbedaan endpoint ini dengan pengiriman kampanye, panduan email transaksional menyajikan sudut pandang strategi pesan.

Kampanye email

POST /v3/emailCampaigns memerlukan name dan sender, ditambah tepat satu sumber konten: htmlContent (minimum 10 karakter, di bawah 1 MB), htmlUrl, atau templateId. Audiens masuk ke recipients sebagai listIds atau segmentIds, dan scheduledAt memakai format UTC YYYY-MM-DDTHH:mm:ss.SSSZ. Rute pendamping mencakup pengiriman langsung, pengiriman uji, pembaruan status, dan penarikan laporan kampanye.

Perusahaan, deal, dan objek

CRM Brevo punya dua jalur penulisan yang saling tumpang tindih, dan memilih dengan benar itu penting.

Rute CRM adalah POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id}, serta set yang setara untuk deal. Rute ini sinkron. Sebuah PATCH mengembalikan 204 begitu perubahan diterapkan.

API objek adalah jalur massalnya: POST /v3/objects/{object_type}/batch/upsert menerima hingga 1.000 record dan 1 MB per permintaan, hingga 500 atribut per record, dan hingga 10 record asosiasi per tipe objek per record. Rute ini mengembalikan 202 beserta processId, yang berarti diterima, bukan diterapkan.

Terminal window
curl -X POST https://api.brevo.com/v3/objects/company/batch/upsert \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"identifiers": { "id": 12345 },
"attributes": { "domain": "acme.example", "industry": "retail" }
}
]
}'

Panduan Brevo CRM membahas model objek ini dari sisi operator.

SDK resmi

Brevo memelihara klien di bawah organisasi GitHub getbrevo:

BahasaRepositori
Node.jsgithub.com/getbrevo/brevo-node
Pythongithub.com/getbrevo/brevo-python
PHPgithub.com/getbrevo/brevo-php
Javagithub.com/getbrevo/brevo-java
C#github.com/getbrevo/brevo-csharp
Gogithub.com/getbrevo/brevo-go
Rubygithub.com/getbrevo/brevo-ruby

Klien Node dipasang sebagai @getbrevo/brevo:

Terminal window
npm install @getbrevo/brevo
import { BrevoClient } from "@getbrevo/brevo";
// Reconcile uncertain send outcomes before retrying.
const brevo = new BrevoClient({ apiKey: process.env.BREVO_API_KEY, maxRetries: 0 });
const result = await brevo.transactionalEmails.sendTransacEmail({
subject: "Order confirmed",
htmlContent: "<html><body><p>Thanks for your order.</p></body></html>",
sender: { name: "Acme", email: "[email protected]" },
to: [{ email: "[email protected]", name: "Customer" }],
tags: ["order-confirmation"],
});
console.log("Message ID:", result.messageId);

Klien Python dipasang dengan pip install brevo-python. Jika Anda lebih suka tidak membawa dependensi SDK hanya untuk dua endpoint, permukaan HTTP mentahnya cukup kecil untuk dipanggil langsung, sekaligus melindungi Anda dari pergantian versi SDK:

Klien Python dapat dipasang dengan pip install brevo-python. Untuk beberapa endpoint, HTTP langsung cukup:

import os
import requests
BASE = "https://api.brevo.com/v3"
HEADERS = {"api-key": os.environ["BREVO_API_KEY"]}
def upsert_consented_contact(source_id, email, first_name, list_id, consent):
if not consent:
raise ValueError("No marketing consent in the source")
if not source_id or not isinstance(list_id, int):
raise ValueError("Stable source ID and numeric list ID required")
# Configure FNAME in Brevo before using this explicit field mapping.
response = requests.post(
f"{BASE}/contacts",
headers=HEADERS,
json={
"email": email,
"ext_id": source_id,
"attributes": {"FNAME": first_name},
"listIds": [list_id],
"updateEnabled": True,
"getId": True,
},
timeout=30,
)
response.raise_for_status()
return response.json().get("id") if response.content else None

Pembaruan sukses dapat memberi respons 204 tanpa isi. None berarti Anda perlu membaca ulang kontak untuk mendapatkan ID.

Contoh menganggap pemanggil telah memeriksa persetujuan dan blokir di Brevo. Contoh tidak meminta pembukaan blokir. Kunci asli akan menulis ke akun; uji dahulu dengan respons tiruan. Konflik pengenal bisa menghasilkan berbagai 4xx. Baca respons dan rekonsiliasi ID, jangan selalu mengharapkan 409.

Webhook

Webhook adalah cara Anda mengetahui apa yang terjadi setelah pengiriman. POST /v3/webhooks membuat satu webhook, dengan url, events, type, dan secara opsional channel (email atau sms), batched, headers kustom, serta objek auth.

Ada tiga tipe webhook dengan kosakata event yang berbeda:

  • Transaksional: sent, request, delivered, hardBounce, softBounce, blocked, spam, invalid, deferred, click, opened, uniqueOpened, unsubscribed.
  • Marketing: spam, opened, click, hardBounce, softBounce, unsubscribed, listAddition, delivered, contactUpdated, contactDeleted.
  • Inbound: inboundEmailProcessed, yang memerlukan domain.
Terminal window
curl -X POST https://api.brevo.com/v3/webhooks \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.example/hooks/brevo",
"type": "transactional",
"events": ["delivered", "hardBounce", "spam", "unsubscribed"],
"description": "Deliverability signals"
}'

Untuk perubahan kontak, daftarkan webhook pemasaran dengan contactUpdated. Brevo menamai peristiwa dalam payload contact_updated. Autentikasi penerima dengan token bearer auth atau header khusus sesuai panduan keamanan. Verifikasi rahasia sebelum memproses dan jangan mencatatnya.

Simpan kunci deduplikasi dari jenis peristiwa, ID kontak, dan cap waktu selama jendela pengiriman ulang. Cap waktu saja tidak unik. Peristiwa bisa dikirim lagi atau tiba tidak berurutan. Baca ulang kontak saat ini dan rekonsiliasi dengan sumber tepercaya. Tetapkan jendela pemutaran ulang, tolak peristiwa lama setelah pemulihan, serta lakukan pemeriksaan inkremental berkala untuk menutup celah. Webhook memberi sinyal perubahan tetapi bukan sinkronisasi dua arah dengan sendirinya. Lihat panduan konektor.

Rate limit dan penanganan error

Rate limit Brevo ditetapkan per endpoint dan per tingkat paket, dan rentang antar endpoint sangat lebar.

EndpointGeneral (setiap paket)Advanced (Professional dan Enterprise)
POST /v3/smtp/email1.000 RPS2.000 RPS
POST /v3/transactionalSMS/send150 RPS200 RPS
/v3/contacts/...10 RPS, 36.000 RPH20 RPS, 72.000 RPH
POST /v3/events10 RPS, 36.000 RPH20 RPS, 72.000 RPH
GET /v3/smtp/emails2 RPS, 7.200 RPH3 RPS, 10.800 RPH
Endpoint tanpa batas sendiri100 RPH200 RPH

Brevo mendokumentasikan x-sib-ratelimit-limit, x-sib-ratelimit-remaining, dan x-sib-ratelimit-reset pada endpoint yang dibatasi. Baca juga pada respons sukses. Setelah 429, tunggu reset dan ulangi hanya dalam batas jumlah percobaan serta waktu. Reset adalah durasi dalam satuan jendela, biasanya detik, bukan stempel waktu Unix.

async function callBrevo(path, init) {
for (let attempt = 0; attempt < 3; attempt++) {
const response = await fetch(`https://api.brevo.com/v3${path}`, {
...init,
headers: { "api-key": process.env.BREVO_API_KEY, ...init.headers },
});
if (response.status !== 429 || attempt === 2) return response;
const raw = Number(response.headers.get("x-sib-ratelimit-reset"));
const seconds = Number.isFinite(raw) && raw > 0 ? raw : 2 ** attempt;
const delayMs = (seconds + 2 ** attempt) * 1000;
if (delayMs > 60_000) return response;
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}

Jika waktu tunggu yang diperlukan lebih dari 60 detik, fungsi mengembalikan 429. Jadwalkan percobaan berikutnya nanti.

Helper ini hanya untuk permintaan yang sudah Anda pastikan aman diulang. Setelah kegagalan pengiriman yang tidak jelas, rekonsiliasi ID pesan Anda sebelum mengirim lagi. Catat status dan header laju, bukan kunci API atau data kontak.

Jangan ulangi semua 4xx. Referensi pembuatan kontak mencantumkan 400 dan 425; konflik tidak selalu 409. Setelah 5xx pada penulisan, periksa apakah perubahan sudah diterapkan.

Status apa yang diterima?

  1. 429

    Tunggu dalam batas

    Gunakan durasi reset dan berhenti setelah sedikit percobaan.

  2. 5xx setelah penulisan

    Periksa hasil

    Server mungkin sudah menerapkan perubahan.

  3. 400

    Perbaiki permintaan

    Biasanya masukan tidak valid.

  4. Konflik pengenal

    Baca dan cocokkan ID

    API tidak menjamin satu kode konflik.

Menguji tanpa mengirim email

Tambahkan header X-Sib-Sandbox dengan nilai drop pada pengiriman transaksional. Brevo memvalidasi permintaan, mengembalikan 201 beserta messageId, tidak mengirimkan apa pun, dan tidak menulis log email.

Terminal window
curl -X POST https://api.brevo.com/v3/smtp/email \
-H "api-key: $BREVO_API_KEY" \
-H "X-Sib-Sandbox: drop" \
-H "Content-Type: application/json" \
-d '{ "sender": { "email": "[email protected]" }, "to": [{ "email": "[email protected]" }], "subject": "Sandbox", "htmlContent": "<p>hi</p>" }'

Pahami apa yang dibuktikan dan tidak dibuktikan langkah ini. Mode sandbox hanya memvalidasi format permintaan. Mode ini tidak mengatakan apa pun tentang autentikasi pengirim, rendering template, atau deliverability. Simpan akun Brevo terpisah untuk pengujian integrasi apa pun yang menyentuh kontak atau data CRM, karena mode sandbox mencakup pengiriman dan bukan bagian API lainnya.

Periksa sebelum sinkronisasi kontak

  • Pilih ID sumber stabil untuk ext_id dan simpan ID Brevo yang dihasilkan.
  • Pastikan atribut sudah terdaftar, lalu baca ulang kontak uji.
  • Gunakan daftar yang jelas dan bukti persetujuan yang tepercaya; lewati kontak diblokir atau berhenti berlangganan.
  • Hitung terpisah penulisan yang diterima, diterapkan, dilewati, dan gagal. Status 202 mula-mula hanya berarti diterima.
  • Autentikasi dan deduplikasi webhook pemasaran, lalu rekonsiliasi keadaan saat ini.
  • Amati header batas laju dan hentikan setelah percobaan terbatas.

Tajo menyinkronkan data perdagangan dengan Brevo. Jika membangun lapisan sendiri, lihat panduan konektor Brevo.

Pertanyaan yang sering diajukan

Apa base URL dari Brevo API?

Semua panggilan REST Brevo menuju https://api.brevo.com/v3/. Versi menjadi bagian dari path, dan v3 adalah generasi yang berlaku saat ini, sehingga endpoint seperti pengiriman transaksional memiliki path lengkap https://api.brevo.com/v3/smtp/email.

Bagaimana cara melakukan autentikasi dengan Brevo API?

Kirim kunci Anda dalam header HTTP bernama api-key. Brevo tidak menggunakan header Authorization atau Bearer untuk API key standar. Kunci dibuat di pengaturan akun, bagian SMTP dan API, tab API keys, dan nilainya hanya ditampilkan satu kali.

Berapa rate limit Brevo API?

Batasnya ditetapkan per endpoint dan per tingkat rate limit. Pada tingkat general, yang didapat setiap paket, endpoint pengiriman transaksional mengizinkan 1.000 permintaan per detik, endpoint kontak mengizinkan 10 per detik, dan endpoint yang tidak memiliki batas sendiri dibatasi 100 permintaan per jam. Paket Professional dan Enterprise dapat menggunakan tingkat advanced, dan Enterprise tingkat extended. Melampaui batas menghasilkan 429.

Apakah Brevo punya SDK resmi?

Ya. Brevo menerbitkan klien untuk Node.js, Python, PHP, Java, C#, Go, dan Ruby di bawah organisasi GitHub getbrevo. Paket Node adalah @getbrevo/brevo di npm dan paket Python adalah brevo-python di PyPI.

Bagaimana cara menguji Brevo API tanpa mengirim email sungguhan?

Tambahkan header X-Sib-Sandbox dengan nilai drop pada pengiriman transaksional. Brevo memvalidasi permintaan, mengembalikan 201 beserta messageId, tidak mengirim apa pun, dan tidak menulis log email. Mode ini hanya memeriksa format permintaan, bukan deliverability.

Event webhook apa saja yang didukung Brevo?

Webhook transaksional mencakup pengiriman, bounce, dan berhenti berlangganan. Webhook pemasaran mencakup contactUpdated dan contactDeleted. Untuk peristiwa masuk, Brevo mendokumentasikan inboundEmailProcessed.

Bagaimana upsert kontak menjaga status berhenti berlangganan?

Gunakan ID sumber yang stabil dan atribut yang terdaftar. Jangan setel emailBlacklisted menjadi false dalam pembaruan biasa. Periksa kontak dan sumber persetujuan sebelum menambahkan ke daftar pemasaran.

Apakah webhook cukup untuk sinkronisasi dua arah?

Tidak. Autentikasi penerima, hilangkan pengiriman duplikat, dan rekonsiliasi peristiwa yang terlewat atau tidak berurutan dengan sumber tepercaya. Webhook memberi sinyal perubahan, bukan bukti bahwa status kedua sistem sudah sama.

Ajukan akses awal

Masukkan nama depan dan alamat email kerja Anda. Kami akan mengirim tautan untuk mengonfirmasi permintaan akses Tajo.

Dapatkan Brevo