الفوترة
إدارة اشتراكك وعرض الفواتير ومراقبة الاستخدام
تستخدم MailLand Stripe لإدارة الاشتراكات والفوترة. تمتلك كل مساحة عمل اشتراكاً خاصاً بها مع تسعير مبني على الاستخدام أو قائم على الخطة. يمكن لأي عضو قراءة حالة الفوترة؛ يمكن فقط لمالك مساحة العمل تغييرها (تُرجع الاستدعاءات المُغيِّرة 403 INSUFFICIENT_PERMISSIONS، ومفاتيح API تُرفض دائماً في تلك النقاط).
حالات الدفع
paymentStatus تُعاد كسلسلة نصية بصيغة snake_case، وليست تعداداً رقمياً:
| الحالة | الوصف |
|---|---|
current | الاشتراك نشط، الدفع محدّث |
grace_period | فشل الدفع، فترة السماح نشطة |
overdue | الدفع متأخر، الميزات مقيّدة |
blocked | الحساب محظور بسبب عدم السداد |
الحصول على تفاصيل الاشتراك
GET https://api.mail.land/v1/account/subscriptioncurl https://api.mail.land/v1/account/subscription \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"planName": "Pro",
"monthlyEmailLimit": 100000,
"rateLimitPerSecond": 10,
"pricePerMonth": 49.00,
"startDate": "2026-01-15T08:00:00Z",
"endDate": "2026-03-01T00:00:00Z",
"status": "Active",
"paymentStatus": "current",
"marketingPausedDueToPayment": false,
"sendingBlockedDueToPayment": false,
"transactionalDailyLimit": 5000,
"daysUntilBlocked": null,
"cancelAtPeriodEnd": false,
"planFamilyId": "fam_pro",
"planTierPublicId": "tier_pro_monthly",
"usage": {
"emailsSentThisMonth": 45000,
"monthlyLimit": 100000,
"percentageUsed": 45.0,
"transactionalCount": 30000,
"marketingCount": 12000,
"apiCount": 40000,
"smtpCount": 5000,
"campaignCount": 3000,
"automationCount": 2000,
"inboundForwardCount": 500
}
}لا يوجد id أو planId أو interval أو currentPeriodStart/currentPeriodEnd، ولا حقول paymentStatus الرقمية أو عدادات استخدام التحقق/النطاقات/الفريق/الأتمتة في هذه الاستجابة، استخدم أسماء الحقول أعلاه. paymentStatus سلسلة نصية بصيغة snake_case: "current" أو "grace_period" أو "overdue" أو "blocked". status بصيغة PascalCase ("Active"، "Suspended"، "Cancelled"): الاستثناء الوحيد هو الاستجابة الاحتياطية عند عدم وجود اشتراك، والتي تُعيد "active" بحروف صغيرة.
حقول الاستخدام
| الحقل | الوصف |
|---|---|
emailsSentThisMonth | الرسائل المُرسَلة في دورة الفوترة الحالية |
monthlyLimit | الحد الأقصى للرسائل في كل دورة |
percentageUsed | نسبة emailsSentThisMonth من monthlyLimit |
transactionalCount | الرسائل المعاملاتية المُرسَلة |
marketingCount | الرسائل التسويقية المُرسَلة |
apiCount | الرسائل المُرسَلة عبر API |
smtpCount | الرسائل المُرسَلة عبر ترحيل SMTP |
campaignCount | الرسائل المُرسَلة بواسطة الحملات |
automationCount | الرسائل المُرسَلة بواسطة الأتمتة |
inboundForwardCount | الرسائل المُرسَلة بواسطة قواعد إعادة توجيه البريد الوارد |
لا توجد عدادات استخدام للتحقق أو النطاقات أو أعضاء الفريق أو الأتمتة في هذه الاستجابة، فقط عدادات إرسال البريد.
متى يتم احتساب استخدام البريد الإلكتروني
يُحتسب المستلمون ضمن استخدامك وحصتك (emailsSentThisMonth / monthlyLimit) في اللحظة التي يُسجَّل فيها القبول بشكل دائم. المستلمون المرفوضون أو المكبوتون قبل القبول لا يُحتسبون أبداً. أي ارتداد أو كبح لاحق أو فشل تسليم أو أي شكل آخر من عدم التسليم يحدث بعد القبول لا يُعيد أو يسترجع تلقائياً الاستخدام أو الحصة، لا يُعدَّل العدّ بأثر رجعي. يصف هذا القسم محاسبة الاستخدام فقط؛ ولا يُقرّ أو يُلمّح إلى تسعير Stripe لكل رسالة أو أي حق استرداد، فهذه أمور تحكمها شروط اشتراكك بشكل منفصل.
تُعاد الحصة إلى الصفر في كل دورة فوترة من Stripe للخطط المُفوترة عبرها، أو في اليوم الأول من كل شهر تقويمي بتوقيت UTC للخطط غير المُفوترة عبر Stripe (المجانية والخطط الممنوحة من المسؤول): وليست دائماً "لكل دورة" بمعنى Stripe.
الخطط والاحتفاظ بالبيانات
الخطط هي Free وPro وMax. تُحفظ سجلات الرسائل لمدة 30 يوماً في Free، و90 يوماً في Pro، و180 يوماً في Max.
ملخص السياسة
احصل على حالة التحقق من مساحة العمل وسياسة الإرسال:
GET https://api.mail.land/v1/account/subscription/policy-summarycurl https://api.mail.land/v1/account/subscription/policy-summary \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."الاستجابة كائن متداخل، وليست مسطحة (SubscriptionController.cs:137-200):
{
"subscription": {
"planFamilyId": "fam_pro",
"planFamilyName": "Pro",
"planTierId": "tier_pro_monthly",
"monthlyQuota": 100000,
"pricePerMonth": 49.00
},
"usage": {
"usedThisMonth": 45000,
"remainingThisMonth": 55000,
"percentUsed": 45.0
},
"effectiveRates": {
"transactionalRatePerMin": 600,
"marketingRatePerMin": 300,
"isOverridden": false
},
"domainWarmup": [
{
"domainId": "h4k7m1n9w2p5x8",
"domainName": "example.com",
"currentStage": 2,
"totalStages": 5,
"todaySentCount": 350,
"dailyLimit": 500,
"progressPercent": 70.0,
"completed": false,
"bypassed": false
}
],
"alerts": [
{
"type": "warning",
"code": "QUOTA_WARNING",
"message": "You have used 80% of your monthly quota. Consider upgrading your plan.",
"actionUrl": "/billing"
}
],
"dailySendingLimit": {
"limit": 5000,
"usedToday": 1200,
"remainingToday": 3800,
"resetsAt": "2026-02-18T00:00:00Z"
},
"verification": {
"level": 2,
"levelName": "SenderVerified",
"limits": {},
"progress": {},
"nextSteps": []
}
}| الحقل | الوصف |
|---|---|
subscription | عائلة الخطة، الفئة والحصة/السعر الشهري |
usage | الرسائل المستخدمة، المتبقية والنسبة المستخدمة هذا الشهر |
effectiveRates | معدلات الإرسال الفعلية في الدقيقة وما إذا كانت مُتجاوَزة |
domainWarmup | تقدم الإحماء لكل نطاق، مُدخل واحد لكل نطاق قيد الإحماء |
alerts | التنبيهات النشطة لهذه المساحة (الحصة، الحد اليومي، وما شابه) |
dailySendingLimit | الحد اليومي للإرسال والمساحة المتبقية، عند الانطباق |
verification | مستوى التحقق الحالي، حدوده، تقدمه والخطوات التالية |
إنشاء جلسة دفع
ابدأ جلسة Stripe Checkout للاشتراك أو الترقية:
POST https://api.mail.land/v1/account/billing/checkout{
"planTierId": "tier_pro_monthly",
"locale": "en",
"businessAttested": true,
"businessAttestationKey": "business-use-v3-button"
}| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
planTierId | string | نعم | المعرّف العام لمستوى الخطة |
locale | string | لا | لغة صفحة الدفع المستضافة |
businessAttested | boolean | نعم | تؤكد القيمة true أنك تشتري MailLand لاستخدام تجاري أو مهني (بما في ذلك العمل الحر أو النشاط الفردي أو موقعك الخاص). تُرسلها لوحة التحكم عبر زر الدفع: تسميته «Pay for business use» وتحته ملاحظة من سطر واحد توضح ما يؤكده النقر |
businessAttestationKey | string | نعم | إصدار الصياغة الذي يشير إليه التأكيد؛ حاليًا business-use-v3-button (ما زال business-use-v1، وهو الصياغة الأقدم، مقبولًا) |
يُرفض الطلب الذي لا يتضمن businessAttested: true ومفتاح businessAttestationKey مقبولًا برمز 400 BUSINESS_ATTESTATION_REQUIRED قبل خصم أي مبلغ. يحفظ MailLand من أكّد ومتى وبأي صياغة (المفتاح الذي أرسلته) وبأي لغة. في Stripe Checkout يمكنك إدخال رقم ضريبي؛ وهو اختياري. الأسعار لا تشمل ضريبة القيمة المضافة ولا يحصّل MailLand هذه الضريبة؛ ويضيف رقم ضريبة قيمة مضافة أوروبي تم التحقق منه خارج المملكة المتحدة ملاحظة الاحتساب العكسي إلى فواتيرك.
لا يوجد حقل successUrl أو cancelUrl: روابط النجاح/الإلغاء ليست مقدَّمة من المستدعي.
curl -X POST https://api.mail.land/v1/account/billing/checkout \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "planTierId": "tier_pro_monthly", "locale": "en", "businessAttested": true, "businessAttestationKey": "business-use-v3-button" }'{
"upgraded": false,
"sessionId": "cs_live_abc123...",
"url": "https://checkout.stripe.com/c/pay/cs_live_abc123..."
}أعد توجيه المستخدم إلى url لإتمام الدفع على صفحة دفع Stripe المستضافة. إذا كان لدى مساحة العمل بالفعل اشتراك نشط، يتغير الخطة في مكانها بدلاً من فتح جلسة دفع جديدة: تكون الاستجابة { "upgraded": true } بدون sessionId/url، ولا يوجد إعادة توجيه. لا تُعِد التوجيه إلا عندما تكون url موجودة.
بوابة الفوترة
افتح بوابة عملاء Stripe للإدارة الذاتية (تحديث طريقة الدفع، الإلغاء، عرض الفواتير):
POST https://api.mail.land/v1/account/billing/portal{
"locale": "en"
}locale اختياري.
curl -X POST https://api.mail.land/v1/account/billing/portal \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "locale": "en" }'{
"url": "https://billing.stripe.com/p/session/abc123..."
}أعد توجيه المستخدم إلى url للوصول إلى بوابة Stripe.
قائمة الفواتير
GET https://api.mail.land/v1/account/billing/invoices| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
limit | int | 20 | عدد الفواتير المُراد إرجاعها |
cursor | string | - | مؤشر غامق من nextCursor في استجابة سابقة |
curl https://api.mail.land/v1/account/billing/invoices \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"publicId": "inv_abc123",
"invoiceNumber": "INV-2026-0015",
"stripeInvoiceId": "in_1AbCdEfGhIjKlMn",
"status": "Paid",
"amountDue": 4900,
"amountPaid": 4900,
"currency": "eur",
"periodStart": "2026-01-01T00:00:00Z",
"periodEnd": "2026-02-01T00:00:00Z",
"paidAt": "2026-01-01T00:05:00Z",
"hostedInvoiceUrl": "https://pay.stripe.com/invoice/inv_abc123",
"invoicePdfUrl": "https://pay.stripe.com/invoice/inv_abc123/pdf",
"createdAt": "2026-01-01T00:00:00Z"
},
{
"publicId": "inv_def456",
"invoiceNumber": "INV-2026-0014",
"stripeInvoiceId": "in_2BcDeFgHiJkLmNo",
"status": "Paid",
"amountDue": 4900,
"amountPaid": 4900,
"currency": "eur",
"periodStart": "2025-12-01T00:00:00Z",
"periodEnd": "2026-01-01T00:00:00Z",
"paidAt": "2025-12-01T00:05:00Z",
"hostedInvoiceUrl": "https://pay.stripe.com/invoice/inv_def456",
"invoicePdfUrl": "https://pay.stripe.com/invoice/inv_def456/pdf",
"createdAt": "2025-12-01T00:00:00Z"
}
],
"nextCursor": null,
"hasMore": false
}هذه استجابة مقسّمة إلى صفحات بمؤشر (cursor)، وليست { "invoices": [...] }: مرر nextCursor كمعامل cursor للحصول على الصفحة التالية، وتوقف عندما تكون hasMore قيمتها false. حجم الصفحة الافتراضي هو 20 وليس 10؛ وأسماء الحقول هي invoiceNumber وamountDue وamountPaid وhostedInvoiceUrl وinvoicePdfUrl (وليست number أو amount أو invoiceUrl أو invoicePdf).
مبالغ الفواتير بأصغر وحدة من currency الخاصة بالفاتورة (السنت بالنسبة لليورو EUR). اقسم على 100 للعرض. أسعار الباقات باليورو (EUR) ولا تشمل ضريبة القيمة المضافة.
استجابات الخطأ
| الحالة | الرمز | الوصف |
|---|---|---|
400 | VALIDATION_FAILED | نص طلب غير صالح |
400 | INVALID_REQUEST | فئة الخطة موجودة لكنها غير متزامنة مع Stripe |
403 | INSUFFICIENT_PERMISSIONS | فقط مالك مساحة العمل يمكنه تنفيذ هذا التعديل (قراءة الفوترة متاحة لأي عضو) |
404 | RESOURCE_NOT_FOUND | فئة خطة غير معروفة أو غير نشطة |
502 | STRIPE_ERROR | فشل طلب Stripe |
نقاط نهاية أخرى للفوترة
متوفرة أيضاً، ولم يتم تفصيلها أعلاه: POST /v1/account/billing/cancel وPOST /v1/account/billing/reactivate والنقطة العامة GET /public/plans/catalog.
الخطوات التالية
- مساحات العمل: إدارة إعدادات مساحة العمل
- إدارة الفريق: إدارة أعضاء الفريق
- حدود المعدل: فهم حدود معدل API