REST API
إرسال رسائل البريد الإلكتروني باستخدام REST API الخاص بـ Mail.Land مع مرجع كامل للطلبات والاستجابات
أرسل رسائل البريد الإلكتروني التحويلية عبر POST /v1/transactional/send. هذه هي الطريقة الأساسية لإرسال البريد الإلكتروني من خلال MailLand.
المصادقة
أدرج مفتاح API الخاص بك في رأس X-API-Key:
X-API-Key: ml_pet_Ab3Kx9mN2pQ7rT4wL8yD...يجب أن تحتوي بيانات الاعتماد على قناة Api مُفعَّلة وأن تكون بيانات اعتماد منتج Sending.
إرسال بريد إلكتروني واحد
POST https://api.mail.land/v1/transactional/sendcurl -X POST https://api.mail.land/v1/transactional/send \
-H "X-API-Key: ml_pet_Ab3Kx9mN2pQ7rT4wL8yD..." \
-H "Content-Type: application/json" \
-d '{
"from": {"email": "[email protected]"},
"to": [{"email": "[email protected]"}],
"subject": "Hello from MailLand",
"htmlContent": "<p>Your email content here</p>"
}'نص الطلب
{
"from": {
"email": "[email protected]",
"name": "Your App"
},
"to": [
{
"email": "[email protected]",
"name": "Jane Doe",
"variables": {
"firstName": "Jane",
"orderNumber": "ORD-12345"
}
}
],
"subject": "Your order #{{orderNumber}} has shipped",
"htmlContent": "<h1>Hi {{firstName}},</h1><p>Your order #{{orderNumber}} is on its way.</p>",
"textContent": "Hi {{firstName}}, Your order #{{orderNumber}} is on its way.",
"replyTo": "[email protected]",
"tags": ["order-shipped", "transactional"],
"customHeaders": {
"X-Entity-Ref-ID": "order-12345"
},
"tracking": {
"opens": true,
"clicks": true
},
"priority": "High",
"idempotencyKey": "order-12345-shipped-v1"
}مرجع الحقول
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
from | object | نعم | عنوان المُرسِل |
from.email | string | نعم | بريد المُرسِل الإلكتروني (يجب أن يكون على نطاق موثَّق) |
from.name | string | لا | الاسم المعروض |
to | array | نعم | قائمة المستلمين |
to[].email | string | نعم | عنوان البريد الإلكتروني للمستلم |
to[].name | string | لا | الاسم المعروض للمستلم |
to[].variables | object | لا | متغيرات القالب الخاصة بكل مستلم |
subject | string | مشروط | مطلوب ما لم يُستخدم قالب |
templateId | string | لا | استخدام قالب مخزَّن بدلاً من المحتوى المضمَّن |
htmlContent | string | مشروط | نص HTML (إذا لم يكن هناك templateId، يلزم htmlContent أو textContent) |
textContent | string | لا | النص العادي الاحتياطي |
variables | object | لا | متغيرات القالب العامة. تُطبَّق سواء استُخدم templateId أم لا؛ وعند تكرار المفتاح، تفوز قيمة to[].variables الخاصة بالمستلم |
replyTo | string | لا | عنوان البريد الإلكتروني للرد |
tags | array | لا | علامات للتصفية في التحليلات والخطافات |
customHeaders | object | لا | رؤوس بريد إلكتروني مخصصة (أزواج مفتاح-قيمة) |
tracking | object | لا | تجاوز إعدادات التتبع |
tracking.opens | boolean | لا | طلب تتبع الفتح لهذه الرسالة (الافتراضي: متوقف في النوعين). يُستخدم فقط ما دام نطاق الإرسال لم يختر بعد؛ اختيار النطاق نفسه لكل نوع، من صفحة النطاقات، هو الذي يسري. false يوقفه دائمًا |
tracking.clicks | boolean | لا | تفعيل تتبع النقر (الافتراضي: false للرسائل التعاملية ما لم يفعّله حسابك، وtrue للتسويق) |
ipPoolId | string | لا | محجوز لمجمّعات IP المخصّصة. غير متاح بعد: إرساله يُرجع 400 IP_POOL_NOT_FOUND. يُحذف. |
scheduledAt | datetime | لا | جدولة للتسليم المستقبلي (UTC)، بحد أقصى 7 أيام مقدَّماً |
idempotencyKey | string | لا | منع الإرسال المكرر لنفس المفتاح. يُفضّل استخدام ترويسة X-Idempotency-Key |
attachments | array | لا | مرفقات الملفات (بحد أقصى 10، وبحد أقصى 10 ميجابايت إجمالي بعد فك الترميز) |
priority | enum | لا | Low أو Normal (الافتراضي) أو High أو Critical |
المرفقات
يتطلب كل مرفق ثلاثة حقول:
{
"attachments": [
{
"fileName": "invoice.pdf",
"contentType": "application/pdf",
"content": "JVBERi0xLjQKJ...",
"inline": false
},
{
"fileName": "logo.png",
"contentType": "image/png",
"content": "iVBORw0KGgoAAAA...",
"contentId": "company-logo",
"inline": true
}
]
}| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
fileName | string | نعم | اسم الملف مع الامتداد |
contentType | string | نعم | نوع MIME (مثلاً application/pdf) |
content | string | نعم | محتوى الملف بترميز Base64 قياسي: مع الحشو (padding) وبدون مسافات أو فواصل أسطر |
contentId | string | لا | معرّف المحتوى للمرفقات المضمَّنة (يُشار إليه في HTML بـ cid:company-logo) |
inline | boolean | لا | هل هذه صورة مضمَّنة (الافتراضي: false) |
بحد أقصى 10 مرفقات لكل بريد إلكتروني، وبحد أقصى 10 ميجابايت إجمالي بعد فك الترميز (Base64). عدم وجود contentType، أو ترميز Base64 غير قياسي، أو تجاوز العدد أو الحجم المسموح به، يُرجع 400 VALIDATION_FAILED. لا يحتوي POST /v1/transactional/send-batch على حقل attachments.
الاستجابة
الحالة: 202 Accepted
{
"success": true,
"jobId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"messageIds": ["t_a1b2c3d4e5f6..."],
"acceptedRecipients": ["[email protected]"],
"rejectedRecipients": [],
"queuedAt": "2026-02-17T10:30:00Z",
"isSandboxed": false
}| الحقل | النوع | الوصف |
|---|---|---|
success | boolean | هل تم قبول الطلب |
jobId | string | معرّف المهمة الفريد للتتبع |
messageIds | array | معرّفات الرسائل لكل مستلم (البادئة t_ للتحويلية، m_ للتسويقية) |
acceptedRecipients | array | عناوين البريد الإلكتروني المقبولة للتسليم |
rejectedRecipients | array | المستلمون الذين تم رفضهم |
queuedAt | datetime | وقت وضع البريد الإلكتروني في قائمة الانتظار |
isSandboxed | boolean | true إذا استخدم الطلب بيانات اعتماد sandbox (انظر وضع Sandbox) |
sandboxReason | string | credential_sandbox_mode (سُجّلت ولم تُسلَّم) أو all_recipients_not_in_sandbox_allowlist (لم يكن أي مستلم في قائمة السماح)؛ وغائب في الحالات الأخرى |
المستلمون المرفوضون
يمكن رفض المستلمين لعدة أسباب:
{
"success": true,
"jobId": "...",
"acceptedRecipients": ["[email protected]"],
"rejectedRecipients": [
{
"email": "[email protected]",
"reason": "Suppressed"
},
{
"email": "[email protected]",
"reason": "domain_typo",
"suggestion": "[email protected]"
}
]
}أسباب الرفض الشائعة:
Suppressed: العنوان موجود في قائمة القمع (ارتدادات أو شكاوى سابقة)disposable_domain: تم اكتشاف مزود بريد إلكتروني مؤقتdomain_typo: خطأ مطبعي محتمل في النطاق (يتضمن حقلsuggestion)
الفحص المسبق
تحقق من قدرتك على الإرسال قبل تقديم الطلب الفعلي:
GET https://api.mail.land/v1/transactional/send/check?recipientCount=1curl https://api.mail.land/v1/transactional/send/check?recipientCount=1 \
-H "X-API-Key: ml_pet_Ab3Kx9mN2pQ7rT4wL8yD..."{
"canSend": true,
"rateLimitStatus": {
"currentSecond": 2,
"limitPerSecond": 50,
"currentHour": 450,
"limitPerHour": 5000,
"currentDay": 8200,
"limitPerDay": 50000
},
"monthlyUsed": 125000,
"monthlyLimit": 500000
}إذا كان canSend يساوي false، يوضح حقل reason السبب (حد المعدل أو الحصة أو حالة الحساب وما إلى ذلك).
قابلية التكرار (Idempotency)
إعادة محاولة الإرسال بعد انتهاء مهلة الشبكة يجب ألا تُسلّم البريد مرتين. عند تمرير مفتاح تكرار، تُعيد المحاولة الاستجابة الأصلية بدلاً من الإرسال من جديد.
أرسل المفتاح كترويسة (مستحسن):
X-Idempotency-Key: order-12345-shipped-v1أو استخدم الحقل idempotencyKey في الجسم. كلاهما مقبول، ويمكن إرسالهما معاً فقط إذا تطابقت القيمتان.
القواعد
- النطاق. تُقبل
X-Idempotency-KeyعلىPOST /v1/transactional/sendوPOST /v1/transactional/send-batchفقط، ولا تقرأها أي نقطة نهاية أخرى. - الصيغة. من 1 إلى 255 محرفاً: حروف وأرقام و
_و-. تُقارن المفاتيح تماماً دون اقتطاع أو توحيد لحالة الأحرف. - النافذة. يبقى المفتاح قابلاً للتكرار 24 ساعة، وبعدها يُعامل المفتاح نفسه كطلب جديد.
- التكرار. إعادة المحاولة ضمن النافذة تُعيد الاستجابة الأصلية حرفياً، الأرقام نفسها والحالة نفسها، ولا تُرسل شيئاً.
- التفرّد. المفاتيح فريدة لكل حساب. إعادة استخدام مفتاح لنقطة نهاية مختلفة تُرفض بالرمز
409؛ استخدم مفتاحاً مستقلاً لكل عملية.
معرّف الارتباط
تتبع الطلبات عبر الأنظمة بتضمين معرّف ارتباط:
X-Correlation-ID: my-app-order-12345أو
X-Request-ID: my-app-order-12345يظهر معرّف الارتباط في السجلات وسجل النشاط.
رؤوس حد المعدل
تتضمن الاستجابات الناجحة معلومات حد المعدل لكل عنوان IP:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 295عند تطبيق محرك سياسة الإرسال لحد المعدل (429)، يشير رأس Retry-After إلى ثواني الانتظار:
Retry-After: 30يمكن أن يتضمن الطلب التعاملي ما يصل إلى 5 مستلمين، ويُحتسب كل منهم ضمن حدود المعدل لديك. إذا تجاوز ذلك حدّك في الثانية (مثلًا 1 في الثانية في خطة بمعدل 60 في الدقيقة)، يُقبل الطلب عندما لا يكون أي طلب آخر قد قُبل في الثانية نفسها؛ وإلا فإنه يتلقى 429 مع Retry-After: 1 وينجح عند إعادة المحاولة في الثانية التالية، ضمن حدّك في الدقيقة. انظر حدود المعدل.
تتضمن استجابة 429 على مستوى IP أيضاً X-RateLimit-Reset كوقت UTC بصيغة ISO-8601.
استجابات الأخطاء
تُرجع جميع الأخطاء نصاً بتنسيق JSON:
{
"code": "ERROR_CODE",
"message": "Human-readable description",
"timestamp": "2026-02-17T10:30:00Z",
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}رموز الأخطاء
| الحالة | الرمز | الوصف |
|---|---|---|
400 | INVALID_REQUEST | نص طلب مشوَّه، أو scheduledAt أبعد من 7 أيام ("لا يمكن جدولة البريد لأكثر من 7 أيام مقدَّماً") |
400 | VALIDATION_FAILED | لا يوجد htmlContent أو textContent أو templateId؛ أو فشل مرفق في التحقق (راجع حدود المرفقات أعلاه). يتضمن الرد مصفوفة errors[] مع الحقل والقاعدة المخالفة. (سابقاً: MISSING_CONTENT: مهمل منذ 2026-04.) |
413 | CONTENT_TOO_LARGE | "The message is too large to send: it would exceed the platform's message-size limit. Reduce the HTML, text, attachments or recipients.": الرسالة تتجاوز حد حجم الرسائل في المنصة. تُعيدها POST /v1/transactional/send وsend-batch بالرمز 413؛ ولا يوضع شيء في الطابور. قلّص الرسالة. وفي استيراد CSV يكون الرمز 400 |
400 | transactional_recipient_limit_exceeded | أكثر من 5 مستلمين على بيانات اعتماد معاملاتية (1000 في التسويق) |
400 | TEMPLATE_NOT_FOUND | لا يوجد لدى templateId قالب نشط في هذا الحساب (يُرجع أيضاً لقالب محذوف) |
400 | IP_POOL_NOT_FOUND | لا يوجد لدى ipPoolId مجمّع مخصَّص لهذا الحساب (حالياً دائماً، لأنه لا يمكن تخصيص مجمّع بعد، راجع مرجع الحقول أعلاه) |
422 | TEMPLATE_VARIABLE_MISSING | يحتوي المحتوى على {{placeholder}} بلا قيمة؛ تسرد details.missingVariables الأسماء. لا يوضع شيء في الطابور |
400 | IDEMPOTENCY_KEY_INVALID | المفتاح فارغ أو غير صالح أو يتجاوز 255 محرفاً، أو أُرسلت الترويسة أكثر من مرة |
400 | IDEMPOTENCY_KEY_CONFLICT | أُرسلت الترويسة وحقل idempotencyKey معاً وقيمتاهما مختلفتان |
400 | SEND_FAILED | جميع المستلمين مقموعون (الرسالة: "All recipients are suppressed") |
409 | IDEMPOTENCY_KEY_REUSED | المفتاح مستخدم بالفعل لنقطة نهاية مختلفة في هذا الحساب |
401 | UNAUTHORIZED | X-API-Key مفقود أو غير صالح أو منتهي الصلاحية أو مُلغى |
403 | ACCOUNT_SUSPENDED | تم تعليق الحساب |
403 | ACCOUNT_DISABLED | تم تعطيل الحساب |
403 | ACCOUNT_NOT_ACTIVE | الحساب غير نشط |
403 | NO_ACTIVE_SUBSCRIPTION | لا يوجد اشتراك نشط للحساب |
403 | SUBSCRIPTION_EXPIRED | انتهى اشتراك الحساب |
403 | IP_NOT_ALLOWED | عنوان IP للطلب ليس في القائمة المسموح بها لبيانات الاعتماد |
403 | SENDING_BLOCKED | الإرسال محظور لهذا الحساب |
403 | ACTION_REQUIRED | يلزم اتخاذ إجراء على الحساب قبل الإرسال |
403 | TENANT_APPROVAL_REQUIRED | الحساب بانتظار المراجعة قبل أن يتمكن من الإرسال. إعادة المحاولة لا تفيد؛ تواصل مع الدعم |
422 | DOMAIN_NOT_VERIFIED | نطاق المُرسِل غير موثَّق |
422 | DOMAIN_NOT_ALLOWED_FOR_CREDENTIAL | النطاق ليس ضمن نطاق بيانات الاعتماد |
422 | DOMAIN_NOT_FOUND | نطاق المُرسِل غير موجود |
429 | RATE_LIMIT_EXCEEDED | تم تجاوز حد المعدل |
429 | QUOTA_EXCEEDED | استُنفدت الحصة الشهرية |
429 | WARMUP_LIMIT_EXCEEDED | بلغ حساب الحد اليومي لمرحلة تهيئة الإرسال؛ يُعاد ضبطه عند 00:00 UTC |
429 | DAILY_LIMIT_EXCEEDED | تم بلوغ حد الإرسال اليومي |
429 | WARMUP_POOL_BUDGET_EXCEEDED | "Sending is temporarily paused for today. It resumes automatically at 00:00 UTC; no action is needed." / "Sending is briefly delayed. Please retry in a few minutes." |
429 | WARMUP_POOL_EMPTY | "Sending is temporarily paused. It resumes automatically; no action is needed." |
429 | PLATFORM_DAILY_CAPACITY_REACHED | "Platform sending capacity for today is fully booked. This is a temporary platform-wide limit, not your account quota, and it resets at midnight UTC." |
429 | PLATFORM_CAPACITY_PROTECTION | "New sending is briefly paused to protect platform capacity. Mail already accepted is not affected. This is transient and clears on its own; retry shortly." |
429 | PROBATION_CAP_REACHED | "New accounts can send to N recipients per rolling 24 hours until our team has reviewed the account. Capacity returns as earlier sends age out of the 24-hour window; contact support to request a review." |
429 | PAYMENT_DAILY_LIMIT_EXCEEDED | تم بلوغ الحد اليومي لحساب متأخر السداد |
429 | MARKETING_PAUSED | تم إيقاف إرسال التسويق مؤقتاً لهذا الحساب |
429 | SENDING_BLOCKED | مستوى توثيق الحساب لا يسمح بهذا الإرسال (رفض متعلق بالـsandbox/مستوى التوثيق؛ أما الحظر الصارم للإرسال فيُرجع 403 بدلاً من ذلك، راجع أعلاه) |
503 | SERVICE_UNAVAILABLE | خدمة البريد الإلكتروني غير متاحة مؤقتاً |
حد المستلمين للتحويلية
تفرض بيانات الاعتماد التحويلية حداً أقصى قدره 5 مستلمين لكل طلب إرسال. هذا يمنع إساءة استخدام تدفقات التحويلية للإرسال الجماعي. إذا كنت تحتاج إلى مستلمين أكثر، استخدم بيانات اعتماد التسويق مع الإرسال الجماعي.
استخدام القوالب
بدلاً من HTML المضمَّن، أشر إلى قالب مخزَّن:
{
"from": { "email": "[email protected]" },
"to": [
{
"email": "[email protected]",
"variables": {
"firstName": "Jane",
"resetLink": "https://app.example.com/reset?token=abc123"
}
}
],
"templateId": "t8x2m4q9zk7wpr",
"variables": {
"companyName": "Acme Inc"
}
}يأتي subject من القالب. عند تكرار المفاتيح، تفوز قيمة to[].variables الخاصة بالمستلم على variables العامة، نفس قاعدة المحتوى المضمَّن. راجع القوالب لإنشاء القوالب وإدارتها.
الخطوات التالية
- الإرسال الجماعي: الإرسال إلى مستلمين متعددين دفعة واحدة
- مرحّل SMTP: الإرسال عبر SMTP بدلاً من REST
- القوالب: إنشاء قوالب بريد إلكتروني قابلة لإعادة الاستخدام
- رسائل البريد الإلكتروني المجدولة: جدولة رسائل البريد الإلكتروني للتسليم المستقبلي