Brevo API: คู่มือเชิงปฏิบัติสำหรับนักพัฒนา
คู่มือ Brevo API สำหรับนักพัฒนา ครอบคลุมการยืนยันตัวตน base URL ผู้ติดต่อ อีเมลธุรกรรม แคมเปญ ออบเจกต์ CRM Webhook ขีดจำกัดอัตราการเรียก และข้อจำกัดที่พบในการใช้งานจริง
Brevo เปิด REST API ชุดเดียวที่ครอบคลุมทั้งการส่งข้อความธุรกรรม แคมเปญการตลาด ข้อมูลผู้ติดต่อ และเรกคอร์ด CRM การทำให้คำขอแรกคืนค่า 201 ใช้เวลาราวสองนาที แต่การสร้างการเชื่อมต่อระดับโปรดักชันที่ไม่ทำข้อมูลหายอย่างเงียบ ๆ ใช้เวลานานกว่านั้นมาก เพราะข้อจำกัดที่สำคัญที่สุดหลายข้อไม่ได้อยู่ในเอกสาร หรือขัดแย้งกับสิ่งที่ API รายงานเกี่ยวกับตัวมันเอง
คู่มือนี้ครอบคลุมทั้งสองด้าน ทั้ง endpoint, SDK และการยืนยันตัวตนที่คุณต้องใช้ตั้งแต่วันแรก และข้อจำกัดของแพลตฟอร์มที่คุณต้องออกแบบเผื่อไว้ก่อนขึ้นระบบจริง
Brevo API ครอบคลุมอะไรบ้าง
ทุกอย่างอยู่ภายใต้โฮสต์เดียวและ path เวอร์ชันเดียว เอกสารสำหรับนักพัฒนา จัดกลุ่มพื้นผิวนี้ออกเป็นสี่กลุ่มผลิตภัณฑ์
- การส่งข้อความ: อีเมลธุรกรรม SMS และ WhatsApp รวมถึงการส่งแบบกลุ่ม การตั้งเวลา และกิจกรรมของข้อความ
- แพลตฟอร์มการตลาด: ผู้ติดต่อ รายชื่อ เซกเมนต์ และแคมเปญอีเมล
- eCommerce: สินค้า ออเดอร์ และการติดตามอีเวนต์ของลูกค้า
- Conversations: วิดเจ็ตแชทและการจัดการบทสนทนาแบบเขียนโปรแกรม
กลุ่มเหล่านี้ใช้บัญชีเดียวกัน ฐานข้อมูลผู้ติดต่อเดียวกัน และ API key เดียวกัน ซึ่งสะดวกและบางครั้งก็อันตราย เพราะสคริปต์ที่เขียนขึ้นโดยคิดว่ากำลังคุยกับข้อมูลทดสอบ กำลังคุยกับผู้ติดต่อชุดเดียวกับที่แคมเปญของคุณส่งถึงจริง
ธุรกรรมกับการตลาด
สองตระกูลนี้ทำงานต่างกันมากพอที่การสับสนระหว่างกันจะเป็นข้อผิดพลาดด้านการออกแบบที่พบบ่อยที่สุด
| ธุรกรรม | การตลาด | |
|---|---|---|
| Endpoint หลัก | POST /v3/smtp/email | POST /v3/emailCampaigns |
| การระบุผู้รับ | ระบุผู้รับตรง ๆ ในคำขอ | listIds หรือ segmentIds |
| ทริกเกอร์ | แอปพลิเคชันของคุณ แบบเรียลไทม์ | ตั้งเวลาไว้หรือสั่งส่งเอง |
| รูปแบบปริมาณทั่วไป | ต่อเนื่อง ทีละข้อความ | เป็นช่วงพุ่ง ส่งครั้งใหญ่ครั้งเดียว |
| ท่าทีของขีดจำกัดอัตรา | สูงมาก 1,000 คำขอต่อวินาทีบนแพ็กเกจมาตรฐาน | ต่ำ endpoint ของแคมเปญอยู่ใต้เพดานทั่วไป |
หากคุณยังตัดสินใจไม่ได้ว่า Brevo เหมาะกับคุณหรือไม่ ภาพรวมแพลตฟอร์ม ครอบคลุมประเด็นนั้นไว้แล้ว
การยืนยันตัวตนและการจัดการคีย์
Brevo ใช้ API key แบบธรรมดาใน header ที่กำหนดเอง header นั้นชื่อ api-key ไม่ใช่ Authorization และไม่มีคำนำหน้า Bearer จุดนี้ทำให้เกือบทุกคนที่เคยใช้ API ส่งข้อความเจ้าอื่นมาก่อนสะดุด
curl https://api.brevo.com/v3/account \ -H "api-key: $BREVO_API_KEY"คีย์สร้างได้ในแอป Brevo ที่หน้าการตั้งค่าบัญชี ในส่วน SMTP and API แท็บ API keys ตั้งชื่อคีย์แต่ละตัวให้สื่อถึงระบบที่ใช้งานมัน ค่าของคีย์จะแสดงเพียงครั้งเดียวตอนสร้าง ดังนั้นถ้าทำหาย คุณต้องสร้างใหม่แทนที่จะกู้ของเดิม
กฎเชิงปฏิบัติที่ควรจำ
- ออกคีย์แยกต่อสภาพแวดล้อมการติดตั้งและต่อบริการ การเพิกถอนคีย์ที่รั่วไหลไม่ควรทำให้ระบบที่ไม่เกี่ยวข้องกันสามระบบล่มไปด้วย
- API key มาตรฐานมีสิทธิ์ทั้งบัญชี ให้ถือว่าทุกคีย์เข้าถึงผู้ติดต่อ การส่ง และข้อมูล CRM ได้เต็มที่
- Brevo ยังรองรับ OAuth 2.0 สำหรับแอปพลิเคชันที่ทำงานแทนบัญชี Brevo อื่น ซึ่งอธิบายไว้คู่กับการใช้คีย์ใน authentication schemes
- เซิร์ฟเวอร์ MCP ที่ผู้ช่วย AI ใช้ ต้องใช้โทเค็นแยกต่างหากและใช้ header แบบ bearer จริง โทเค็นนั้นสร้างในหน้า API keys เดียวกันแต่ใช้แทน REST key ไม่ได้
Base URL การกำหนดเวอร์ชัน และการเขียนข้อมูลครั้งแรก
Base URL คือ https://api.brevo.com/v3/ เวอร์ชันอยู่ใน path ไม่ใช่ใน header และ v3 คือรุ่นปัจจุบัน ทุก path ในคู่มือนี้อ้างอิงจาก base นั้น
การเขียนข้อมูลครั้งแรกให้ข้อมูลมากกว่าการอ่านครั้งแรก เพราะมันไปแตะส่วนของบัญชีที่มักตั้งค่าผิด โดยเฉพาะผู้ส่งที่ยืนยันแล้ว
curl -X POST https://api.brevo.com/v3/smtp/email \ -H "api-key: $BREVO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sender": { "name": "Ops", "email": "[email protected]" }, "to": [{ "email": "[email protected]", "name": "Dev" }], "subject": "การส่งอีเมลธุรกรรมครั้งแรก", "htmlContent": "<html><body><p>ใช้งานได้แล้ว</p></body></html>", "tags": ["smoke-test"] }'การส่งที่สำเร็จจะคืนค่า 201 พร้อม messageId ส่วนการส่งแบบตั้งเวลาจะคืนค่า 202
Endpoint ที่คุณจะได้ใช้จริง
ผู้ติดต่อ
POST /v3/contacts สร้างผู้ติดต่อ เนื้อหาคำขอรับ email แผนที่ attributes สำหรับฟิลด์ที่กำหนดเอง listIds ext_id สำหรับคีย์ภายนอกของคุณเอง และแฟล็กสองตัวที่สำคัญที่สุดในทางปฏิบัติ ได้แก่ updateEnabled ซึ่งเปลี่ยนการเรียกให้กลายเป็น upsert และ getId ซึ่งทำให้การตอบกลับส่งรหัสผู้ติดต่อกลับมาด้วย
การอ่านใช้ GET /v3/contacts ซึ่งแบ่งหน้าด้วย limit (ค่าเริ่มต้น 50 สูงสุด 1000) และ offset และรองรับ modifiedSince กับ createdSince ในเวลา UTC การซิงค์แบบเพิ่มทีละส่วนควรพึ่ง modifiedSince แทนการไล่อ่านรายชื่อทั้งหมด อนึ่ง พารามิเตอร์ filter รองรับเฉพาะตัวดำเนินการเท่ากับเท่านั้น ดังนั้นเงื่อนไขที่ซับซ้อนกว่านั้นควรอยู่ในเซกเมนต์
สำหรับการนำเข้าจำนวนมาก POST /v3/contacts/import รับ fileUrl fileBody หรือ jsonBody ระบุปลายทางด้วย listIds และทำงานแบบอะซิงโครนัส คืนค่า processId Brevo ระบุขนาดเนื้อหาสูงสุด 10 MB และแนะนำให้อยู่ราว 8 MB เพราะการแปลงข้อมูลทำให้เพย์โหลดพองขึ้น ให้ระบุ notifyUrl เพื่อรับทราบผลลัพธ์แทนการคอยถามซ้ำ
อีเมลธุรกรรม
POST /v3/smtp/email คือตัวหลัก นอกจาก sender to subject และ htmlContent แล้ว ฟิลด์ที่ควรรู้ได้แก่
templateIdคู่กับparamsซึ่งแทนที่เนื้อหาแบบอินไลน์ด้วยเทมเพลตของ Brevo และการแทนค่าตัวแปร พารามิเตอร์ของแต่ละเวอร์ชันจำกัดที่ 100 KB และรวมกันทั้งหมดที่ 1000 KBmessageVersionsซึ่งส่งเนื้อหาหลายแบบที่ปรับให้เข้ากับผู้รับในคำขอเดียว รองรับผู้รับสูงสุด 99 รายต่อเวอร์ชันtagsซึ่งคุณควรตั้งเสมอ แท็กจะกลับมากับอีเวนต์ของ Webhook และเป็นวิธีเดียวที่ประหยัดในการเชื่อมโยงอีเวนต์การส่งกับเส้นทางโค้ดที่สร้างมันขึ้นมาscheduledAtคู่กับbatchIdสำหรับการส่งในอนาคตที่คุณอาจต้องการยกเลิกทั้งกลุ่มheadersเขียนแบบ Title-Case สำหรับ SMTP header ที่กำหนดเอง
คำขอเดียวรับผู้รับได้สูงสุด 2,000 ราย สำหรับความแตกต่างระหว่าง endpoint นี้กับการส่งแคมเปญ คู่มืออีเมลธุรกรรม ให้มุมมองเชิงกลยุทธ์การส่งข้อความไว้แล้ว
แคมเปญอีเมล
POST /v3/emailCampaigns ต้องการ name และ sender พร้อมแหล่งเนื้อหาเพียงหนึ่งอย่างเท่านั้น ได้แก่ htmlContent (อย่างน้อย 10 ตัวอักษร ไม่เกิน 1 MB) htmlUrl หรือ templateId กลุ่มเป้าหมายอยู่ใน recipients เป็น listIds หรือ segmentIds และ scheduledAt ใช้รูปแบบ UTC YYYY-MM-DDTHH:mm:ss.SSSZ เส้นทางที่เกี่ยวข้องครอบคลุมการส่งทันที การส่งทดสอบ การอัปเดตสถานะ และการดึงรายงานแคมเปญ
บริษัท ดีล และออบเจกต์
CRM ของ Brevo มีเส้นทางการเขียนสองแบบที่ทับซ้อนกัน และการเลือกให้ถูกมีผลจริง
เส้นทาง CRM ได้แก่ POST /v3/companies PATCH /v3/companies/{id} DELETE /v3/companies/{id} และชุดเทียบเท่าสำหรับดีล เส้นทางเหล่านี้ทำงานแบบซิงโครนัส PATCH จะคืนค่า 204 เมื่อการเปลี่ยนแปลงถูกนำไปใช้แล้ว
ส่วน objects API คือเส้นทางแบบกลุ่ม POST /v3/objects/{object_type}/batch/upsert รับได้สูงสุด 1000 เรกคอร์ดและ 1 MB ต่อคำขอ สูงสุด 500 แอตทริบิวต์ต่อเรกคอร์ด และสูงสุด 10 เรกคอร์ดความสัมพันธ์ต่อประเภทออบเจกต์ต่อเรกคอร์ด มันคืนค่า 202 พร้อม processId ซึ่งหมายถึงรับเรื่องไว้แล้ว ไม่ใช่ดำเนินการเสร็จแล้ว
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" } } ] }'คู่มือ Brevo CRM อธิบายโมเดลออบเจกต์จากมุมของผู้ใช้งานฝั่งปฏิบัติการ
SDK อย่างเป็นทางการ
Brevo ดูแลไคลเอนต์ภายใต้องค์กร getbrevo บน GitHub
| ภาษา | ที่เก็บโค้ด |
|---|---|
| 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 |
ไคลเอนต์ของ Node ติดตั้งในชื่อ @getbrevo/brevo
npm install @getbrevo/brevoimport { BrevoClient } from "@getbrevo/brevo";
const brevo = new BrevoClient({ apiKey: process.env.BREVO_API_KEY });
const result = await brevo.transactionalEmails.sendTransacEmail({ subject: "ยืนยันคำสั่งซื้อแล้ว", htmlContent: "<html><body><p>ขอบคุณสำหรับคำสั่งซื้อของคุณ</p></body></html>", tags: ["order-confirmation"],});
console.log("Message ID:", result.messageId);ไคลเอนต์ของ Python ติดตั้งด้วย pip install brevo-python หากคุณไม่อยากแบกภาระ SDK เพียงเพื่อเรียกสอง endpoint พื้นผิว HTTP ดิบก็เล็กพอที่จะเรียกตรงได้ ซึ่งยังช่วยกันคุณจากการเปลี่ยนเวอร์ชันของ SDK ด้วย
import osimport requests
BASE = "https://api.brevo.com/v3"HEADERS = { "api-key": os.environ["BREVO_API_KEY"], "Content-Type": "application/json",}
def upsert_contact(email, attributes, list_ids): response = requests.post( f"{BASE}/contacts", headers=HEADERS, json={ "email": email, "attributes": attributes, "listIds": list_ids, "updateEnabled": True, }, timeout=30, ) response.raise_for_status() return responseนอกจากนี้ยังมี เซิร์ฟเวอร์ MCP ที่ https://mcp.brevo.com/v1/brevo/mcp สำหรับผู้ช่วย AI ยืนยันตัวตนด้วย bearer token ที่สร้างในหน้าการตั้งค่าเดียวกัน มันมีประโยชน์สำหรับการสำรวจข้อมูลและคำถามเกี่ยวกับบัญชี ไม่ใช่สำหรับเส้นทางข้อมูลระดับโปรดักชัน
Webhook
Webhook คือวิธีที่คุณรู้ว่าเกิดอะไรขึ้นหลังการส่ง POST /v3/webhooks สร้างหนึ่งรายการ ด้วย url events type และตัวเลือกอย่าง channel (email หรือ sms) batched headers ที่กำหนดเอง และออบเจกต์ auth
Webhook มีสามประเภท แต่ละประเภทมีชุดอีเวนต์ของตัวเอง
- ธุรกรรม:
sent,request,delivered,hardBounce,softBounce,blocked,spam,invalid,deferred,click,opened,uniqueOpened,unsubscribed - การตลาด:
spam,opened,click,hardBounce,softBounce,unsubscribed,listAddition,delivered,contactUpdated,contactDeleted - ขาเข้า:
inboundEmailProcessedและreplyซึ่งต้องระบุdomainเพิ่มด้วย
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": "สัญญาณด้านการส่งถึงกล่องขาเข้า" }'มีสามเรื่องที่ต้องทำให้ถูก เรื่องแรก หนึ่งบัญชีมี Webhook ได้สูงสุด 40 รายการรวมทุกประเภท ดังนั้นให้แยกเส้นทางตามอีเวนต์ภายในตัวจัดการของคุณ แทนที่จะลงทะเบียนหนึ่ง endpoint ต่อหนึ่งอีเวนต์ เรื่องที่สอง ใช้แฟล็ก batched เมื่อคาดว่าจะมีปริมาณมาก เพราะคำขอเดียวที่บรรทุกหลายอีเวนต์ประมวลผลถูกกว่าคำขอจำนวนมากอย่างเทียบไม่ติด เรื่องที่สาม ป้องกันตัวรับ Brevo เผยแพร่ช่วง IP ที่ใช้ส่ง และการจำกัด endpoint ของคุณให้รับเฉพาะช่วงเหล่านั้นคือวิธีที่เอกสารแนะนำ เพิ่มความลับร่วมของคุณเองผ่านฟิลด์ headers เป็นชั้นที่สอง
ตัวจัดการต้องเป็น idempotent ให้ใช้รหัสข้อความบวกประเภทอีเวนต์บวกเวลาเป็นคีย์สำหรับตัดรายการซ้ำ
ขีดจำกัดอัตราและการจัดการข้อผิดพลาด
ขีดจำกัดอัตรา ของ Brevo กำหนดแยกตาม endpoint และตามระดับแพ็กเกจ และช่องว่างระหว่าง endpoint นั้นกว้างมาก
| Endpoint | มาตรฐาน | Professional และ 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 | สูงกว่าบน Enterprise |
GET /v3/smtp/emails | 2 RPS, 7,200 RPH | 3 RPS, 10,800 RPH |
| ทุกอย่างที่เหลือ | 100 RPH | 200 RPH |
แถวสุดท้ายคือแถวที่เจ็บ การส่งแทบไม่ถูกจำกัดเลย ในขณะที่การจัดการแคมเปญ การอ่าน CRM และการเรียกเชิงบริหารส่วนใหญ่ต้องแบ่งงบ 100 คำขอต่อชั่วโมงร่วมกันบนแพ็กเกจมาตรฐาน การไล่เติมข้อมูลย้อนหลังแบบไร้เดียงสาที่อ่านเรกคอร์ดบริษัทก่อนเขียนทุกครั้ง จะใช้โควตาทั้งชั่วโมงหมดภายในไม่ถึงสองนาที
ทุกการตอบกลับจะมี x-sib-ratelimit-limit x-sib-ratelimit-remaining และ x-sib-ratelimit-reset ให้อ่านค่าเหล่านี้ตอนสำเร็จด้วย ไม่ใช่เฉพาะตอนล้มเหลว หากเกินขีดจำกัดจะได้ 429 และการตอบสนองที่ถูกต้องคือรอตามช่วงเวลาใน header reset แล้วค่อยใช้ exponential backoff พร้อม jitter
async function callBrevo(path, init, attempt = 0) { const response = await fetch(`https://api.brevo.com/v3${path}`, { ...init, headers: { "api-key": process.env.BREVO_API_KEY, "Content-Type": "application/json", ...init.headers }, });
if (response.status === 429 && attempt < 5) { const reset = Number(response.headers.get("x-sib-ratelimit-reset") || 1); const backoff = Math.pow(2, attempt) * 250 + Math.random() * 250; await new Promise((r) => setTimeout(r, reset * 1000 + backoff)); return callBrevo(path, init, attempt + 1); }
return response;}ให้ลองใหม่กับ 429 และ 5xx อย่าลองใหม่กับ 400 หรือ 409 แบบไม่คิด เพราะทั้งคู่มักหมายถึงคำขอผิด ไม่ใช่เร็วเกินไป และ 409 โดยเฉพาะต้องการการกระทำที่ต่างออกไป ไม่ใช่การส่งซ้ำ
การทดสอบโดยไม่ส่งอีเมลจริง
เพิ่ม header X-Sib-Sandbox ค่า drop ลงในคำขอส่งอีเมลธุรกรรม Brevo จะตรวจสอบคำขอ คืนค่า 201 พร้อม messageId ไม่ส่งอะไรเลย และไม่บันทึกล็อกอีเมล
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>" }'ทำความเข้าใจว่าสิ่งนี้พิสูจน์อะไรและไม่พิสูจน์อะไร โหมด sandbox ตรวจสอบเฉพาะรูปแบบของคำขอ มันไม่บอกอะไรเลยเกี่ยวกับการยืนยันตัวตนผู้ส่ง การเรนเดอร์เทมเพลต หรือความสามารถในการส่งถึงกล่องขาเข้า ให้แยกบัญชี Brevo ต่างหากไว้ทดสอบการเชื่อมต่อของทุกอย่างที่แตะข้อมูลผู้ติดต่อหรือ CRM เพราะโหมด sandbox ครอบคลุมเฉพาะการส่ง ไม่ครอบคลุมส่วนที่เหลือของ API
ข้อจำกัดที่กำหนดรูปแบบการออกแบบการเชื่อมต่อของคุณ
นี่คือข้อจำกัดที่จะปรากฏก็ต่อเมื่อการเชื่อมต่อทำงานกับบัญชีจริงที่ปริมาณจริง หลายข้อขัดแย้งกับสิ่งที่ API บอกเกี่ยวกับตัวเอง ไม่มีข้อใดต่อรองได้ ดังนั้นทางออกเดียวที่สมเหตุสมผลคือออกแบบให้อยู่กับมันได้
บริษัทต้องมีโดเมน และหนึ่งโดเมนได้เพียงหนึ่งบริษัท
GET /v3/crm/attributes/companies รายงานว่าแอตทริบิวต์ทุกตัวไม่จำเป็นต้องกรอก และเอกสารอ้างอิงการสร้างบริษัทระบุเพียง name ว่าเป็นฟิลด์บังคับ แต่ในทางปฏิบัติ POST /v3/companies ที่ไม่มีแอตทริบิวต์ domain ซึ่งมีค่าไม่ว่างจะคืนค่า 400 พร้อมข้อความเรื่องแอตทริบิวต์เริ่มต้นที่จำเป็นขาดหายไป การใส่สตริงว่างก็ล้มเหลวเหมือนกับการไม่ใส่เลย
ที่แย่กว่านั้นคือมีการบังคับให้โดเมนไม่ซ้ำ บริษัทรายที่สองบนโดเมนที่ถูกใช้ไปแล้วจะคืนค่า 409 สำหรับการค้าแบบ B2B นี่เป็นปัญหาเชิงโครงสร้าง บริษัทลูกที่ใช้โดเมนอีเมลผู้ซื้อร่วมกันไม่สามารถมีอยู่เป็นบริษัทแยกกันใน Brevo ได้ทั้งหมด อีกทั้งการซิงค์ผู้ติดต่อเพียงรายเดียวก็เพียงพอที่จะทำให้เกิดบริษัทบนโดเมนอีเมลของผู้ติดต่อรายนั้น ดังนั้นการสร้างบริษัทอาจชนกับบริษัทที่ไม่มีใครตั้งใจสร้าง ตัวจัดการที่ถูกต้องจะรับบริษัทที่มีอยู่มาใช้เมื่อเจอ 409 แทนที่จะล้มเหลวหรือลองใหม่
แอตทริบิวต์ที่ไม่ได้ประกาศถูกทิ้งอย่างเงียบ ๆ
นี่คือพฤติกรรมที่อันตรายที่สุดในแพลตฟอร์ม และ Brevo ระบุไว้ตรงไปตรงมา ถ้าแอตทริบิวต์ปรากฏในคำขอแต่ไม่เคยถูกนิยามไว้ในสคีมาของออบเจกต์ จะไม่มีอะไรเกิดขึ้น ไม่มีข้อผิดพลาด ไม่มีการสร้างแอตทริบิวต์ ไม่มีคำเตือน
การตอบกลับ 2xx จึงไม่ใช่หลักฐานว่าข้อมูลของคุณลงจริง ให้อ่านสคีมาก่อนเขียน ตัดทุกอย่างที่ไม่ได้ประกาศออกในไคลเอนต์ของคุณเอง และปฏิเสธที่จะรันการซิงค์ที่แอตทริบิวต์ยังไม่มีอยู่ แทนที่จะเขียนเรกคอร์ดครึ่งใบทิ้งไว้เป็นเดือนกว่าจะมีใครสังเกตเห็น
ตัวกรองแอตทริบิวต์ถูกรับไว้แล้วเพิกเฉย
GET /v3/companies?filters[attributes.domain]=... คืนค่า 200 และเพิกเฉยต่อตัวกรอง ตัวกรองที่ต่างกันโดยสิ้นเชิงสองแบบคืนเรกคอร์ดชุดเดียวกัน ไม่มีวิธีที่ใช้ได้จริงในการค้นหาบริษัทจากแอตทริบิวต์ผ่านเส้นทางนั้น
เมื่อรวมกับข้อเท็จจริงที่ว่าการดึงรายการแบบไม่กรองจะหมดเวลาด้วย 504 บนบัญชีขนาดใหญ่ไม่ว่าจะตั้งขนาดหน้าเท่าใด บริษัทที่มีอยู่จริงอาจค้นหาไม่พบเลยผ่านเส้นทางที่เอกสารระบุ ทางแก้คือสแกน GET /v3/objects/company/records ด้วย sort=desc ซึ่งเร็ว แบ่งหน้าได้ และคืนแอตทริบิวต์มาด้วย โดยจำกัดจำนวนหน้าไว้ในระดับที่สมเหตุสมผล บริษัทที่เพิ่งทำให้เกิด 409 มักถูกสร้างขึ้นไม่กี่อึดใจก่อนหน้านั้น การสแกนจากใหม่ไปเก่าจึงเจอได้เร็ว
หนึ่งล้านเรกคอร์ดต่อประเภทออบเจกต์ และไม่มีการลบแบบกลุ่ม
POST /v3/objects/{type}/batch/upsert จะคืนค่า 400 เมื่อประเภทออบเจกต์นั้นมีหนึ่งล้านเรกคอร์ดแล้ว มันบล็อกทั้งการอัปเดตและการสร้าง การอ้างถึงเรกคอร์ดที่มีอยู่ด้วยรหัสตัวเลขของมันเองก็ล้มเหลวเช่นเดียวกัน เส้นทางการเขียนออบเจกต์ทั้งเส้นปิดตัวลงพร้อมกัน
การลดจำนวนให้กลับลงมาต่ำกว่าเพดานทำได้ช้า เพราะ POST /v3/objects/{type}/batch/delete คืนค่า 403 สำหรับออบเจกต์มาตรฐานของ Brevo เช่น company เส้นทางเดียวที่เหลือคือ DELETE /v3/companies/{id} ทีละเรกคอร์ดต่อหนึ่งการเรียก ที่ราว 156 ms การล้าง 124,000 เรกคอร์ดด้วยวิธีนี้ใช้เวลาหลายชั่วโมงแม้จะใช้ตัวประมวลผลขนาน 20 ตัว ให้เฝ้าดูจำนวนเรกคอร์ดตามตารางเวลา แทนที่จะมารู้จักเพดานจากการซิงค์ที่ล้มเหลว และให้ส่งการอัปเดตปริมาณสูงผ่าน PATCH /v3/companies/{id} ซึ่งไม่มีข้อจำกัดแบบนั้น
ext_id เป็นรหัสของ Brevo ไม่ใช่ของคุณ
บนเรกคอร์ดออบเจกต์ identifiers.ext_id เก็บรหัสบริษัทใน CRM ของ Brevo เอง เป็นสตริงสไตล์ Mongo มันไม่ใช่คีย์ภายนอกที่คุณกำหนดได้อิสระ การทำ upsert โดยใช้ ext_id เป็นตัวระบุของแพลตฟอร์มคุณจะสร้างข้อมูลซ้ำแทนที่จะจับคู่ รหัสภายนอกของคุณควรอยู่ในแอตทริบิวต์ที่ประกาศไว้เองต่างหาก
การ upsert ออบเจกต์เป็นแบบอะซิงโครนัส ส่วนการเขียน CRM ไม่ใช่
batch/upsert คืนค่า 202 พร้อม processId แล้วจึงนำไปใช้ภายหลัง รหัสที่ไม่มีอยู่จริงจะล้มเหลวแบบอะซิงโครนัสและยังคืนค่า 202 ให้ผู้เรียกอยู่ดี ส่วน PATCH /v3/companies/{id} คืนค่า 204 และมีผลทันทีแบบซิงโครนัส หากการซิงค์ของคุณรายงานว่าสำเร็จ มีเพียงเส้นทางซิงโครนัสเท่านั้นที่สมควรใช้คำนั้นได้โดยไม่ต้องอ่านซ้ำเพื่อยืนยัน
รายการตรวจสอบสั้น ๆ สำหรับการเชื่อมต่อ
- แยก API key ต่อบริการและต่อสภาพแวดล้อม พร้อมหมุนคีย์เมื่อมีการเปลี่ยนแปลงบุคลากร
- การเขียนทั้งหมดผ่านไคลเอนต์ตัวเดียวที่อ่าน header ขีดจำกัดอัตราและถอยเมื่อเจอ 429
- ตรวจสอบสคีมาของแอตทริบิวต์ตอนเริ่มระบบ และให้การซิงค์ปฏิเสธที่จะทำงานหากแอตทริบิวต์หายไป
- 409 ตอนสร้างบริษัทหมายถึงให้รับของเดิมมาใช้ ไม่ใช่ลองใหม่
- เส้นทางแบบกลุ่มใช้ objects API เพื่อปริมาณงาน และใช้เส้นทาง CRM สำหรับสิ่งที่ต้องยืนยันผล
- Webhook ต้องเป็น idempotent ทำงานแบบรวมกลุ่ม จำกัด IP และมี header ความลับร่วม
- การซิงค์ผู้ติดต่อแบบเพิ่มทีละส่วนใช้
modifiedSinceไม่ใช่การไล่อ่านรายชื่อทั้งหมด
การสร้างและดูแลชั้นนี้คืองานวิศวกรรมของจริง ทั้งการตรวจสอบสคีมา การถอยเมื่อโดนจำกัด ตรรกะการรับบริษัทเดิมมาใช้ และการกระทบยอดข้อมูล Tajo มีอยู่เพื่อรับภาระนี้ไป โดยทำให้ข้อมูล Shopify และข้อมูลการค้าซิงค์กับผู้ติดต่อ บริษัท และอีเวนต์ใน Brevo โดยไม่ต้องมีใครเขียนตรรกะการลองใหม่และการตัดข้อมูลซ้ำด้วยมือ หากคุณจะต่อเองแทน คู่มือการเชื่อมต่อ Brevo พาไล่ดูตัวเลือกของโมเดลข้อมูลที่ต้องตัดสินใจก่อนลงมือเขียนโค้ด
ประเด็นสำคัญ
- API เป็นพื้นผิว REST เดียวที่
https://api.brevo.com/v3/ยืนยันตัวตนด้วย headerapi-keyแทนที่จะเป็น bearer token - ขีดจำกัดอัตราไม่สม่ำเสมออย่างมาก การส่งแทบไม่ถูกจำกัดเลย ในขณะที่ endpoint อื่นส่วนใหญ่ต้องแบ่ง 100 คำขอต่อชั่วโมงร่วมกันบนแพ็กเกจมาตรฐาน
- มี SDK อย่างเป็นทางการเจ็ดภาษา แต่พื้นผิว HTTP ก็เรียบง่ายพอที่จะเรียกตรงได้เมื่อคุณต้องใช้เพียงไม่กี่ endpoint
- โหมด sandbox ตรวจสอบเฉพาะรูปแบบของคำขอ ดังนั้นให้แยกบัญชีต่างหากไว้ทดสอบทุกอย่างที่เกินกว่าการส่ง
- การตอบกลับ 2xx ไม่ได้พิสูจน์ว่าการเขียนมีผล แอตทริบิวต์ที่ไม่ได้ประกาศจะถูกทิ้งอย่างเงียบ ๆ และการ upsert ออบเจกต์เป็นแบบอะซิงโครนัส
- ออกแบบให้อยู่กับข้อจำกัดตายตัว หนึ่งโดเมนหนึ่งบริษัท หนึ่งล้านเรกคอร์ดต่อประเภทออบเจกต์ ไม่มีการลบแบบกลุ่มสำหรับออบเจกต์มาตรฐาน และตัวกรองแอตทริบิวต์ที่ไม่ทำอะไรเลยอย่างเงียบ ๆ