في هذه الصفحة
قد تعيد كتابة جهة اتصال الرمز 201 وتظل النتيجة خاطئة: ضاع معرّف المصدر، أو اختيرت قائمة خاطئة، أو أُهمل إلغاء اشتراك سابق. هذه قرارات تخص البيانات، وليست تفاصيل HTTP فقط.
يبدأ الدليل بطلب كتابة يعمل، ثم يشرح فحوص مزامنة صغيرة قابلة للتكرار.
ما الذي تغطيه واجهة Brevo API
كل شيء يقع تحت مضيف واحد ومسار إصدار واحد. تقسّم وثائق المطورين السطح إلى أربعة مجالات منتجات:
- المراسلة: البريد المعاملاتي، والرسائل النصية، و WhatsApp، بما في ذلك الإرسال الدفعي والجدولة ونشاط الرسائل.
- منصّة التسويق: جهات الاتصال والقوائم والشرائح وحملات البريد الإلكتروني.
- التجارة الإلكترونية: المنتجات والطلبات وتتبّع أحداث العملاء.
- المحادثات: أداة الدردشة وإدارة المحادثات برمجيًا.
هذه المجالات تتشارك حسابًا واحدًا، وقاعدة جهات اتصال واحدة، ومفتاح API واحدًا. هذا مريح وخطير أحيانًا: نصّ برمجي كُتب على أساس تصوّر تجريبي للبيانات يتحدث في الواقع إلى جهات الاتصال نفسها التي ترسل إليها حملاتك.
المعاملاتي مقابل التسويقي
تختلف العائلتان في سلوكهما بما يكفي لجعل الخلط بينهما أكثر أخطاء التصميم شيوعًا.
| معاملاتي | تسويقي | |
|---|---|---|
| نقطة النهاية الأساسية | POST /v3/smtp/email | POST /v3/emailCampaigns |
| تحديد المستلمين | مستلمون صريحون في الطلب | listIds أو segmentIds |
| المُشغِّل | تطبيقك، في الوقت الفعلي | مجدول أو يُرسَل عند الطلب |
| شكل الحجم المعتاد | مستمر، رسالة واحدة في كل مرة | متقطع، إرسالة واحدة كبيرة |
| موقف حدود المعدل | مرتفع جدًا، 1,000 طلب في الثانية في المستوى العام | منخفض، نقاط نهاية الحملات تقع ضمن السقف العام |
إذا كنت لا تزال تقرّر ما إذا كانت Brevo هي المنصّة المناسبة أصلًا، فإن نظرة عامة على المنصّة تغطي هذا الجانب.
المصادقة وإدارة المفاتيح
تستخدم Brevo مفتاح API بسيطًا داخل ترويسة مخصّصة. اسم الترويسة هو api-key، وليس Authorization، ولا توجد بادئة Bearer. هذه النقطة تُربك تقريبًا كل من استخدم واجهة مراسلة أخرى قبلها.
يمكن أن يستخدم OAuth رمز Bearer في العمليات المدعومة؛ ويبقى المفتاح المعتاد في ترويسة api-key.
curl https://api.brevo.com/v3/account \ -H "api-key: $BREVO_API_KEY"تُنشأ المفاتيح داخل تطبيق Brevo ضمن إعدادات الحساب، في قسم SMTP and API، في تبويب API keys. امنح كل مفتاح اسمًا وصفيًا مرتبطًا بالنظام الذي يستخدمه. تُعرض قيمة المفتاح مرة واحدة فقط عند إنشائه، فإذا فقدتها تُنشئ مفتاحًا جديدًا بدل استرجاع القديم.
بعض القواعد العملية:
- أصدر مفتاحًا منفصلًا لكل بيئة نشر ولكل خدمة. إبطال مفتاح مسرَّب يجب ألا يوقف ثلاثة أنظمة غير مرتبطة.
- مفاتيح API القياسية تشمل الحساب كله. تعامل مع أي مفتاح على أنه وصول كامل إلى جهات الاتصال والإرسال وبيانات CRM.
- تدعم Brevo أيضًا OAuth 2.0 للتطبيقات التي تعمل نيابة عن حسابات Brevo أخرى، وهو موصوف إلى جانب تدفق المفاتيح في مخططات المصادقة.
- خادم MCP الذي تستخدمه مساعدات AI يأخذ رمزًا منفصلًا، وهو يستخدم فعلًا ترويسة bearer. يُنشأ ذلك الرمز في شاشة API keys نفسها لكنه غير قابل للتبادل مع مفتاح REST.
عنوان القاعدة والإصدارات وأول عملية كتابة
عنوان القاعدة هو https://api.brevo.com/v3/. رقم الإصدار في المسار وليس في ترويسة، و v3 هو الجيل الحالي. كل مسار في هذا الدليل نسبي لذلك العنوان.
استخدم في أول كتابة عنوانًا تجريبيًا تملكه، ومعرّف قائمة صالحًا، ومعرّف مصدر ثابتًا. أنشئ السمة FNAME في Brevo أولًا. باستخدام مفتاح حقيقي، يكتب هذا المثال مباشرة:
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 }'استبدل 42 بمعرّف القائمة التجريبية. أعد قراءة جهة الاتصال وتحقق من المعرّف والاسم والقائمة والحظر. الرمز 2xx وحده لا يثبت النتيجة المتوقعة.
نقاط النهاية التي ستستخدمها فعلًا
جهات الاتصال
ينشئ POST /v3/contacts جهة اتصال. يقبل الطلب email وattributes المعرّفة وlistIds وext_id كمفتاح مصدر ثابت. يحدّث updateEnabled: true جهة موجودة، ويطلب getId: true المعرّف النهائي. يوثق Brevo هذه الحقول. استخدم قيمة ext_id نفسها في كل تشغيل واحفظ الربط بين معرّف المصدر ومعرّف Brevo.
قبل الكتابة، حدد النظام المسؤول عن كل سمة والقائمة التي تستقبل جهات الاتصال التي وافقت. اذكر listIds صراحة. لا ترسل emailBlacklisted: false في التحديث المعتاد. يحذر Brevo من أن تغيير بريد جهة محظورة قد يرفع الحظر؛ تعامل مع تغيير العنوان منفصلًا. تحقق من الحظر وإلغاء الاشتراك قبل الإضافة إلى قائمة تسويقية. قد تتغير الحالة بين القراءة والكتابة؛ إذا احتجت ضمانًا صارمًا فتحقق مرة أخيرة قبل الإرسال.
تمر القراءات عبر GET /v3/contacts، الذي يرقّم النتائج باستخدام limit (الافتراضي 50، والحد الأقصى 1000) و offset، ويدعم modifiedSince و createdSince بتوقيت UTC. عمليات المزامنة التزايدية يجب أن تعتمد على modifiedSince بدل المرور على القائمة كاملة. لاحظ أن المعامل filter يدعم عامل المساواة فقط، لذا فإن أي شيء أكثر تعبيرًا مكانه شريحة.
للتحميل الجماعي، يقبل POST /v3/contacts/import القيم fileUrl أو fileBody أو jsonBody، ويستهدف listIds، ويعمل بشكل غير متزامن مُعيدًا processId. توثّق Brevo حدًا أقصى للجسم يبلغ 10 ميجابايت وتنصح بالبقاء قرب 8 ميجابايت لأن التحليل يضخّم الحمولة. مرّر notifyUrl كي تعرف النتيجة بدل الاستعلام المتكرر.
البريد المعاملاتي
POST /v3/smtp/email هو حصان العمل. إلى جانب sender و to و subject و htmlContent، الحقول التي تستحق المعرفة هي:
templateIdمعparams، وهو يستبدل المحتوى المضمَّن بقالب Brevo واستبدالات متغيراته. حدود معاملات النسخة الواحدة 100 كيلوبايت، والمجموع التراكمي 1000 كيلوبايت.messageVersions، الذي يرسل نسخًا مخصّصة في استدعاء واحد، بحد أقصى 99 مستلمًا لكل نسخة.- قد تساعد
tagsفي ربط أحداث التسليم بسير العمل في التطبيق الذي أنشأها. scheduledAtمعbatchId، للإرسالات المستقبلية التي قد ترغب في إلغائها كمجموعة.headers، بصيغة Title-Case، لترويسات SMTP المخصّصة.
يقبل الطلب الواحد 2,000 مستلم كحد أقصى. وللفرق بين هذه النقطة وإرسال الحملات، يقدّم دليل البريد المعاملاتي وجهة نظر استراتيجية المراسلة.
حملات البريد الإلكتروني
يتطلب POST /v3/emailCampaigns الحقلين name و sender، إضافة إلى مصدر محتوى واحد بالضبط: htmlContent (10 أحرف كحد أدنى، وأقل من 1 ميجابايت)، أو htmlUrl، أو templateId. يوضع الجمهور في recipients بصيغة listIds أو segmentIds، ويستخدم scheduledAt صيغة YYYY-MM-DDTHH:mm:ss.SSSZ بتوقيت UTC. وتغطي المسارات المرافقة الإرسال الفوري، وإرسال اختبار، وتحديث الحالة، وسحب تقرير الحملة.
الشركات والصفقات والكائنات
يمتلك نظام CRM في Brevo مسارَي كتابة متداخلين، والاختيار الصحيح بينهما مهم.
مسارات CRM هي POST /v3/companies و PATCH /v3/companies/{id} و DELETE /v3/companies/{id}، والمجموعة المكافئة للصفقات. هذه المسارات متزامنة. يعيد PATCH الحالة 204 بمجرد تطبيق التغيير.
أما واجهة الكائنات فهي المسار الجماعي: POST /v3/objects/{object_type}/batch/upsert يأخذ حتى 1000 سجل و 1 ميجابايت لكل طلب، وحتى 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";
// 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);يُثبَّت عميل Python عبر pip install brevo-python. وإذا كنت تفضّل ألا تحمل اعتمادية SDK من أجل نقطتَي نهاية فقط، فإن سطح HTTP الخام صغير بما يكفي لاستدعائه مباشرة، وهذا يعزلك أيضًا عن تقلّبات إصدارات SDK:
ثبّت عميل Python بالأمر pip install brevo-python. ويمكن استخدام HTTP مباشرة لعدد قليل من نقاط النهاية:
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 Noneقد يعيد التحديث الناجح ردًا فارغًا 204. عندئذ تعني None أن عليك قراءة جهة الاتصال مرة أخرى للحصول على المعرّف.
يفترض المثال أن المستدعي تحقق من الموافقة والحظر في Brevo مسبقًا. لا يطلب رفع الحظر. يكتب المفتاح الحقيقي إلى الحساب؛ اختبر أولًا بردود وهمية. قد يعيد تعارض المعرّفات رموز 4xx مختلفة. اقرأ الرد وطابق المعرّفات بدل افتراض 409 دائمًا.
الـ webhooks
الـ webhooks هي وسيلتك لمعرفة ما حدث بعد الإرسال. ينشئ POST /v3/webhooks واحدًا، مع url و events و type، واختياريًا channel (email أو sms)، و batched، وترويسات headers مخصّصة، وكائن auth.
هناك ثلاثة أنواع من الـ webhooks بمفردات أحداث مختلفة:
- معاملاتي:
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": "Deliverability signals" }'لتغييرات جهات الاتصال، سجل webhook تسويقيًا يتضمن contactUpdated. يسمي Brevo الحدث داخل الحمولة contact_updated. وثق المستقبِل برمز bearer من auth أو بترويسات مخصصة وفق دليل الأمان. تحقق من السر قبل المعالجة ولا تسجله.
احفظ مفتاح إزالة التكرار من نوع الحدث ومعرّف جهة الاتصال والطابع الزمني طوال فترة إعادة التسليم. الطابع الزمني وحده غير فريد. قد تتكرر الأحداث أو تصل بغير ترتيب. أعد قراءة جهة الاتصال الحالية وطابقها مع مصدر موثوق. حدد فترة إعادة التشغيل، وارفض الأحداث القديمة بعد التعافي، ونفذ فحصًا تزايديًا دوريًا لتعويض الفائت. webhook وحده لا ينشئ مزامنة ثنائية الاتجاه. راجع دليل الموصلات.
حدود المعدل ومعالجة الأخطاء
حدود المعدل في Brevo محدَّدة لكل نقطة نهاية ولكل مستوى خطّة، والفارق بين نقاط النهاية هائل.
| نقطة النهاية | General (كل الخطط) | Advanced (Professional و Enterprise) |
|---|---|---|
POST /v3/smtp/email | 1,000 طلب في الثانية | 2,000 طلب في الثانية |
POST /v3/transactionalSMS/send | 150 طلبًا في الثانية | 200 طلب في الثانية |
/v3/contacts/... | 10 في الثانية، 36,000 في الساعة | 20 في الثانية، 72,000 في الساعة |
POST /v3/events | 10 في الثانية، 36,000 في الساعة | 20 في الثانية، 72,000 في الساعة |
GET /v3/smtp/emails | 2 في الثانية، 7,200 في الساعة | 3 في الثانية، 10,800 في الساعة |
| نقاط النهاية التي ليس لها حد خاص بها | 100 في الساعة | 200 في الساعة |
يوثق Brevo ترويسات x-sib-ratelimit-limit وx-sib-ratelimit-remaining وx-sib-ratelimit-reset لنقاط النهاية المحدودة. اقرأها حتى في الردود الناجحة. بعد 429 انتظر إعادة الضبط، ثم أعد المحاولة ضمن حد ثابت للوقت والمحاولات. قيمة reset مدة بوحدة نافذة الحد، وغالبًا بالثواني، وليست وقت 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)); }}إذا تجاوز الانتظار المطلوب 60 ثانية، تعيد الدالة 429. حدد محاولة جديدة لاحقًا.
استخدم الدالة المساعدة فقط للطلبات التي تأكدت أن تكرارها آمن. بعد فشل إرسال ملتبس، طابق معرّف رسالتك قبل الإرسال مرة أخرى. سجل الحالة وترويسات الحد، لا المفتاح أو بيانات الاتصال.
لا تكرر كل 4xx دون فحص. يذكر مرجع إنشاء جهة اتصال 400 و425؛ ولا يلزم أن يكون التعارض 409. بعد 5xx في الكتابة، تحقق هل طُبق التغيير بالفعل.
ما الحالة التي عادت؟
-
429
انتظر ضمن الحد
استخدم مدة إعادة الضبط وتوقف بعد محاولات قليلة.
-
5xx بعد الكتابة
تحقق من النتيجة
قد يكون الخادم كتب قبل الخطأ.
-
400
صحح الطلب
غالبًا المدخل غير صالح.
-
تعارض المعرّف
طابق المعرّفات
لا تضمن الواجهة رمزًا واحدًا للتعارض.
الاختبار دون إرسال بريد
أضف الترويسة 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>" }'افهم ما يثبته هذا وما لا يثبته. وضع الاختبار المعزول يتحقق من صيغة الطلب فقط. وهو لا يقول شيئًا عن مصادقة المرسِل، أو عرض القالب، أو قابلية التسليم. احتفظ بحساب Brevo منفصل لاختبار تكامل أي شيء يمس جهات الاتصال أو بيانات CRM، لأن الوضع المعزول يغطي الإرسال لا بقية الواجهة.
تحقق قبل مزامنة جهات الاتصال
- اختر معرّف مصدر ثابتًا لـ
ext_idواحفظ معرّف Brevo. - عرّف السمات قبل الكتابة ثم أعد قراءة جهة الاتصال التجريبية.
- استخدم قائمة محددة ودليل موافقة موثوقًا؛ تجاوز المحظورين والملغين لاشتراكهم.
- احسب الكتابات المقبولة والمطبقة والمتجاوزة والفاشلة منفصلة. يعني 202 أولًا قبول الطلب فقط.
- وثق webhooks التسويقية، وأزل التكرار وطابق الحالة.
- راقب ترويسات الحد وتوقف بعد محاولات محددة.
يزامن Tajo بيانات التجارة مع Brevo. إذا بنيت هذا المسار بنفسك فراجع دليل الموصلات.
الأسئلة المتكررة
ما هو عنوان القاعدة لواجهة Brevo API؟
كل استدعاءات REST في Brevo تذهب إلى https://api.brevo.com/v3/. رقم الإصدار جزء من المسار، و v3 هو الجيل الحالي، لذا فإن نقطة نهاية مثل الإرسال المعاملاتي تكون بالمسار الكامل https://api.brevo.com/v3/smtp/email.
كيف تتم المصادقة مع واجهة Brevo API؟
أرسل مفتاحك في ترويسة HTTP اسمها api-key. لا تستخدم Brevo ترويسة Authorization أو Bearer لمفاتيح API القياسية. تُنشَأ المفاتيح ضمن إعدادات الحساب، ثم SMTP and API، ثم API keys، وتُعرض القيمة مرة واحدة فقط.
ما هي حدود المعدل في واجهة Brevo API؟
الحدود محدَّدة لكل نقطة نهاية ولكل مستوى من مستويات حدود المعدل. في المستوى العام، الذي تحصل عليه كل الخطط، تسمح نقطة نهاية الإرسال المعاملاتي بـ 1,000 طلب في الثانية، وتسمح نقاط نهاية جهات الاتصال بـ 10 في الثانية، أما نقاط النهاية التي ليس لها حد خاص بها فمحدودة بـ 100 طلب في الساعة. يمكن لخطّتَي Professional و Enterprise استخدام المستوى المتقدم (Advanced)، ولخطة Enterprise المستوى الموسّع (Extended). تجاوز الحد يعيد 429.
هل لدى Brevo حزم SDK رسمية؟
نعم. تنشر Brevo عملاء برمجيين للغات Node.js و Python و PHP و Java و C# و Go و Ruby ضمن منظمة getbrevo على GitHub. حزمة Node هي @getbrevo/brevo على npm، وحزمة Python هي brevo-python على PyPI.
كيف أختبر واجهة Brevo API دون إرسال بريد حقيقي؟
أضف الترويسة X-Sib-Sandbox بالقيمة drop إلى طلب إرسال معاملاتي. تتحقق Brevo من صحة الطلب، وتعيد 201 مع messageId، ولا ترسل شيئًا، ولا تكتب أي سجل بريد. هذا يفحص صيغة الطلب فقط، لا قابلية التسليم.
ما أحداث الـ webhook التي تدعمها Brevo؟
تغطي webhooks الخاصة بالرسائل المعاملاتية التسليم والارتداد وإلغاء الاشتراك. تتضمن webhooks التسويقية contactUpdated وcontactDeleted. يوثق Brevo الحدث inboundEmailProcessed للبريد الوارد.
كيف يحافظ تحديث جهة الاتصال على إلغاء الاشتراك السابق؟
استخدم معرّف مصدر ثابتًا وسمات معرّفة. لا ترسل emailBlacklisted: false في التحديث المعتاد. تحقق من جهة الاتصال ومصدر الموافقة قبل إضافتها إلى قائمة تسويقية.
هل يكفي webhook للمزامنة ثنائية الاتجاه؟
لا. تحقق من هوية المستقبِل، وأزل التسليمات المكررة، وطابق الأحداث المفقودة أو غير المرتبة مع مصدر موثوق. يشير webhook إلى تغيير، ولا يثبت تطابق حالة النظامين.