Trên trang này
Tạo liên hệ có thể trả về 201 mà kết quả vẫn sai: mất ID nguồn, chọn nhầm danh sách hoặc bỏ qua lần hủy đăng ký trước đó. Đây là quyết định về dữ liệu, không chỉ là chi tiết HTTP.
Bài này bắt đầu bằng lệnh ghi liên hệ hoạt động được, rồi nêu các kiểm tra cho đồng bộ nhỏ, chạy lặp lại.
Brevo API bao gồm những gì
Mọi thứ nằm dưới một host duy nhất và một đường dẫn phiên bản duy nhất. Tài liệu dành cho lập trình viên chia bề mặt API thành bốn mảng sản phẩm:
- Nhắn tin: email giao dịch, SMS và WhatsApp, gồm cả gửi hàng loạt, lên lịch và theo dõi hoạt động tin nhắn.
- Nền tảng marketing: danh bạ, danh sách, phân khúc và chiến dịch email.
- Thương mại điện tử: sản phẩm, đơn hàng và theo dõi sự kiện khách hàng.
- Conversations: widget chat và quản lý hội thoại bằng chương trình.
Bốn mảng đó dùng chung một tài khoản, một cơ sở dữ liệu danh bạ và một khóa API. Điều đó vừa tiện lợi vừa đôi khi nguy hiểm: một script viết theo hình dung về dữ liệu staging thực ra đang nói chuyện với đúng những danh bạ mà chiến dịch của bạn gửi tới.
Giao dịch so với marketing
Hai nhóm này hoạt động khác nhau đủ nhiều để việc nhầm lẫn giữa chúng trở thành lỗi thiết kế phổ biến nhất.
| Giao dịch | Marketing | |
|---|---|---|
| Endpoint chính | POST /v3/smtp/email | POST /v3/emailCampaigns |
| Cách chỉ định người nhận | Người nhận khai báo tường minh trong request | listIds hoặc segmentIds |
| Yếu tố kích hoạt | Ứng dụng của bạn, theo thời gian thực | Lên lịch trước hoặc gửi khi cần |
| Hình dạng lưu lượng điển hình | Liên tục, mỗi lần một tin nhắn | Dồn dập, một lượt gửi lớn |
| Thế của giới hạn tốc độ | Rất cao, 1.000 request mỗi giây ở bậc general | Thấp, endpoint chiến dịch nằm trong hạn mức chung |
Nếu bạn vẫn đang cân nhắc liệu Brevo có phải nền tảng phù hợp hay không, bài tổng quan nền tảng đã bàn kỹ chuyện đó.
Xác thực và quản lý khóa
Brevo dùng một khóa API thuần trong header tùy chỉnh. Header có tên là api-key, không phải Authorization, và không có tiền tố Bearer. Điểm này khiến gần như ai từng dùng một API nhắn tin khác trước đó đều vấp phải.
OAuth có thể dùng Bearer token cho thao tác hỗ trợ; khóa API tiêu chuẩn vẫn gửi qua header api-key.
curl https://api.brevo.com/v3/account \ -H "api-key: $BREVO_API_KEY"Khóa được tạo trong ứng dụng Brevo, ở phần cài đặt tài khoản, mục SMTP and API, tab API keys. Hãy đặt cho mỗi khóa một cái tên mô tả gắn với hệ thống sử dụng nó. Giá trị khóa chỉ hiển thị đúng một lần khi được tạo, nên nếu làm mất, bạn phải tạo khóa mới chứ không khôi phục lại khóa cũ.
Một vài nguyên tắc thực dụng:
- Cấp một khóa riêng cho từng môi trường triển khai và từng dịch vụ. Việc thu hồi một khóa bị lộ không bao giờ nên kéo sập ba hệ thống không liên quan.
- Khóa API tiêu chuẩn có phạm vi toàn tài khoản. Hãy coi mọi khóa như quyền truy cập đầy đủ vào danh bạ, khả năng gửi và dữ liệu CRM.
- Brevo cũng hỗ trợ OAuth 2.0 cho các ứng dụng hành động thay mặt tài khoản Brevo khác, được mô tả cùng luồng khóa trong authentication schemes.
- Máy chủ MCP dùng cho trợ lý AI cần một token riêng và có dùng header bearer. Token đó được tạo trong cùng màn hình API keys nhưng không thể dùng thay cho khóa REST.
Base URL, phiên bản và lệnh ghi đầu tiên
Base URL là https://api.brevo.com/v3/. Phiên bản nằm trong đường dẫn chứ không nằm trong header, và v3 là thế hệ hiện tại. Mọi đường dẫn trong hướng dẫn này đều tương đối so với base đó.
Lần ghi đầu hãy dùng địa chỉ thử nghiệm do bạn kiểm soát, ID danh sách hợp lệ và ID nguồn ổn định. Tạo thuộc tính FNAME trong Brevo trước. Với khóa thật, ví dụ này ghi trực tiếp:
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 }'Thay 42 bằng ID danh sách thử nghiệm của bạn. Đọc lại liên hệ để kiểm tra ID, tên, danh sách và trạng thái chặn. Mã 2xx đơn lẻ không chứng minh kết quả mong đợi.
Những endpoint bạn thực sự sẽ dùng
Danh bạ
POST /v3/contacts tạo liên hệ. Body nhận email, attributes đã khai báo, listIds và ext_id làm khóa nguồn ổn định. updateEnabled: true cập nhật liên hệ có sẵn, còn getId: true yêu cầu ID cuối. Brevo ghi rõ các trường này. Dùng cùng ext_id mỗi lần chạy và lưu ánh xạ ID nguồn với ID Brevo.
Trước khi ghi, xác định hệ thống nào sở hữu từng thuộc tính và danh sách nào nhận liên hệ có đồng ý. Khai báo listIds rõ ràng. Đừng gửi emailBlacklisted: false khi upsert thông thường. Brevo cảnh báo rằng đổi email của liên hệ bị chặn có thể xóa trạng thái chặn. Xử lý đổi địa chỉ riêng. Kiểm tra chặn và hủy đăng ký trước khi thêm vào danh sách tiếp thị. Có khoảng trống ngắn giữa đọc và ghi; nếu cần bảo đảm nghiêm ngặt, kiểm tra lần cuối trước khi gửi.
Việc đọc đi qua GET /v3/contacts, phân trang bằng limit (mặc định 50, tối đa 1000) và offset, đồng thời hỗ trợ modifiedSince và createdSince theo giờ UTC. Các luồng đồng bộ gia tăng nên dựa vào modifiedSince thay vì duyệt toàn bộ danh sách. Lưu ý rằng tham số filter chỉ hỗ trợ toán tử bằng, nên bất cứ điều kiện nào phức tạp hơn đều thuộc về một phân khúc.
Để nạp hàng loạt, POST /v3/contacts/import nhận fileUrl, fileBody hoặc jsonBody, nhắm tới listIds và chạy bất đồng bộ, trả về một processId. Brevo ghi rõ giới hạn body tối đa 10 MB và khuyến nghị giữ quanh mức 8 MB vì quá trình phân tích cú pháp làm phình payload. Hãy cung cấp notifyUrl để biết kết quả thay vì phải hỏi liên tục.
Email giao dịch
POST /v3/smtp/email là con ngựa kéo chính. Ngoài sender, to, subject và htmlContent, những trường đáng biết là:
templateIdđi kèmparams, thay nội dung nội tuyến bằng một mẫu của Brevo cùng các phép thay biến. Params của từng phiên bản bị giới hạn ở 100 KB, tổng cộng ở mức 1000 KB.messageVersions, gửi các biến thể được cá nhân hóa trong một lệnh gọi, với tối đa 99 người nhận cho mỗi phiên bản.tagscó thể giúp liên hệ sự kiện gửi với quy trình ứng dụng đã tạo ra nó.scheduledAtcùngbatchId, cho những lượt gửi tương lai mà bạn có thể muốn hủy theo nhóm.headers, viết theo Title-Case, cho các header SMTP tùy chỉnh.
Một request đơn lẻ chấp nhận tối đa 2.000 người nhận. Về khác biệt giữa endpoint này và việc gửi chiến dịch, hướng dẫn email giao dịch trình bày góc nhìn chiến lược nhắn tin.
Chiến dịch email
POST /v3/emailCampaigns yêu cầu name và sender, cộng đúng một nguồn nội dung: htmlContent (tối thiểu 10 ký tự, dưới 1 MB), htmlUrl hoặc templateId. Đối tượng nhận nằm trong recipients dưới dạng listIds hoặc segmentIds, còn scheduledAt dùng định dạng UTC YYYY-MM-DDTHH:mm:ss.SSSZ. Các route đi kèm bao gồm gửi ngay, gửi bản thử, cập nhật trạng thái và lấy báo cáo chiến dịch.
Công ty, thương vụ và object
CRM của Brevo có hai đường ghi chồng lấn nhau, và chọn đúng là chuyện quan trọng.
Các route CRM là POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id} và bộ tương đương cho thương vụ. Chúng là đồng bộ. Một lệnh PATCH trả về 204 ngay khi thay đổi được áp dụng.
API object là đường đi hàng loạt: POST /v3/objects/{object_type}/batch/upsert nhận tối đa 1000 bản ghi và 1 MB mỗi request, tối đa 500 thuộc tính cho mỗi bản ghi, và tối đa 10 bản ghi liên kết cho mỗi loại object trên mỗi bản ghi. Nó trả về 202 kèm một processId, nghĩa là đã tiếp nhận chứ chưa áp dụng.
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" } } ] }'Hướng dẫn Brevo CRM trình bày mô hình dữ liệu này từ góc nhìn người vận hành.
SDK chính thức
Brevo duy trì các client dưới tổ chức GitHub getbrevo:
| Ngôn ngữ | Kho mã |
|---|---|
| Node.js | github.com/getbrevo/brevo-node |
| Python | github.com/getbrevo/brevo-python |
| PHP | github.com/getbrevo/brevo-php |
| Java | github.com/getbrevo/brevo-java |
| C# | github.com/getbrevo/brevo-csharp |
| Go | github.com/getbrevo/brevo-go |
| Ruby | github.com/getbrevo/brevo-ruby |
Client Node cài đặt dưới tên @getbrevo/brevo:
npm install @getbrevo/brevoimport { 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>", tags: ["order-confirmation"],});
console.log("Message ID:", result.messageId);Client Python cài bằng pip install brevo-python. Nếu bạn không muốn gánh thêm một phụ thuộc SDK chỉ vì hai endpoint, bề mặt HTTP thô đủ nhỏ để gọi trực tiếp, và cách đó cũng giúp bạn tránh được những đợt thay đổi phiên bản SDK:
Cài ứng dụng Python bằng pip install brevo-python. Với vài endpoint, gọi HTTP trực tiếp cũng phù hợp:
import osimport 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 NoneCập nhật thành công có thể trả phản hồi 204 rỗng. Khi đó None nghĩa là bạn phải đọc lại liên hệ để lấy ID.
Ví dụ giả định bên gọi đã kiểm tra đồng ý và chặn trong Brevo. Nó không yêu cầu bỏ chặn. Khóa thật sẽ ghi vào tài khoản; hãy thử bằng phản hồi giả lập trước. Xung đột định danh có thể trả nhiều mã 4xx. Đọc phản hồi và đối soát ID, đừng luôn giả định 409.
Webhook
Webhook là cách bạn biết chuyện gì đã xảy ra sau khi gửi. POST /v3/webhooks tạo một webhook, với url, events, type, và tùy chọn channel (email hoặc sms), batched, headers tùy chỉnh cùng một đối tượng auth.
Có ba loại webhook với ba bộ từ vựng sự kiện riêng:
- Giao dịch:
sent,request,delivered,hardBounce,softBounce,blocked,spam,invalid,deferred,click,opened,uniqueOpened,unsubscribed. - Marketing:
spam,opened,click,hardBounce,softBounce,unsubscribed,listAddition,delivered,contactUpdated,contactDeleted. - Thư đến:
inboundEmailProcessed, cầndomain.
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" }'Với thay đổi liên hệ, đăng ký webhook tiếp thị có contactUpdated. Brevo gọi sự kiện trong payload là contact_updated. Xác thực bên nhận bằng bearer token auth hoặc header riêng theo hướng dẫn bảo mật. Kiểm tra bí mật trước khi xử lý, không ghi vào log.
Lưu khóa khử trùng lặp gồm loại sự kiện, ID liên hệ và dấu thời gian trong suốt thời gian giao lại. Chỉ dấu thời gian không bảo đảm duy nhất. Sự kiện có thể lặp hoặc đến sai thứ tự. Đọc lại liên hệ hiện tại và đối soát với nguồn tin cậy. Giới hạn cửa sổ phát lại, bỏ sự kiện cũ sau khôi phục và kiểm tra tăng dần định kỳ để bù phần thiếu. Webhook tự nó không tạo đồng bộ hai chiều. Xem hướng dẫn kết nối.
Giới hạn tốc độ và xử lý lỗi
Giới hạn tốc độ của Brevo được đặt theo từng endpoint và từng bậc gói dịch vụ, và khoảng cách giữa các endpoint là rất lớn.
| Endpoint | General (mọi gói) | Advanced (Professional và Enterprise) |
|---|---|---|
POST /v3/smtp/email | 1.000 RPS | 2.000 RPS |
POST /v3/transactionalSMS/send | 150 RPS | 200 RPS |
/v3/contacts/... | 10 RPS, 36.000 RPH | 20 RPS, 72.000 RPH |
POST /v3/events | 10 RPS, 36.000 RPH | 20 RPS, 72.000 RPH |
GET /v3/smtp/emails | 2 RPS, 7.200 RPH | 3 RPS, 10.800 RPH |
| Endpoint không có giới hạn riêng | 100 RPH | 200 RPH |
Brevo ghi rõ x-sib-ratelimit-limit, x-sib-ratelimit-remaining và x-sib-ratelimit-reset cho endpoint bị giới hạn. Đọc cả khi thành công. Với 429, đợi thời điểm đặt lại và chỉ thử lại trong số lần cùng thời gian cố định. Reset là khoảng thời gian theo đơn vị của cửa sổ, thường là giây, không phải Unix timestamp.
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)); }}Nếu cần đợi hơn 60 giây, hàm trả 429. Hãy lên lịch thử lại sau.
Hàm hỗ trợ chỉ dùng cho yêu cầu bạn đã xác nhận có thể lặp an toàn. Nếu lỗi gửi không rõ kết quả, đối soát ID thư của bạn trước khi gửi lại. Ghi trạng thái và header giới hạn, không ghi khóa hay dữ liệu liên hệ.
Đừng thử lại mọi 4xx. Tài liệu tạo liên hệ liệt kê 400 và 425; xung đột không nhất thiết là 409. Sau 5xx khi ghi, kiểm tra thay đổi đã áp dụng hay chưa.
Trạng thái nào được trả về?
-
429
Đợi trong giới hạn
Dùng thời gian reset và dừng sau vài lần thử.
-
5xx sau khi ghi
Kiểm tra kết quả
Máy chủ có thể đã ghi trước lỗi.
-
400
Sửa yêu cầu
Thường do đầu vào không hợp lệ.
-
Xung đột ID
Đối soát ID
API không hứa một mã xung đột cố định.
Thử nghiệm mà không gửi thư
Hãy thêm header X-Sib-Sandbox với giá trị drop vào một lệnh gửi giao dịch. Brevo kiểm tra request, trả về 201 kèm messageId, không chuyển phát gì và không ghi nhật ký email.
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>" }'Hãy hiểu rõ điều này chứng minh được gì và không chứng minh được gì. Chế độ sandbox chỉ kiểm tra định dạng request. Nó không nói gì về xác thực người gửi, kết xuất mẫu hay khả năng vào hộp thư. Hãy giữ một tài khoản Brevo riêng để kiểm thử tích hợp cho bất cứ thứ gì chạm vào danh bạ hoặc dữ liệu CRM, vì chế độ sandbox chỉ bao phủ việc gửi chứ không bao phủ phần còn lại của API.
Kiểm tra trước khi đồng bộ liên hệ
- Chọn ID nguồn ổn định cho
ext_idvà lưu ID Brevo trả về. - Khai báo thuộc tính trước khi ghi, sau đó đọc lại liên hệ thử nghiệm.
- Dùng danh sách rõ ràng và bằng chứng đồng ý tin cậy; bỏ qua liên hệ bị chặn hay hủy đăng ký.
- Đếm riêng bản ghi được nhận, áp dụng, bỏ qua và lỗi. 202 ban đầu chỉ nghĩa là đã nhận.
- Xác thực, khử trùng lặp webhook tiếp thị và đối soát trạng thái.
- Theo dõi header giới hạn và dừng sau số lần thử cố định.
Tajo đồng bộ dữ liệu thương mại với Brevo. Nếu tự xây tầng này, xem hướng dẫn connector.
Câu hỏi Thường gặp
Base URL của Brevo API là gì?
Mọi lệnh gọi REST của Brevo đều đi tới https://api.brevo.com/v3/. Phiên bản nằm ngay trong đường dẫn và v3 là thế hệ hiện tại, nên một endpoint như gửi email giao dịch có đường dẫn đầy đủ là https://api.brevo.com/v3/smtp/email.
Bạn xác thực với Brevo API như thế nào?
Bạn gửi khóa của mình trong một HTTP header tên là api-key. Brevo không dùng header Authorization hay Bearer cho khóa API tiêu chuẩn. Khóa được tạo trong phần cài đặt tài khoản, mục SMTP and API, tab API keys, và giá trị chỉ hiển thị đúng một lần.
Giới hạn tốc độ của Brevo API là bao nhiêu?
Giới hạn được đặt theo từng endpoint và theo từng bậc giới hạn tốc độ. Ở bậc general, bậc mà mọi gói đều có, endpoint gửi email giao dịch cho phép 1.000 request mỗi giây, các endpoint danh bạ cho phép 10 request mỗi giây, và các endpoint không có giới hạn riêng bị giới hạn ở 100 request mỗi giờ. Gói Professional và Enterprise có thể dùng bậc advanced, và gói Enterprise có thể dùng bậc extended. Vượt giới hạn sẽ nhận về mã 429.
Brevo có SDK chính thức không?
Có. Brevo phát hành client cho Node.js, Python, PHP, Java, C#, Go và Ruby dưới tổ chức GitHub getbrevo. Gói Node là @getbrevo/brevo trên npm và gói Python là brevo-python trên PyPI.
Làm sao để thử nghiệm Brevo API mà không gửi email thật?
Hãy thêm header X-Sib-Sandbox với giá trị drop vào lệnh gửi email giao dịch. Brevo sẽ kiểm tra request, trả về 201 kèm messageId, không gửi gì cả và không ghi nhật ký email. Chế độ này chỉ kiểm tra định dạng request, không kiểm tra khả năng gửi tới hộp thư.
Brevo hỗ trợ những sự kiện webhook nào?
Webhook giao dịch bao gồm gửi, trả về và hủy đăng ký. Webhook tiếp thị có contactUpdated và contactDeleted. Brevo ghi nhận inboundEmailProcessed cho sự kiện email đến.
Upsert liên hệ bảo vệ việc hủy đăng ký trước đó ra sao?
Dùng ID nguồn ổn định và thuộc tính đã khai báo. Đừng đặt emailBlacklisted: false trong lần cập nhật thông thường. Kiểm tra liên hệ và nguồn đồng ý trước khi thêm vào danh sách tiếp thị.
Webhook có đủ để đồng bộ hai chiều không?
Không. Xác thực bên nhận, loại bỏ lần giao trùng và đối soát sự kiện thiếu hoặc sai thứ tự với nguồn tin cậy. Webhook báo thay đổi, không chứng minh hai hệ thống cùng trạng thái.