DM Champ Docs

واجهة برمجة التطبيقات (API) للوكالات

بصفتك وكالة، يمكنك استخدام نفس REST API الذي يستخدمه عملاؤك، ولكن يمكنك توجيه الطلبات الفردية إلى أحد الحسابات الفرعية التي تديرها بدلاً من حسابك الخاص. يتيح لك هذا بناء أدوات تقوم بتهيئة العميل من البداية إلى النهاية — إنشاء حملاتهم، وتدريب ذكائهم الاصطناعي على قاعدة معرفية، واستيراد جهات اتصالهم، وربط قنوات المراسلة الخاصة بهم، وشراء أرقام هواتف — كل ذلك دون الحاجة إلى تسجيل الدخول إلى كل حساب فرعي يدويًا.

تغطي هذه الصفحة السلوك الخاص بالوكالة فقط: كيفية التصرف نيابة عن حساب فرعي باستخدام المعامل sub_account_id. للاطلاع على الأساسيات (إنشاء مفتاح، المصادقة، عنوان URL الأساسي، تنسيق الخطأ، حدود المعدل)، ابدأ بدليل الوصول إلى واجهة برمجة التطبيقات. كل ما ورد هناك ينطبق هنا أيضاً — حيث تقوم بالمصادقة باستخدام مفتاح واجهة برمجة التطبيقات الخاص بحساب وكالتك.

ملاحظة: هذه الصفحة تقنية. إذا لم تكن مطوراً، شاركها مع الشخص الذي يقوم ببناء التكامل الخاص بك.


كيف يعمل “التصرف نيابة عن”

بشكل افتراضي، يعمل كل طلب لواجهة برمجة التطبيقات على الحساب الذي يمتلك مفتاح واجهة برمجة التطبيقات — وهو حساب وكالتك. للتصرف نيابة عن حساب عميل مُدار بدلاً من ذلك، أضف المعامل الاختياري sub_account_id إلى الطلب، وقم بتعيينه على معرف حساب ذلك العميل.

  • حذف sub_account_id ← يعمل الطلب على حساب وكالتك الخاص.
  • تضمين sub_account_id ← يعمل الطلب على ذلك الحساب الفرعي، ولكن فقط بعد أن تؤكد المنصة أن الحساب الفرعي يخصك بالفعل.

أنت تقوم دائماً بالمصادقة باستخدام مفتاح واجهة برمجة التطبيقات الخاص بحساب وكالتك. لا تحتاج أبداً إلى مفتاح الحساب الفرعي الخاص، ولا تتعامل أبداً مع بيانات اعتماد الحساب الفرعي.

أين تضعه

  • نقاط نهاية GET / DELETE → مررها كمعامل استعلام: ?sub_account_id=THE_SUB_ACCOUNT_ID (إلى جانب apiKey الخاص بك، إذا كنت تقوم بالمصادقة عبر الاستعلام).
  • نقاط نهاية POST / PUT / PATCH → قم بتضمينها في نص طلب JSON كـ "sub_account_id": "THE_SUB_ACCOUNT_ID".
  • مساعدو الذكاء الاصطناعي → لا يوجد شيء يحتاج إلى تهيئة. يحمل خادم MCP نفس الإعداد في أدوات القراءة الخاصة به، لذا يمكن لاتصال واحد باستخدام مفتاح الوكالة الخاص بك تقديم تقارير عن كل عميل: ما عليك سوى ذكر اسم العميل في طلبك (“كم عدد جهات الاتصال لدى Bella’s Bistro؟”). إجراءات الكتابة متاحة أيضاً: كل نقطة نهاية تقبل sub_account_id يتم عرضها كأداة، لذا يمكنك الإنشاء والتغيير والإرسال نيابة عن العميل من نفس الاتصال.

العثور على معرف الحساب الفرعي

يُعد sub_account_id المعرف الفريد لحساب العميل. يمكنك الحصول على قائمة الحسابات الفرعية الخاصة بك ومعرفاتها من نقاط نهاية واجهة برمجة تطبيقات SubAccounts (راجع دليل الحسابات الفرعية) أو من صفحة الحسابات الفرعية في الشريط الجانبي.


يتم التحقق من الملكية دائماً

عند تمرير sub_account_id، تتحقق المنصة من أن الحساب هو حساب فرعي حقيقي و أنه ينتمي إلى وكالتك. عندها فقط يتم تنفيذ الطلب.

إذا كان المعرف غير معروف، أو لم يكن حساباً فرعياً، أو ينتمي إلى وكالة أخرى، يفشل الطلب مع استجابة 404:

{
  "success": false,
  "error_code": 404,
  "error": "Sub-account not found."
}

لماذا 404 وليس 403؟ إن استجابة “ممنوع” (forbidden) ستخبر الطرف الخارجي بأن المعرف (id) موجود ولكنه لا يخصه. إرجاع نفس 404 لكل من “غير موجود” و"لا يخصك" يعني أنه لا يمكن استخدام نقطة النهاية لاكتشاف معرفات الحسابات التي تنتمي إلى وكالات أخرى. تعامل مع 404 هنا على أنه “هذا ليس حساباً فرعياً تديره”.


أين يتم دعم sub_account_id

يتم قبول sub_account_id في كل نقطة نهاية للموارد تقريبًا — أي استدعاء يقوم بإنشاء أو قراءة أو تحديث أو حذف بيانات الحساب نفسه. من الناحية العملية، يمكنك توفير وتشغيل إعدادات الحساب الفرعي بالكامل باستخدام مفتاح الوكالة الخاص بك:

  • إعداد الذكاء الاصطناعي — الحملات، الوكلاء، الأسئلة الشائعة، مصادر القاعدة المعرفية (زحف الموقع الإلكتروني و تحميل المستندات)، مجموعات القاعدة المعرفية، البث، الوظائف المخصصة، خوادم MCP
  • جهات الاتصال وإدارة علاقات العملاء (CRM) — جهات الاتصال (بما في ذلك الاستيراد)، القوائم، العلامات، المهام، الصفقات، المواعيد، الأحداث
  • القنوات والأرقام — ربط WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE، البحث عن / شراء / إدارة أرقام الهواتف، قوالب WhatsApp، توجيه القنوات
  • المراسلة والمحتوى — إرسال الرسائل، جلسات الدردشة، تصدير الدردشات، الملخصات اليومية
  • الإعدادات والتكاملات — خطافات الويب (webhooks)، تكوين أداة الدردشة، تكوين العلامة البيضاء (white-label)، رسائل SMS الخاصة بك (BYOK) وإعدادات الحساب الأخرى، التحليلات

في كل واحدة من هذه الحالات، يكون المعامل اختياريًا — اتركه فارغًا وسيعمل الاستدعاء على حساب الوكالة الخاص بك، بحيث يخدم تكامل واحد كلا الطرفين. يتم خصم الأرصدة والاستخدام دائمًا من الحساب الذي تستهدفه: الرسوم الخاصة بحملات الحساب الفرعي، والرسائل، والعلامات، والأرقام يتم خصمها من رصيد الحساب الفرعي.

الحالات التي لا ينطبق فيها ذلك

بعض نقاط النهاية تكون على مستوى الوكالة أو موجهة للذات وتتجاهل sub_account_id:

  • إدارة الحسابات الفرعية نفسها — نقاط نهاية الحسابات الفرعية (إنشاء / سرد / تحديث حساب فرعي) ونقطة نهاية حد الإنفاق الخاص بـ BYOK تسمي بالفعل الحساب الفرعي في مسار URL الخاص بها. تتبع نقاط نهاية التسعير والسياسة ونقاط نهاية مراقبة الدردشة النمط نفسه.
  • نسخ وكيل (Agent) بين الحسابات — تقوم POST /v1/subaccounts/agents/copy بتسمية كلا الحسابين، حيث تأخذ الوجهة كـ targetUserId. انظر المثال العملي أدناه. (تعمل POST /v1/subaccounts/campaigns/copy الأقدم بنفس الطريقة ولكن تم إيقافها مع بقية واجهة برمجة تطبيقات الحملات.)
  • تعديل الأرصدة، وعمليات التجميع على مستوى الوكالة — تحدد POST /v1/subaccounts/credits الحساب الفرعي بواسطة email بدلاً من ذلك؛ بينما تقوم GET /v1/subaccounts/credit-usage و GET /v1/subaccounts/campaign-status بإعداد تقارير عن كل حساب فرعي في وقت واحد، لذا لا يوجد حساب واحد للاستهداف.
  • حساب وكالتك الخاص — إدارة مفاتيح API، وإعداد تقارير استخدام الوكالة، وإدارة الفريق، ومستويات التسعير الخاصة بك تعمل دائمًا على حساب وكالتك.
  • خطافات الويب للرسائل الواردة — نقاط النهاية التي تنشر فيها الأنظمة الخارجية إلى مرتبطة بالحساب الذي قامت بيانات اعتماده بتهيئتها، لذا لا يوجد شيء لإعادة توجيهه.

القائمة المحدثة دائمًا والقابلة للقراءة آليًا للمعلمات التي تقبلها كل نقطة نهاية موجودة في مرجع واجهة برمجة التطبيقات الخاص بلوحة التحكم (الإعدادات ← عمليات التكامل ← مفتاح واجهة برمجة التطبيقات) ومواصفات OpenAPI على GET /v1/docs/openapi.yaml. نحن نصدر تغييرات واجهة برمجة التطبيقات بشكل متكرر - تعامل معها كمصدر أساسي للمعلومات.

صفحة إعدادات مفتاح API مع مفتاح مخفي وعنصر تحكم إعادة التوليد

الإعدادات ← عمليات التكامل ← مفتاح API — مفتاح وكالتك موجود هنا، بجانب رابط مرجع API الكامل.


مثال عملي: ربط Instagram و Messenger لحساب فرعي

يعد ربط Instagram و Messenger تدفقاً يعتمد على المتصفح. تبدأ العملية باستخدام API، ثم تسلم رابط الموافقة الذي تم إرجاعه للعميل (أو تفتحه له)، وتنتظر حتى يقوم بالتفويض في متصفحه، ثم تختار الصفحة التي تريد ربطها — كل ذلك أثناء استهداف حسابه الفرعي باستخدام sub_account_id.

الخطوة 1 — بدء الاتصال

استدعِ نقطة نهاية الاتصال مع sub_account_id الخاص بالعميل في body. لا يتم إرسال أي بيانات اعتماد هنا؛ تُرجع المنصة رابط موافقة يجب على العميل فتحه في المتصفح، بالإضافة إلى رمز ارتباط (correlation token) لمرة واحدة.

cURL

curl -X POST "https://api.dmchamp.com/v1/channels/meta/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sub_account_id": "abc123def456"
  }'

JavaScript

const res = await fetch("https://api.dmchamp.com/v1/channels/meta/connect", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();
// data.oauth_url -> open this in the client's browser

Python

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/channels/meta/connect",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "sub_account_id": "abc123def456",
    },
)

data = res.json()
# data["oauth_url"] -> open this in the client's browser

الاستجابة:

{
  "success": true,
  "oauth_url": "https://www.facebook.com/v21.0/dialog/oauth?client_id=...&state=...",
  "state_token": "8sFq2yV0kQ7m4n1pZr3tWb6cXe9hJl2aD5gK7uN0oI",
  "expires_at": "2026-06-10T12:30:00.000Z"
}

أرسل العميل إلى oauth_url في المتصفح للتفويض. يقوم state_token بربط هذه المحاولة وهو سر قصير الأجل — لا تقم بتسجيله. تنتهي صلاحية المحاولة في expires_at؛ إذا انقضت، ابدأ من جديد.

الخطوة 2 — الاستطلاع (Polling) حتى تحميل الصفحات

بعد أن يقوم العميل بالتفويض، قم باستطلاع نقطة نهاية الحالة (باستخدام نفس sub_account_id، هذه المرة كمعامل استعلام) حتى تظهر الصفحات القابلة للاتصال.

cURL

curl "https://api.dmchamp.com/v1/channels/meta/status?apiKey=YOUR_API_KEY&sub_account_id=abc123def456"

JavaScript

const res = await fetch(
  "https://api.dmchamp.com/v1/channels/meta/status?sub_account_id=abc123def456",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);

const data = await res.json();
// Wait until data.status === "pages_loaded", then read data.pages

Python

import requests

res = requests.get(
    "https://api.dmchamp.com/v1/channels/meta/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"sub_account_id": "abc123def456"},
)

data = res.json()
# Wait until data["status"] == "pages_loaded", then read data["pages"]

الاستجابة:

{
  "success": true,
  "status": "pages_loaded",
  "pages": [
    {
      "id": "1098765432101234",
      "name": "Acme Studio",
      "category": "Hair Salon",
      "instagram_business_account": {
        "id": "17841400000000000",
        "username": "acme.studio"
      }
    }
  ],
  "selected_page": null
}

ينتقل الحقل status عبر pendingtoken_receivedpages_loadedconnected. انتظر pages_loaded قبل اختيار صفحة. يمكن أن تظهر حالتا خطأ نهائيتان أيضًا بدلاً من التقدم: failed و expired (رفض العميل الموافقة، أو انقضاء نافذة رمز الحالة التي تبلغ حوالي 30 دقيقة) — يتم تضمين حقل reason عند حدوث أي منهما. توقف عن الاستطلاع وأعد البدء من الخطوة 1 إذا رأيت إحداهما؛ لا تنتظر pending إلى الأبد. لا يتم إرجاع رموز وصول الصفحة مطلقًا.

الخطوة 3 — اختر الصفحة المراد توصيلها

اختر أحد معرفات الصفحات من الخطوة 2 وقم بتحديده. يؤدي اختيار صفحة إلى توصيل كل من Instagram وMessenger لتلك الصفحة. قم بتضمين sub_account_id في النص الأساسي (body) مرة أخرى.

cURL

curl -X POST "https://api.dmchamp.com/v1/channels/meta/select-page?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "page_id": "1098765432101234",
    "sub_account_id": "abc123def456"
  }'

JavaScript

const res = await fetch("https://api.dmchamp.com/v1/channels/meta/select-page", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    page_id: "1098765432101234",
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();

Python

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/channels/meta/select-page",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "page_id": "1098765432101234",
        "sub_account_id": "abc123def456",
    },
)

data = res.json()

الاستجابة:

{
  "success": true,
  "page_id": "1098765432101234",
  "instagram_business_account_id": "17841400000000000"
}

هذا كل شيء — تم الآن توصيل Instagram وMessenger في الحساب الفرعي للعميل. لقد قمت فقط بتوفير page_id؛ يتم حل بيانات الاعتماد الأساسية على الخادم ولا يتم تمريرها مطلقاً عبر تكاملك.


مثال عملي: شراء رقم لحساب فرعي

يعمل شراء رقم بنفس الطريقة: ابحث باستخدام sub_account_id في الاستعلام، ثم قم بالشراء باستخدامه في النص الأساسي. يتم خصم الرصيد من رصيد الحساب الفرعي، ويتم توفير الرقم على الحساب الفرعي.

البحث (cURL):

curl "https://api.dmchamp.com/v1/phone-numbers/available?apiKey=YOUR_API_KEY&country_code=US&sub_account_id=abc123def456"

الشراء (JavaScript):

const res = await fetch("https://api.dmchamp.com/v1/phone-numbers", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phone_number: "+14155551234",
    country_code: "US",
    display_name: "Support line",
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();

الشراء (Python):

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/phone-numbers",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "phone_number": "+14155551234",
        "country_code": "US",
        "display_name": "Support line",
        "sub_account_id": "abc123def456",
    },
)

data = res.json()

الاستجابة:

{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "whatsapp_status": "PURCHASED",
  "outgoing_status": "PURCHASED",
  "status": "PURCHASED",
  "purchase_credits": 11.5,
  "monthly_credits": 11.5
}

يتم توفير الرقم في حالة PURCHASED ويستمر تسجيل مرسل WhatsApp في الخلفية. استطلع GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 حتى تصل الحالة إلى ONLINE قبل الإرسال.


مثال عملي: إرسال وكيل (Agent) نموذجي إلى كل عميل جديد

النمط المعتاد للوكالة هو الاحتفاظ بوكيل رئيسي واحد في حساب وكالتك، مضبوطًا بالطريقة التي تريد أن يبدأ بها كل عميل، ونسخه إلى كل حساب فرعي جديد في وقت التزويد. هذه ثلاث استدعاءات، ولا يحتاج أي شيء إلى التكرار بعد ذلك: تحتفظ النسخة بإعداداتها حتى تقوم بتغييرها.

الخطوة 1 — نسخ الوكيل (Agent)

POST /v1/subaccounts/agents/copy

curl -X POST "https://api.dmchamp.com/v1/subaccounts/agents/copy?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "YOUR_TEMPLATE_AGENT_ID",
    "targetUserId": "abc123def456",
    "newName": "Inbound Instagram Leads",
    "copyFaqs": true
  }'

تحمل الاستجابة معرف الوكيل الجديد في data.agent_id. يتم نقل الأسئلة الشائعة وقاعدة المعرفة ومكتبة الوسائط؛ بينما لا يتم نقل قوالب WhatsApp الخاصة بالحساب المصدر، والمنشورات الاجتماعية المتصلة، وجهات الاتصال بشكل متعمد. قائمة الحقول الكاملة موجودة في واجهة برمجة تطبيقات وكلاء الذكاء الاصطناعي.

لاحظ أن نقطة النهاية هذه تأخذ targetUserId بدلاً من sub_account_id — فهي تحدد كلا الحسابين بنفسها. الاستدعاءان أدناه يستخدمان المعامل sub_account_id العادي.

الخطوة 2 — تشغيله

تصل النسخة دائمًا وهي متوقفة مؤقتًا، لذا لا يمكنها مراسلة أي شخص حتى تأمرها بذلك. هذه أيضًا هي اللحظة المناسبة لتثبيت مستوى الذكاء الاصطناعي الذي تريد أن يكون العميل عليه؛ حيث يبقى هناك، لذا لا حاجة لإعادة تطبيقه وفق جدول زمني.

curl -X PATCH "https://api.dmchamp.com/v1/agents/NEW_AGENT_ID/active?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'

curl -X PUT "https://api.dmchamp.com/v1/agents/NEW_AGENT_ID?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "anthropic_model": "max" }'

لمنع العميل من تغيير المستوى بعد ذلك، قم بقفل المستويات المسموح بها في الحساب الفرعي بدلاً من إعادة إرسال القيمة.

الخطوة 3 — توجيه قنوات العميل إليها

تصل النسخة بدون توجيه أيضًا، لذا لا يصلها أي شيء حتى تجعلها هي المجيب على القنوات التي قام العميل بتوصيلها. استدعاء واحد لكل قناة:

curl -X PUT "https://api.dmchamp.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "instagram", "agent_id": "NEW_AGENT_ID" }'

من هنا، يتم التقاط رسالة لأول مرة من جهة اتصال غير معروفة على تلك القناة بواسطة الوكيل المنسوخ تلقائيًا. انظر توجيه قناة إلى وكيل لمعرفة القنوات الأخرى والتوجيه لكل رقم.

قم بتعيين المنطقة الزمنية للعميل عند إنشاء الحساب الفرعي. مرر time_zone_id في POST /v1/subaccounts. يتم تقييم ساعات نشاط الحملة في المنطقة الزمنية الخاصة بالحساب الفرعي، لذا فإن العميل الذي يتم إنشاؤه بدون منطقة زمنية تتم قراءة جدولته مقابل التوقيت العالمي المنسق (UTC) — وهو ما يتغير بهدوء عندما يُسمح للمساعد بالرد.


تخطي معالج الإعداد لعميل تقوم بتهيئة حسابه بنفسك

POST /v1/subaccounts

بشكل افتراضي، في المرة الأولى التي يسجل فيها مالك حساب فرعي جديد دخوله، يتم توجيهه عبر معالج الإعداد الموجه. بالنسبة للعملاء الذين تقدم لهم الخدمة بالكامل — حيث تقوم ببناء الحملة وربط القنوات قبل أن يسجل العميل دخوله لأول مرة — قم بتمرير guided_onboarding: false عند إنشاء الحساب. سينتقلون إلى لوحة التحكم مباشرة، وسيتم إخفاء عنصر معالج الإعداد من الشريط الجانبي الخاص بهم.

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "first_name": "Alex",
    "last_name": "Client",
    "business_name": "Client Co",
    "guided_onboarding": false,
    "usage_limits": { "monthly_credits": 500 }
  }'

احذف الحقل (أو أرسل true) وسيعمل المعالج تمامًا كما كان دائمًا، لذا لا تحتاج عمليات التكامل الحالية إلى أي تغيير. لإعادة المعالج إلى العميل لاحقًا، أعد إظهار عنصر guided_onboarding باستخدام PUT /v1/subaccounts/{subAccountUid}/menu-visibility (أدناه) — تتحكم رؤية القائمة في ما إذا كان المعالج قابلاً للوصول، بينما يتحكم guided_onboarding فقط في إعادة التوجيه عند تسجيل الدخول لأول مرة.


إيقاف المهام أو الملخصات اليومية أو مكتبة الوسائط لعميل ما

POST /v1/subaccounts

يتم تفعيل هذه الميزات الثلاث لكل عميل جديد ما لم تحدد خلاف ذلك، وهي تعمل بشكل مختلف عن أي ميزة أخرى في هذا الدليل: فهي تعتمد على إلغاء الاشتراك (opt-out) وليس الانضمام (opt-in). لا يكفي استبعادها من features بمفرده، لأن قائمة features الخاصة بتكامل قديم لم تكن تذكرها ببساطة — فلا يمكننا التمييز بين “الوكالة أوقفت هذا” وبين “هذه القائمة كُتبت قبل وجود هذا الخيار”.

لذا، صرّح بذلك صراحةً باستخدام feature_settings:

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "first_name": "Alex",
    "last_name": "Client",
    "business_name": "Client Co",
    "feature_settings": {
      "tasks": false,
      "daily_summaries": false,
      "ai_media_library": true
    }
  }'

كل مفتاح اختياري؛ أي شيء تستبعده يظل مفعلاً. مع tasks: false يتوقف الذكاء الاصطناعي عن إنشاء مهام لذلك العميل ولن يتم إرسال رسائل بريد إلكتروني بعنوان “تم إنشاء مهمة جديدة”؛ ومع daily_summaries: false لن يتم إنشاء الملخص الليلي أو إرساله عبر البريد الإلكتروني.

يعد feature_settings هو الشيء الوحيد الذي يوقف هذه الميزات الثلاث عند الإنشاء. استبعادها من features لا يؤدي إلى أي شيء بمفرده، بغض النظر عما تبدو عليه بقية قائمتك — وهذا مقصود، حتى لا يفقد تكامل قديم هذه الميزات الثلاث بصمت.

لتغيير أي من هذا لاحقاً، أرسل قائمة features الكاملة إلى PUT /v1/subaccounts/{subAccountUid}/features — هناك، وجود الميزة في القائمة يؤدي إلى تفعيلها، وغيابها يؤدي إلى إيقافها.


تسجيل دخول عملائك تلقائياً إلى حساباتهم الفرعية (SSO)

POST /v1/subaccounts/{subAccountUid}/sso-link

طلب واحد باستخدام مفتاح API الخاص بوكالتك يُرجع رابطاً جاهزاً للفتح يقوم بتسجيل دخول العميل مباشرة إلى حسابه الفرعي الخاص — بدون شاشة تسجيل دخول، وبدون خطوة كلمة مرور، ولا شيء إضافي لبنائه. يمكنك فتحه في علامة تبويب جديدة، أو كإعادة توجيه، أو داخل إطار iframe في منتجك الخاص.

الحقل مطلوب الوصف
redirect لا الصفحة داخل التطبيق التي تريد أن ينتهي العميل إليها، على سبيل المثال "/chats" أو "/agents". يتم إرجاعها كـ deep_link_url في الاستجابة.
app_base_url لا مضيف لوحة التحكم للرابط. يتم تعيينه افتراضيًا على نطاق تطبيقك ذي العلامة البيضاء (أو نطاق المنصة إذا لم يكن لديك أي منها). يجب أن يكون https.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/sso-link" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "redirect": "/chats" }'

الاستجابة

{
  "success": true,
  "url": "https://app.yourdomain.com/auth?redirect=%2Fchats#token=eyJhbGciOi…",
  "deep_link_url": "https://app.yourdomain.com/chats",
  "expires_at": "2026-07-22T15:04:05.000Z",
  "sub_account_uid": "SUB_ACCOUNT_UID"
}

كيفية استخدامه بشكل جيد:

  • قفزة واحدة. يؤدي فتح url إلى تسجيل دخول العميل ونقله مباشرة إلى صفحة redirect في لوحة التحكم — دون الحاجة إلى شاشة تسجيل دخول أو صفحة وسيطة. تشير deep_link_url إلى الوجهة نفسها، وذلك للمكاملين الذين يفضلون التنقل إلى إطار معين صراحةً بعد تسجيل الدخول؛ فبمجرد وجود الجلسة، يعمل أي مسار في لوحة التحكم ضمن سياق المتصفح هذا.
  • إنشاء عند الطلب، وفتح فوري. يحتوي الرابط على بيانات اعتماد تسجيل الدخول وتنتهي صلاحيته بعد ساعة تقريبًا. اطلبه من جانب الخادم في اللحظة التي ينقر فيها العميل، ولا تقم بتخزينه أو إرساله عبر البريد الإلكتروني أبدًا.
  • ينتقل رمز تسجيل الدخول في جزء الرابط (#…)، والذي لا ترسل المتصفحات محتواه إلى الخوادم أبدًا، كما تتم إزالته من شريط العنوان بمجرد استخدامه.
  • حساباتك الفرعية فقط. ترفض نقطة النهاية أي حساب لا تملكه وكالتك.
  • يعرض الرابط منتهي الصلاحية خطأً واضحًا مع مسار لإعادة المحاولة — قم بإنشاء رابط جديد.

إخفاء عناصر التنقل في حساب فرعي

PUT /v1/subaccounts/{subAccountUid}/menu-visibility

يتحكم في عناصر الشريط الجانبي والإعدادات التي يراها الحساب الفرعي — مفيد عند تضمين لوحة التحكم وتريد فقط إظهار الواجهات التي لا يغطيها منتجك بالفعل. أي شيء غير مدرج يظل مرئياً؛ أرسل null كقيمة كاملة لـ menuVisibility لإعادة تعيين كل شيء ليكون مرئياً. إخفاء عنصر يؤدي إلى إخفاء إدخال القائمة — قم بإقرانه بالميزات التي تمنحها للحساب الفرعي للتحكم الصارم.

cURL

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/menu-visibility" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "menuVisibility": {
      "side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
      "settings_nav": { "team": false }
    }
  }'

الاستجابة

{
  "success": true,
  "data": {
    "subAccountUid": "SUB_ACCOUNT_UID",
    "menuVisibility": {
      "side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
      "settings_nav": { "team": false }
    }
  }
}

تقبل side_nav هذه المفاتيح الـ 13، والتي تطابق أسماء عناصر الشريط الجانبي: Dashboard، وDailySummaries، وChats، وContacts، وDeals، وTasks، وAutomations، وCampaigns، وAppointments، وSettings، وHelp، وCreditsCounter (رصيد الائتمان المعروض في الشريط الجانبي) وguided_onboarding (معالج الإعداد). يتم قبول ثلاثة مفاتيح إضافية — AiInsights وSub Accounts وAgency Reselling — ولكنها لا تؤدي أي وظيفة: حيث كانت تنطبق فقط على لوحة التحكم الكلاسيكية التي تم إيقافها، لذا فإن تعيينها ليس له أي تأثير على حساباتك الفرعية. تعني المفاتيح المفقودة أنها مرئية؛ فعند تسجيل دخولك إلى الحساب الفرعي بنفسك، يتم عرض العناصر المخفية مؤقتًا حتى تتمكن دائمًا من تغيير الإعدادات مرة أخرى.

إخفاء صفحة من القائمة لا يمنح الوصول إليها أبداً. يحتاج Automations إلى منح ميزة automations على الحساب الفرعي — إذا قمت بضبط المفتاح على true بدونها، فلن تظهر الصفحة. يعمل Tasks و DailySummaries بطريقة معاكسة: فهما مفعلان لكل عميل ما لم تقم بإيقافهما (راجع إيقاف المهام أو الملخصات اليومية أو مكتبة الوسائط لعميل ما).


اختر أنواع القنوات التي يمكن للعميل الاتصال بها

PUT /v1/subaccounts/{subAccountUid}/features

مفاتيح أنواع القنوات (Channel Types) التي تراها في مستوى الخطة هي معرفات ميزات عادية، لذا يمكنك تعيينها لكل عميل من خلال واجهة برمجة التطبيقات (API) بدلاً من لوحة التحكم. هذه واحدة من نقاط النهاية التي تحدد الحساب الفرعي في عنوان URL الخاص بها، لذا فهي لا تتطلب sub_account_id.

معرف الميزة القناة
channel_chat_widget أداة دردشة الموقع الإلكتروني
channel_whatsapp_api واجهة برمجة تطبيقات واتساب للأعمال
channel_whatsapp_web واتساب ويب (رقم مرتبط برمز QR)
channel_instagram إنستغرام
channel_messenger فيسبوك ماسنجر
channel_telegram تيليجرام
channel_line لاين
channel_viber فايبر
channel_email صندوق بريد إلكتروني
channel_sms الرسائل القصيرة (SMS)
channel_imessage آي مسج (iMessage)
curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/features" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "features": [
      "channels_3",
      "channel_chat_widget",
      "channel_whatsapp_web",
      "channel_instagram",
      "image_understanding",
      "contact_tagging",
      "incoming_campaigns",
      "webhooks"
    ]
  }'

ثلاثة أمور يجب مراعاتها:

  • يحل الاستدعاء محل قائمة الميزات بالكامل. أرسل كل ميزة يجب أن يحتفظ بها العميل، وليس فقط تلك التي تقوم بتغييرها. تعمل نفس المعرفات كـ features في POST /v1/subaccounts عند إنشاء الحساب.
  • أنواع القنوات وعدد القنوات هما بوابتان منفصلتان، وكلاهما قابل للتطبيق. تتحكم channels_1 / channels_3 / channels_unlimited في عدد الاتصالات؛ بينما تتحكم معرفات channel_* في الأنواع المسموح بها. المثال أعلاه يعني “ما يصل إلى 3 اتصالات، وفقط أداة الدردشة، أو WhatsApp Web، أو Instagram”.
  • إرسال معرفات channel_* فارغة يعني عدم وجود قيود على القنوات. هذا هو السلوك الأصلي، ولهذا السبب لم يتأثر العملاء الحاليون عند إطلاق هذه الميزة. أرسل معرفاً واحداً أو أكثر وسيظهر كل شيء آخر كـ “مقفل” في صفحة قنوات العميل مع ملاحظة ترقية بدلاً من زر “اتصال”. ستستمر القنوات التي اتصل بها العميل بالفعل في العمل.

يتم تعيين قائمة القنوات على مستوى الخطة، بحيث يرثها كل عميل يشتري تلك الخطة، من خلال لوحة التحكم ضمن إعدادات خطة الوكالة الخاصة بك. تقوم نقطة النهاية هذه بتعيينها لحساب فرعي محدد.


تعيين حد دقيق لعدد أعضاء الفريق للعميل

PUT /v1/subaccounts/{subAccountUid}/limits

توفر ميزات team_seats_* خطوات متدرجة محددة مسبقاً فقط (3 / 5 / 10 / غير محدود). لمنح العميل عدداً دقيقاً من مقاعد الفريق — 2، 7، 15، أو أي رقم آخر — قم بتعيين usage_limits.team_seats_limit بدلاً من ذلك. يتفوق هذا الخيار على الإعدادات المسبقة، وتفرضه المنصة عند كل دعوة، أو إضافة مباشرة، أو قبول دعوة: بمجرد الوصول إلى الحد، يتم رفض الدعوات الإضافية من جانب الخادم.

  • العدد الصحيح الموجب هو الحد الأقصى الدقيق.
  • 0 يعني أن أعضاء الفريق غير مشمولين — لا يمكن للعميل دعوة أي شخص.
  • -1 يعني غير محدود.
  • null يمسح الحد المخصص ويعود إلى أي إعداد مسبق لـ team_seats_* موجود في قائمة الميزات.

خفض الحد لا يؤدي أبداً إلى إزالة أعضاء الفريق الحاليين؛ بل يمنع فقط إضافة أعضاء جدد.

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/limits" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "usageLimits": { "team_seats_limit": 7 }
  }'

يمكنك أيضاً تعيينها في وقت الإنشاء: تقبل POST /v1/subaccounts القيمة usage_limits.team_seats_limit بنفس الدلالات. لقراءة القيمة الحالية، قم بجلب الحساب الفرعي باستخدام GET /v1/subaccounts?email=... وانظر إلى usage_limits.team_seats_limit (في حال غيابها/null = الإعدادات المسبقة هي التي تقرر). تقوم نفس نقطة النهاية أيضاً بتحديث credits و monthly_credits و roll_over_to_next_month و rollover_cap_months و rollover_expiry_days و byok_monthly_limit_usd — أرسل فقط المفاتيح التي تريد تغييرها.

كيف يتفاعل هذا مع حدود المقاعد في خطط SaaS. يمكن لخطط SaaS الخاصة بك أن تحمل مخصصات مقاعد خاصة بها (يتم تعيينها في محرر الخطط — راجع مقاعد الفريق في خطة ما)، والتي يتم تطبيقها تلقائيًا عند اشتراك العميل. الحد الذي تعينه من خلال نقطة النهاية هذه يُحتسب كمنح يدوي: شراء خطة يستبدلها بمخصصات المقاعد الخاصة بالخطة نفسها (ذلك الشراء هو خيار خطة صريح)، ولكن التجديدات الشهرية التلقائية لا تتجاوز أبدًا الحد اليدوي — لذا فإن الاستثناء لمرة واحدة الذي تمنحه للعميل يستمر خلال دورة فوترته. مسح الحد اليدوي باستخدام null يعيد التحكم في الحقل إلى الخطة عند تجديدها التالي.

حدد ما يحمله العميل بين فترات التجديد. يوجد مفتاحان إضافيان من نوع usage_limits بجوار roll_over_to_next_month. كلاهما مقبول بواسطة POST /v1/subaccounts في وقت الإنشاء أيضاً، وتقوم null بمسح أي منهما.

المفتاح وظيفته
rollover_cap_months عدد أشهر المخصصات التي قد يحتفظ بها العميل. رقم من 0 إلى 120، الكسور مسموح بها (0.5 = نصف شهر). عند كل تجديد، يتم تقليص الرصيد غير المستخدم إلى ما لا يزيد عن هذا العدد مضروباً في المخصصات التي يمنحها ذلك التجديد، قبل إضافة الأرصدة الجديدة؛ 0 لا ترحل أي شيء.
rollover_expiry_days عدد صحيح من الأيام، من 1 إلى 3650. الأرصدة التي تُترك دون استخدام لهذه المدة يتم إسقاطها عند أول تجديد بعد وصولها إلى هذا العمر. يتم الخصم دائماً من الأرصدة الأقدم أولاً، لذا فإن العميل الذي ينفق مخصصاته كل شهر لا يفقد أي شيء أبداً.

إذا تُركت دون تعيين، يعود كلاهما إلى خطة العميل؛ القيمة المرسلة هنا تتفوق على قيمة الخطة. الأرصدة المتكررة فقط (المخصصات الشهرية وأرصدة الخطة) تخضع لها: عمليات الشحن الإضافي، وإعادة الشحن التلقائي، والإضافات لمرة واحدة لا يتم تحديد سقف لها أو تنتهي صلاحيتها أبداً. يتم تسجيل كل عملية تقليص في سجل رصيد العميل كـ تعديل رصيد سقف الترحيل أو تعديل رصيد الأرصدة منتهية الصلاحية ولا تُحتسب أبداً كاستخدام. المعادلات على مستوى الخطة هي rollover_cap_months و rollover_expiry_days في مستوى التسعير — راجع الحقول الموجودة في مستوى التسعير و تحديد سقف لما يتم ترحيله.


تعيين تسعير وسياسة الذكاء الاصطناعي لكل عميل

PUT /v1/subaccounts/{subAccountUid}/max-tier · /ai-tiers · /max-rate · /action-pricing · /insider-rate · /locked-bot-fields · /notifications · /zero-credit-reply

ثمانية مفاتيح إضافية لكل عميل، إلى جانب /limits و /features و /menu-visibility المذكورة أعلاه. يأخذ كل منها معرف uid الخاص بالحساب الفرعي في الرابط (بدون sub_account_id في نص الطلب/معاملات الاستعلام — الهدف محدد بالفعل في المسار) ويتم تحديد نطاقها بنفس الطريقة: مفتاح الوكالة الخاص بك، ويجب أن ينتمي الحساب الفرعي إلى وكالتك.

نماذج الذكاء الاصطناعي التي يمكن للعميل استخدامها

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/max-tier" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

{ "enabled": boolean } تتيح للعميل الاشتراك في (أو إلغاء الاشتراك من) مستوى Max AI — بنيتنا التحتية بالسعر المدرج للمنصة. يؤدي تشغيل هذا لعميل BYOK إلى تغيير تكلفة الذكاء الاصطناعي الخاصة به من “مجانية على مفتاحي الخاص” إلى “محملة على رصيد ائتماني الخاص بي”، لذا فهو قرار متعمد لكل عميل بدلاً من كونه إعداداً افتراضياً على مستوى الوكالة.

لتقييد المستويات التي يمكن لحملات العميل ووكلائه الاختيار من بينها (بدلاً من مجرد تقييد الحد الأقصى)، استخدم ai-tiers:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/ai-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "allowed_ai_tiers": ["standard", "economy"] }'

allowed_ai_tiers عبارة عن مصفوفة مستمدة من standard، وeconomy، وmax، وmini — وهي تحل محل قائمة السماح الخاصة بالعميل. أرسل null (أو []) لمسح القيد والسماح لهم باختيار أي مستوى. هذا الأمر مهم لأن الحساب الفرعي الذي يختار مستوى الذكاء الاصطناعي الخاص به يستهلك من رصيدك، لذا فهو الأداة للتحكم في النماذج التي يمكن لعميل إعادة البيع تحميلك تكاليفها.

رد مؤقت أثناء نفاد رصيد العميل

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/zero-credit-reply" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "message": "Thanks for your message, we will get back to you shortly." }'

عندما يكون رصيد العميل (أو مجمعك) فارغاً، لا يمكن للذكاء الاصطناعي الإجابة ولا يسمع جهة الاتصال أي شيء. مع enabled: true، يتلقى كل جهة اتصال تراسل أثناء فترة التوقف message مرة واحدة (بحد أقصى 500 حرف، يتم إرسالها كما هي على كل قناة)، ويقوم الذكاء الاصطناعي بالإجابة على تلك المحادثات فعلياً بمجرد عودة الرصيد. يقوم enabled: false بحفظ النص المرسل لاحقاً؛ بينما يقوم enabled: false بدون message بإزالة الإعداد. نفس المفتاح الموجود في رد مؤقت عند نفاد الرصيد في نافذة تعديل الحساب الفرعي — انظر رد مؤقت أثناء نفاد رصيد العميل.

ما يدفعه العميل مقابل كل إجراء ذكاء اصطناعي، وهامش ربح رسوم WhatsApp

طريقتان لتحديد السعر الموجه لعملائك، من الأبسط إلى الأكثر تفصيلاً:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/max-rate" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "rate": 0.35 }'

rate هو السعر بالرصيد الذي يستهلكه رصيد الحساب الفرعي الخاص بك لكل إجراء ذكاء اصطناعي من طراز Max — وهو هامش الربح الذي تضعه لعملائك فوق ما تدفعه مجموعتك فعلياً. يقوم null بمسح التجاوز وإعادة السعر إلى قائمة أسعار المنصة. يجب أن يكون السعر على الأقل مساوياً لتكلفة إجراء Max على مجموعتك (بحيث لا يمكنك أبداً تسعير خدمة لعميل بأقل من تكلفتك) وبحد أقصى 10 أرصدة؛ سيتم رفض أي طلب خارج هذا النطاق مع إظهار الحد الأدنى المحسوب في رسالة الخطأ.

للحصول على تسعير لكل نوع إجراء بدلاً من سعر ثابت واحد، استخدم action-pricing:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/action-pricing" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "actionPricing": {
      "AI_MESSAGE": 0.6,
      "CHAT_SUMMARY": 0.15,
      "wa_carrier_multiplier": null
    }
  }'

actionPricing عبارة عن دمج (MERGE) في خريطة العميل الحالية — المفتاح الذي لا تذكره يُترك كما كان، و null يقوم بإلغاء تعيين ذلك المفتاح وإعادته إلى قيمته الافتراضية. المفاتيح المعترف بها هي:

المفتاح الأسعار
AI_MESSAGE رد الذكاء الاصطناعي
AI_TOOL_USE استدعاء أداة الذكاء الاصطناعي
EVALUATION_CALL تمريرة تقييم الدردشة
INTERRUPTION_HANDLING التعامل مع مقاطعة في منتصف الرد
CONTACT_TAG وسم جهة اتصال مخصص بواسطة الذكاء الاصطناعي
CHAT_SUMMARY ملخص الدردشة
wa_carrier_multiplier مضاعف ترميز مطبق على كل رسوم واتساب غير المتعلقة بالذكاء الاصطناعي التي يدفعها العميل: إيجار الرقم الشهري، رسوم التوصيل عبر المسار المُدار، وتكاليف تمرير قوالب Meta/Twilio.

يجب أن تكون المعدلات لكل إجراء رقماً أكبر من 0 وحتى 10؛ يجب أن يكون wa_carrier_multiplier على الأقل 1 (لا يوجد خصم أقل من التكلفة) وحتى 10. إرسال مفتاح غير معروف، أو قيمة خارج النطاق، يؤدي إلى رفض الطلب بالكامل وتسمية كل مفتاح مخالف، لذا لا يمكن لخطأ مطبعي أن يحفظ بصمت سعراً لا يتم تطبيقه فعلياً.

إذا كنت عضواً في Champions Circle، فإن insider-rate يمرر معدل خصم 20% الخاص بـ Max/Lead Finder إلى عميل واحد بدلاً من تطبيقه على مستوى الوكالة بالكامل:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/insider-rate" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

يتطلب تفعيله أن يكون حساب وكالتك حاصلاً بالفعل على عضوية Circle؛ أما إيقاف تشغيله فلا يتطلب ذلك أبداً، لذا يمكن للعضو الذي انتهت عضويته دائماً إعادة العميل إلى الحالة السابقة.

قفل أقسام من دليل تشغيل العميل

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/locked-bot-fields" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "locked_bot_fields": ["instructions", "rules"] }'

locked_bot_fields عبارة عن مصفوفة مستمدة من instructions، goal، rules، personality، conclude_unless — وهي تحل محل قائمة العميل المقفلة. يتم رفض القسم المقفل من جانب الخادم إذا حاول الحساب الفرعي نفسه تغييره (مباشرة، أو عبر مفتاح API)، بينما لا يزال بإمكانك (عبر sub_account_id) وعرض مسؤول لوحة تحكم العميل تعديل أي شيء. أرسل null (أو []) لإلغاء قفل كل شيء. مفيد للعملاء الذين تقدم لهم خدمة متكاملة حيث تمتلك أنت دليل التشغيل ويتم تقييمك بناءً على النتيجة.

تعيين تفضيلات إشعارات العميل نيابة عنه

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/notifications" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "notifications": {
      "settings": {
        "credit_alerts": { "enabled": true, "channels": ["email", "in_app"] },
        "new_contacts": { "enabled": false }
      }
    }
  }'

notifications يحل محل مجموعة تفضيلات الإشعارات الكاملة للعميل (ليس دمجاً لكل مفتاح — أرسل كل فئة تريد الاحتفاظ بها، بما يتوافق مع كيفية حفظ صفحة إعدادات الحساب الفرعي لنفسها). تقبل كل فئة تحت settings قيمة enabled (منطقية) وما يصل إلى ثلاثة channels من email، in_app، webhook. أرسل null لإعادة التعيين إلى إعدادات المنصة الافتراضية.

تستجيب جميع نقاط النهاية السبع بـ { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } }، ويتم تسجيلها في سجل التدقيق مع القيمة قبل/بعد التعديل. الأخطاء الشائعة: 403 إذا لم يكن حسابك وكالة/مطور أو لم يكن الحساب الفرعي خاضعاً لإدارتك، 400 إذا لم يكن حساباً فرعياً للوكالة أو كانت القيمة خارج النطاق.


إيقاف عميل قام بتعليق اشتراكه

POST /v1/subaccounts/{subAccountUid}/pause · POST /v1/subaccounts/{subAccountUid}/unpause

عندما يقوم العميل بتعليق اشتراكه معك، قم بإيقاف حسابه مؤقتاً بدلاً من حذفه: سيتوقف كل ما يرسله على الفور — الرسائل الصادرة، والبث، وردود الذكاء الاصطناعي على جميع القنوات — وعندما يسجل الدخول، سيرى شاشة الحساب متوقف مؤقتاً (مع رسالتك الاختيارية) بدلاً من التطبيق. لا يتم حذف أو فصل أي شيء: الوكلاء، والحملات، والقنوات المتصلة، وجهات الاتصال، وسجل الدردشة، كلها تبقى كما هي تماماً، لذا فإن إلغاء الإيقاف يعيد العميل إلى النقطة التي توقف عندها بالضبط — دون الحاجة إلى إعادة الإعداد.

الحقل مطلوب الوصف
message لا يتم عرضه للعميل على شاشة القفل الخاصة به. اتركه فارغاً لاستخدام النص الافتراضي.
reason لا ملاحظة داخلية للوكالة يتم تخزينها مع الإيقاف وفي سجل التدقيق — لا يتم عرضها للعميل أبداً.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/pause" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Your account is on hold — contact us to reactivate it.", "reason": "Subscription suspended per client email" }'

الاستجابة

{
  "success": true,
  "data": {
    "subAccountUid": "SUB_ACCOUNT_UID",
    "paused": true,
    "level": "hard_blocked"
  }
}

عندما يعود العميل، فإن POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (بدون نص) يزيل القفل — وتستأنف عمليات الإرسال وردود الذكاء الاصطناعي على الفور.

جدير بالمعرفة:

  • إنها نفس حالة مفتاح التبديل “محظور نهائياً” (Hard blocked) في لوحة التحكم (حظر / إيقاف حساب فرعي) — العميل الذي يتم إيقافه عبر واجهة برمجة التطبيقات (API) يظهر كمحظور في لوحة التحكم والعكس صحيح، وإلغاء الإيقاف يزيل الحظر الموضوع من أي من الجانبين. يمكن قراءة الحالة الحالية من حقل agency_block في GET /v1/subaccounts (level من "none"، أو "soft_blocked" أو "hard_blocked").
  • كلا الاستدعاءين متماثلان (idempotent). إيقاف عميل متوقف بالفعل يقوم فقط بتحديث الرسالة والسبب والطابع الزمني؛ وإلغاء إيقاف عميل نشط لا يغير شيئاً.
  • لا يتم إرسال بريد إلكتروني للعميل تلقائياً — العديد من الوكالات تستخدم علامتها التجارية الخاصة (white-label)، لذا فإن إبلاغ العميل متروك لك.
  • فواتير DM Champ الخاصة بك لا تتأثر. إيقاف العميل يؤثر فقط على علاقتك به.
  • مساعدو الذكاء الاصطناعي يمكنهم القيام بذلك أيضاً: يوفر خادم MCP هذه النقاط النهائية كأدوات pause_subaccount و unpause_subaccount.

منح أو خصم الأرصدة مباشرة

POST /v1/subaccounts/credits

يضيف أو يزيل مبلغاً محدداً من الرصيد من رصيد حساب فرعي واحد — وهو المعادل البرمجي (API) لتعديل الرصيد اليدوي في لوحة التحكم. هذا تغيير لمرة واحدة في الرصيد، يختلف عن إعدادات monthly_credits و roll_over_to_next_month و rollover_cap_months و rollover_expiry_days المتكررة الموجودة في PUT /v1/subaccounts/{subAccountUid}/limits.

هذه هي نقطة النهاية الوحيدة في هذه الصفحة التي تحدد الحساب الفرعي عن طريق البريد الإلكتروني بدلاً من sub_account_id.

الحقل مطلوب الوصف
email نعم البريد الإلكتروني للحساب الفرعي، كما هو موجود تحت وكالتك.
amount نعم عدد غير صفري من الأرصدة. القيمة الموجبة تضيف، والسالبة تخصم.
description لا يظهر بجانب التعديل في سجل رصيد العميل. الافتراضي هو سطر عام “تم التعديل بواسطة الوكالة عبر API”.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/credits" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "client@example.com", "amount": 500, "description": "Q3 bonus credits" }'

الاستجابة

{
  "success": true,
  "data": {
    "email": "client@example.com",
    "previous_balance": 1200,
    "adjustment": 500,
    "new_balance": 1700
  }
}

يتم رفض أي amount سلبي من شأنه أن يجعل الرصيد أقل من الصفر مع 400، مما يخبرك بالرصيد المتاح والمبلغ الذي حاولت خصمه. إذا كان العميل يستخدم نظام فوترة Stripe الخاص به (وضع إعادة البيع)، فإن المبلغ المضاف يُحتسب أيضاً كأرصدة قام بشرائها، لذا فهو يبقى بعد إعادة التعيين الشهرية التالية بنفس الطريقة التي يعمل بها الشحن الحقيقي؛ أما في حالة العميل المخصص القياسي، فيتم التعامل معه كجزء من مخصصاته المتكررة بدلاً من ذلك. في كلتا الحالتين، هي إضافة لمرة واحدة، لذا فإن حد الترحيل أو تاريخ انتهاء الصلاحية المحدد للحساب (أو خطته) لا يقلصها أبداً — فقط المخصصات المتكررة وأرصدة الخطة تخضع لتلك القيود.


قراءة محادثات حساب فرعي

GET /v1/subaccounts/{subAccountUid}/chats · GET /v1/subaccounts/{subAccountUid}/chats/{contactId}/messages

تتيح لك إنشاء عرض مراقبة أو دعم لمحادثات العميل دون تسجيل الدخول إلى حسابه. ابدأ بسرد جهات الاتصال الخاصة به مع معاينة لأحدث رسالة، ثم اقرأ سجل الرسائل الكامل لجهة اتصال واحدة.

سرد جهات الاتصال

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
معامل الاستعلام مطلوب الوصف
pageSize لا عدد جهات الاتصال في كل صفحة. القيمة الافتراضية 25، والحد الأقصى 50.
lastActivityAt لا مؤشر الترقيم — مرر lastActivityAt الخاص بالصفحة السابقة للمتابعة.
searchQuery لا التصفية حسب اسم جهة الاتصال أو رقم الهاتف.

الاستجابة

{
  "success": true,
  "data": {
    "contacts": [
      {
        "contactId": "contact456",
        "firstName": "Jamie",
        "lastName": "Lee",
        "phoneNumber": "+14155551234",
        "email": "jamie@example.com",
        "channel": "whatsapp",
        "lastActivityAt": "2026-08-30T14:22:00.000Z",
        "lastMessage": { "body": "Thanks, that fixed it!", "direction": "inbound", "timestamp": "2026-08-30T14:22:00.000Z" },
        "isBotActive": true,
        "markChatClosed": false
      }
    ],
    "subAccountName": "Client Co",
    "subAccountEmail": "client@example.com",
    "hasMore": true,
    "lastActivityAt": "2026-08-30T14:22:00.000Z"
  }
}

يتم ترتيب جهات الاتصال حسب النشاط الأحدث أولاً. استمر في الترقيم باستخدام lastActivityAt طالما أن hasMore هو true.

قراءة رسائل جهة اتصال واحدة

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
معامل الاستعلام مطلوب الوصف
pageSize لا عدد الرسائل في كل صفحة. القيمة الافتراضية 30، والحد الأقصى 100.
beforeTimestamp لا مؤشر الترقيم — اجلب الرسائل الأقدم من طابع ISO الزمني هذا.

الاستجابة

{
  "success": true,
  "data": {
    "messages": [
      {
        "messageId": "msg789",
        "body": "Thanks, that fixed it!",
        "direction": "inbound",
        "timestamp": "2026-08-30T14:22:00.000Z",
        "status": "received",
        "channel": "whatsapp",
        "botReply": false,
        "mediaUrl": null,
        "mediaContentType": null,
        "name": "Jamie Lee",
        "role": null
      }
    ],
    "contactInfo": { "firstName": "Jamie", "lastName": "Lee", "phoneNumber": "+14155551234", "channel": "whatsapp" },
    "hasMore": false,
    "oldestTimestamp": "2026-08-30T14:22:00.000Z"
  }
}

تظهر الرسائل من الأحدث إلى الأقدم؛ تصفح السجل للخلف باستخدام beforeTimestamp.


قراءة استخدام الرصيد وحالة الحملة عبر محفظة عملائك

GET /v1/subaccounts/credit-usage · GET /v1/subaccounts/campaign-status

ملخصان بنمط لوحة التحكم لكل حساب فرعي تديره، وذلك لبناء تقارير الوكالة الخاصة بك بدلاً من النقر داخل كل عميل على حدة.

استخدام الرصيد

curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
معامل الاستعلام مطلوب الوصف
from / to نعم نطاق تاريخ ISO.
subAccountId لا اتركه فارغاً للحصول على ملخص على مستوى الوكالة، صف واحد لكل حساب فرعي. قم بتضمينه للتبديل إلى وضع التفاصيل: ملخص ذلك الحساب الفرعي بالإضافة إلى سجلات الاستخدام الخام والمقسمة إلى صفحات.
limitCount لا وضع التفاصيل فقط. القيمة الافتراضية 500، والحد الأقصى 2000.
startAfterTimestamp لا وضع التفاصيل فقط — مؤشر الترقيم.
{
  "success": true,
  "data": {
    "subAccounts": [
      {
        "subAccountId": "abc123def456",
        "subAccountName": "Client Co",
        "subAccountEmail": "client@example.com",
        "totalCreditsUsed": 842,
        "totalCostUsd": 3.15,
        "byReason": { "AI reply": 620, "Chat summary": 80 },
        "topCampaigns": [{ "campaignName": "Inbound Leads", "creditsUsed": 500 }]
      }
    ],
    "totals": { "totalCreditsUsed": 842, "totalCostUsd": 3.15, "totalRecords": 214 },
    "dateRange": { "from": "2026-08-01", "to": "2026-08-31" },
    "hasMore": false,
    "lastTimestamp": null
  }
}

مرر subAccountId وستحمل الاستجابة نفسها أيضاً records: رسوم فردية مع amount وreason وcampaignName وcontactName وtimestamp. العميل الذي ينفق باستخدام مفتاح BYOK الخاص به بدلاً من أرصدتك يتم حجب أرقام التكلفة/الرموز عنه (costsRedacted: true) — فهذه بيانات قياس تكلفة المنصة، وليست شيئاً يجب إظهاره لمشاهد إعادة البيع.

حالة الحملة

curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
معلمة الاستعلام مطلوبة الوصف
pageSize لا عدد الحسابات الفرعية في كل صفحة. القيمة الافتراضية 10، والحد الأقصى 50.
lastDocumentId لا مؤشر الترقيم (Pagination cursor).
searchQuery لا التصفية حسب اسم الحساب الفرعي أو البريد الإلكتروني.
{
  "success": true,
  "data": {
    "totalSubAccounts": 34,
    "subAccountsWithIssues": 3,
    "totalLiveCampaigns": 51,
    "totalPausedCampaigns": 6,
    "subAccounts": [
      {
        "userId": "abc123def456",
        "email": "client@example.com",
        "displayName": "Jamie Lee",
        "businessName": "Client Co",
        "totalCampaigns": 2,
        "liveCampaigns": 1,
        "pausedCampaigns": 1,
        "hasIssues": true,
        "issueDetails": ["1 campaign paused"],
        "lastCampaignActivity": "2026-08-29T09:00:00.000Z"
      }
    ],
    "hasMore": true,
    "lastDocumentId": "abc123def456",
    "pageSize": 20
  }
}

تُستخدم العلامة hasIssues / issueDetails لتحديد الحسابات الفرعية التي تستحق المراجعة — مثل حملة متوقفة مؤقتاً، أو حملة لم يتم توجيه أي قناة إليها، على سبيل المثال. استخدم هذا لبناء لوحة تحكم لفحص الحالة عبر كامل قائمة عملائك بدلاً من فتح حساب كل عميل لاكتشاف الحملات المتوقفة.

للحصول على بيانات المراسلات ونشاط الرصيد عبر جميع العملاء (سلسلة زمنية جاهزة للرسم البياني بدلاً من لقطة في لحظة زمنية معينة)، راجع GET /analytics/agency-rollup في دليل واجهة برمجة تطبيقات التحليلات (Analytics API).


شحن حساب عميل تم إعداده مسبقاً

PUT /v1/snapshots/default · POST /v1/snapshots/{snapshotId}/apply

تُعد اللقطة (snapshot) قالباً قابلاً لإعادة الاستخدام: وكيل ذكاء اصطناعي واحد أو أكثر بالإضافة إلى قاعدة معارفهم وأدواتهم ووسائطهم، يتم التقاطها من حسابك الخاص. هناك نقطتا نهاية تضعانها في تدفق التزويد الخاص بك.

تلقائي — كل عميل جديد يحصل عليها فور إنشائه. قم بتمييز لقطة كنقطة افتراضية مرة واحدة، وسيصل كل حساب تنشئه بعد ذلك وهي مثبتة فيه. يغطي هذا الحسابات التي يتم إنشاؤها من خلال POST /v1/subaccounts، والحسابات التي تنشئها في لوحة التحكم، والحسابات التي يتم إنشاؤها تلقائياً عندما يدفع العميل من خلال رابط الدفع الخاص بك.

أولاً، ابحث عن معرف اللقطة:

curl "https://api.dmchamp.com/v1/snapshots" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

ثم قم بتعيينها كافتراضية:

curl -X PUT "https://api.dmchamp.com/v1/snapshots/default" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "snapshot_id": "SNAPSHOT_ID" }'

هذا هو كل ما يتطلبه التكامل. أرسل {"snapshot_id": null} لإيقاف تشغيلها مرة أخرى. يمكنك القيام بنفس الشيء من لوحة التحكم بالنقر على النجمة في صفحة اللقطات (Snapshots).

لقراءة ما تم تمييزه بنجمة حالياً (على سبيل المثال، قبل أن يقرر برنامج التزويد ما إذا كان سيقوم بتعيين واحد)، تُرجع GET /v1/snapshots/default القيمة { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } } — أو null عندما لا يكون هناك شيء مميز بنجمة. تُرجع GET /v1/snapshots (المستخدمة للعثور على المعرف أعلاه) نفس default_snapshot_id إلى جانب مصفوفة snapshots الكاملة، لذا فإن معظم عمليات التكامل تحتاج فقط إلى هذا الاستدعاء. توجد حقول كائن اللقطة (Snapshot) الكاملة في دليل اللقطات.

عند الطلب — التثبيت في حساب واحد. مفيد لتهيئة عميل حالي، أو لمنح عميل قالباً ثانياً لاحقاً.

curl -X POST "https://api.dmchamp.com/v1/snapshots/SNAPSHOT_ID/apply" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sub_account_id": "SUB_ACCOUNT_UID" }'

احذف sub_account_id وسيتم تثبيتها في حساب الوكالة الخاص بك بدلاً من ذلك. مثل نقاط نهاية /subaccounts، تقوم هذه بتسمية الحساب المستهدف في المسار أو النص بدلاً من استخدام معامل sub_account_id العام.

أشياء تستحق المعرفة قبل البناء عليها:

  • الوكلاء المثبتون يبدأون في حالة إيقاف مؤقت. قم بتوصيل قنوات العميل أولاً، ثم قم بتنشيط الوكيل. هذا ينطبق على كل من المسار التلقائي والمسار عند الطلب.
  • التزويد لا يفشل أبداً بسبب لقطة. إذا تعذر إكمال التثبيت، فسيتم إنشاء حساب العميل ويظل قابلاً للاستخدام - سيصل فارغاً فقط ويمكنك تطبيق اللقطة لاحقاً.
  • لا يتم نسخ القنوات والتقويمات واتصالات OAuth أبداً. يقوم كل حساب بتوصيل اتصالاته الخاصة. الأدوات التي تستخدم مفتاح API بسيط تستمر في العمل فوراً.
  • التطبيق مرتين ينشئ نسخة ثانية. لا يتم استبدال أي شيء.

إنشاء القالب نفسه عبر واجهة برمجة التطبيقات (API)

POST /v1/snapshots · الوكلاء، والوظائف المخصصة، والوسائط عبر واجهة برمجة التطبيقات (API)

يوزع القسم أعلاه لقطة (snapshot) أنشأها شخص ما في لوحة التحكم. كما أن جانب التأليف متاح أيضاً، بحيث يمكن تشغيل الحلقة بأكملها — تجميع الإعداد الرئيسي مرة واحدة، والتقاطه، وتسليمه لكل عميل — من خلال الكود.

الأجزاء، بالترتيب الذي يستخدمها به برنامج التزويد:

  1. أنشئ وظائفك المخصصة. تقوم POST /v1/custom-functions بإنشاء واحدة؛ وتسرد GET /v1/custom-functions ما لديك، وتقوم GET و PUT و DELETE على /v1/custom-functions/{customFunctionId} بقراءة وتحديث وإزالة واحدة. تقوم POST /v1/custom-functions/test بتشغيل تجريبي للتعريف قبل حفظه.
  2. أنشئ الوكيل وقم بتشكيله. تقوم POST /v1/agents بإنشائه، وتقوم PUT /v1/agents/{agentId} بتحديثه، وتقوم PATCH /v1/agents/{agentId}/active مع { "active": false } بإبقائه متوقفاً مؤقتاً أثناء عملك (نفس الاستدعاء مع true يجعله مباشراً). تسرد GET /v1/agents هذه الوكلاء.
  3. امنح الوكيل قدراته. تقوم POST /v1/agents/{agentId}/custom-functions مع { "custom_function_id": "..." } بإرفاق وظيفة بالوكيل؛ وتقوم DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId} المطابقة بإلغاء إرفاقها.
  4. املأ مكتبة الوسائط. تقوم POST /v1/agents/{agentId}/media-library بتحميل عنصر (JSON مع base64Data و mimeType و title و description)؛ وتسرد GET عناصر الوكيل، وتقوم PATCH/DELETE على /{itemId} بتحديث أو إزالة أحدها.
  5. التقطه كلقطة (snapshot).
curl -X POST "https://api.dmchamp.com/v1/snapshots" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Master setup v1",
    "agent_ids": ["AGENT_ID"],
    "include_knowledge": true,
    "include_tools": true,
    "include_media": true
  }'

من هناك، نعود إلى القسم السابق: قم بتمييزه كافتراضي بحيث يولد كل عميل جديد به، أو قم بتطبيقه عند الطلب. توجد أدوات التنظيم جنباً إلى جنب: تقوم PATCH /v1/snapshots/{snapshotId} مع { "name": "..." } بإعادة تسمية واحدة، وتقوم DELETE /v1/snapshots/{snapshotId} بحذف واحدة (وإلغاء تمييزها إذا كانت هي الافتراضية)، وتسرد GET /v1/snapshots/apply-targets كل حساب يمكنك التثبيت فيه.

تقبل جميع نقاط نهاية الوكيل والوظائف المخصصة والوسائط sub_account_id، لذا يمكن لنفس الاستدعاءات أيضاً صيانة وكيل مباشرة داخل حساب عميل واحد. تعمل استدعاءات اللقطات (Snapshot) دائماً على حساب وكالتك — حيث يعيش القالب معك. توجد مخططات الطلب والاستجابة الكاملة لكل هذه العناصر في مرجع واجهة برمجة التطبيقات.


إدارة مستويات التسعير الخاصة بك عبر API

GET /v1/agency/pricing-tiers · POST /v1/agency/pricing-tiers · PATCH /v1/agency/pricing-tiers/{tierIndex} · DELETE /v1/agency/pricing-tiers/{tierIndex}

يمكن قراءة وتغيير الخطط التي تبيعها في وضع SaaS ← مستويات التسعير من خلال الكود، بحيث يمكن للوحة تحكم المسؤول الخاصة بك أو برنامج التزويد إضافة خطة، أو تعديل سعر، أو تقديم رابط دفع دون أن يضطر أي شخص لفتح لوحة التحكم. قم بالمصادقة باستخدام مفتاح API الخاص بوكالتك مثل أي استدعاء آخر في هذه الصفحة؛ نقاط النهاية هذه على مستوى الوكالة، لذا فهي لا تأخذ sub_account_id. كل عملية كتابة تقوم بتشغيل نفس التحقق ونفس مزامنة منتج وسعر Stripe مثل حفظ لوحة التحكم، لذا فإن الخطة التي يتم إنشاؤها هنا لا يمكن تمييزها عن تلك التي قمت بإعدادها يدويًا.

سرد مستوياتك

curl "https://api.dmchamp.com/v1/agency/pricing-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

الاستجابة

{
  "success": true,
  "data": {
    "tiers": [
      {
        "tierIndex": 0,
        "credits": 1000,
        "price_cents": 2900,
        "currency": "usd",
        "label": "Starter",
        "billing_interval": "month",
        "trial_days": 14,
        "trial_credits": 250,
        "trial_card_required": false,
        "trial_hard_expiry": true,
        "stripe_price_id": "price_1PxAbC…",
        "stripe_product_id": "prod_QxAbC…",
        "checkout_url": "https://app.yourdomain.com/v1/checkout?id=YOUR_AGENCY_UID&tierIndex=0"
      }
    ],
    "count": 1,
    "max_tiers": 20
  }
}

يتم إرجاع كل مستوى مع tierIndex الخاص به — موقعه في قائمة الخطط الخاصة بك، وهو ما تشير إليه المكالمات الثلاث الأخرى — و checkout_url جاهز للمشاركة، وهو نفس الرابط الذي تمنحه علامة التبويب المدفوعات، والذي يشير بالفعل إلى نطاق العلامة البيضاء الذي تُباع عليه تلك الخطة.

إضافة مستوى

الجسم عبارة عن كائن مستوى واحد؛ يتم إلحاقه بنهاية قائمتك.

curl -X POST "https://api.dmchamp.com/v1/agency/pricing-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Starter",
    "credits": 1000,
    "price_cents": 2900,
    "currency": "usd",
    "billing_interval": "month",
    "trial_days": 14,
    "trial_credits": 250,
    "trial_card_required": false,
    "trial_hard_expiry": true,
    "features": ["channels_3", "channel_whatsapp_web", "webhooks"]
  }'

تحمل الاستجابة المستوى الذي تم إنشاؤه، بما في ذلك tierIndex الذي استقر عليه و checkout_url الخاص به.

تحرير مستوى

أرسل فقط الحقول التي تريد تغييرها؛ يتم ترك كل شيء آخر في الخطة كما كان.

curl -X PATCH "https://api.dmchamp.com/v1/agency/pricing-tiers/0" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "price_cents": 3900, "trial_hard_expiry": true }'

يتم رفض الحقل الذي لا تتعرف عليه واجهة برمجة التطبيقات بدلاً من تجاهله، ويقوم الخطأ بتسميته — لذا لا يمكن لخطأ مطبعي أبدًا كتابة إعداد يبدو مباشرًا ولكنه لا يفعل شيئًا بهدوء. يؤدي تغيير السعر أو الأرصدة أو العملة أو وتيرة الفوترة إلى إنشاء سعر جديد في Stripe الخاص بك؛ يظل العملاء الذين اشتركوا بالفعل على ما اشتركوا فيه.

حذف مستوى

curl -X DELETE "https://api.dmchamp.com/v1/agency/pricing-tiers/2" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

نفس قاعدة لوحة التحكم: لا يمكن حذف خطة لا تزال تحتوي على مشتركين نشطين. يتم رفض الطلب، ويخبرك بعدد المشتركين الموجودين عليه — قم بإلغائهم أو ترحيلهم أولاً. يستجيب الحذف الناجح بمستوياتك المتبقية، والتي تمت إعادة ترقيمها بالفعل.

الحقول الموجودة في المستوى

الحقل ما هو
label / description اسم الخطة، والسطر الاختياري الذي يظهر في صفحة الدفع الخاصة بك.
credits الأرصدة التي يحصل عليها العميل شهرياً في الخطة الشهرية أو السنوية، ولكل فترة فوترة في الخطة الأسبوعية.
price_cents السعر لكل فترة فوترة، بأصغر وحدة عملة (2900 = 29.00 دولاراً). في الخطة السنوية، هذا هو سعر السنة بأكملها.
currency رمز ISO بأحرف صغيرة — usd، eur، gbp وما إلى ذلك.
billing_interval / billing_interval_count month (الافتراضي)، year، أو week مع عدد من 1–52 لـ “كل N أسبوع”.
trial_days مدة الفترة التجريبية المجانية، من 0 إلى 90. 0 (أو تركها فارغة) يعني عدم وجود فترة تجريبية.
trial_credits الأرصدة التي يبدأ بها العميل الفترة التجريبية. يتم تعيينها افتراضياً على credits الخاصة بالخطة.
trial_card_required يسمح false للعميل ببدء الفترة التجريبية دون إدخال بطاقة. يتم تعيينه افتراضياً على true.
trial_hard_expiry يقوم true بإعادة أرصدة الفترة التجريبية غير المستخدمة إلى مجمعك وقفل حساب العميل عند انتهاء الفترة التجريبية دون ترقية. يتم تعيينه افتراضياً على false — انظر انتهاء الصلاحية الصارم بعد الفترة التجريبية.
rollover_cap_months أشهر المخصصات التي يمكن للعملاء في هذه الخطة ترحيلها بين التجديدات — رقم من 0 إلى 120، الكسور مسموح بها. 0 لا يرحل شيئاً؛ null (الافتراضي) يعني عدم وجود حد أقصى. انظر تحديد ما يتم ترحيله.
rollover_expiry_days الأيام التي يتم بعدها إسقاط الأرصدة غير المستخدمة عند التجديد التالي — رقم صحيح من 1 إلى 3650. null (الافتراضي) يعني أنها لا تنتهي صلاحيتها أبداً.
features / feature_settings ما يحصل عليه العملاء في هذه الخطة — نفس معرفات الميزات الموجودة في اختر أنواع القنوات التي يمكن للعميل الاتصال بها.
team_seats_limit مقاعد الفريق التي تمنحها الخطة: رقم محدد، 0 لعدم وجود مقاعد، -1 لعدد غير محدود.
white_label_config أي من نطاقات العلامة البيضاء الخاصة بك يتم بيع الخطة عليها.

حقول الفترة التجريبية لا تعني شيئاً إلا في الخطة التي تحتوي على فترة تجريبية: احفظ مستوى بـ trial_days: 0 وسيتم إسقاطها. تتم إدارة معرفات منتج وسعر Stripe الخاصة بالخطة نيابة عنك ولا يمكن تعيينها يدوياً.

ثلاثة أمور يجب مراعاتها:

  • فهارس المستويات هي مواضع وليست معرفات دائمة. يؤدي حذف خطة إلى إزاحة كل خطة تليها بمقدار موضع واحد، لذا أعد جلب القائمة بعد أي تغيير — وأعد نسخ روابط الدفع التي نشرتها، تماماً كما تفعل بعد حذف خطة في لوحة التحكم.
  • يجب إعداد وضع SaaS أولاً. تتطلب نقاط النهاية هذه حساب وكالة مع ميزة العلامة البيضاء (white labeling) ومفتاح Stripe محفوظ مسبقاً؛ فبدون ذلك، لن يكون هناك حساب Stripe ليعيش عليه منتج الخطة وسعرها.
  • الحد الأقصى هو عشرون خطة، وهو نفس الحد الموجود في لوحة التحكم. يخبرك الحقل max_tiers في استجابة القائمة بالحد الحالي.

توجد مخططات الطلب والاستجابة الكاملة في مرجع API، تحت قسم الوكالة (Agency).


تعيين سعر الرصيد الخاص بك عبر واجهة برمجة التطبيقات (API)

GET /v1/agency/credit-price · PATCH /v1/agency/credit-price

يمكن قراءة وتغيير السعر الذي يدفعه العملاء مقابل عمليات الشحن المخصصة (وضع SaaS ← تسعير الرصيد) من خلال الكود أيضاً. تم تصميم هذه الميزة للحالات التي يتطلب فيها السعر التغيير تلقائياً: فمثلاً، يمكن لوكالة تبيع الأرصدة بعملة ما ولكنها تحاسب بعملة أخرى استخدام مهمة مجدولة لتعديل السعر مع تغير سعر الصرف، بدلاً من قيام شخص ما بتعديله يدوياً كل أسبوع.

قراءة السعر الحالي

curl "https://api.dmchamp.com/v1/agency/credit-price" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

الاستجابة

{
  "success": true,
  "data": {
    "price_per_credit_cents": 125,
    "price_per_credit_currency": "brl",
    "note": "USD 0.25 per credit at our reference rate",
    "minimum_cents": 60
  }
}

minimum_cents هو أقل سعر تسمح به المنصة بتلك العملة، لذا يمكن للمهمة التحقق من السعر الجديد قبل إرساله. تكون القيم الثلاث جميعها null حتى يتم تعيين سعر.

تغييره

curl -X PATCH "https://api.dmchamp.com/v1/agency/credit-price" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "price_per_credit_cents": 130, "currency": "brl" }'

أرسل فقط ما تريد تغييره. price_per_credit_cents هو السعر بأصغر وحدة عملة (130 = 1.30 ريال برازيلي)؛ currency هو رمز ISO بأحرف صغيرة؛ note هو سطر اختياري يصل إلى 200 حرف يظهر للعملاء مباشرة تحت سعر الرصيد في صفحة الفواتير الخاصة بهم — وهو مفيد للإشارة إلى سعر مرجعي بعملة أخرى، مثل “0.25 دولار أمريكي لكل رصيد بسعرنا المرجعي”. أرسل "note": "" لإزالته. الاستجابة لها نفس شكل القراءة أعلاه، لذا يمكن للمهمة المقارنة وتخطي الكتابة عندما لا يتغير شيء.

تطبق نفس القواعد الموجودة في لوحة التحكم: لا يمكن أن يقل السعر عن الحد الأدنى للمنصة لتلك العملة، ويحتاج الحساب إلى ميزة العلامة البيضاء (white labeling). على عكس نقاط نهاية مستويات التسعير، لا يلزم وجود مفتاح Stripe لقراءة هذه القيمة أو تغييرها.

امنح المهمة مفتاحاً لا يمكنه القيام بأي شيء آخر

إن وضع مفتاح الوكالة الكامل الخاص بك في مجدول مهام يمنح صلاحيات وصول أكثر مما يحتاجه تحديث السعر. بدلاً من ذلك، قم بإنشاء مفتاح محدد النطاق (scoped key) مقتصر على منطقة سعر رصيد الوكالة (Agency Credit Price): يمكن لهذا المفتاح قراءة وتغيير السعر لكل رصيد ولا شيء غير ذلك — فهو لا يمكنه الوصول إلى الحسابات الفرعية، أو الخطط، أو الأرصدة، أو اتصال Stripe الخاص بك.

curl -X POST "https://api.dmchamp.com/v1/api-keys" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "label": "FX price updater", "scopes": { "read_only": false, "tags": ["Agency Credit Price"] } }'

تحمل الاستجابة المفتاح الجديد في api_key مرة واحدة فقط — ولن يتم عرضه مرة أخرى، لذا قم بحفظه على الفور. قم بتعيين "read_only": true للمفتاح الذي يحتاج فقط إلى قراءة السعر، وأضف "expires_at" (تاريخ بتنسيق ISO) إذا كنت تريده أن يتوقف عن العمل تلقائياً. يمكن لمالك الحساب فقط إنشاء مفاتيح محددة النطاق؛ يمكنك سردها أو إلغاؤها باستخدام GET /v1/api-keys و DELETE /v1/api-keys/{id}.


السماح لحساب فرعي بقراءة أسعارك

GET /v1/subaccounts/agency-pricing

يتم استدعاء كل نقطة نهاية أخرى في هذه الصفحة باستخدام مفتاح الوكالة الخاص بك، مع استهداف عميل اختياريًا عبر sub_account_id. هذه النقطة هي العكس تمامًا: يتم استدعاؤها باستخدام مفتاح API الخاص بالحساب الفرعي، بدون sub_account_id، بحيث يمكن لصفحة تعبئة الرصيد الخاصة بالعميل (أو التكامل الذي تبنيه له) عرض ما تفرضه عليهم دون رؤية حساب الوكالة الخاص بك مطلقًا.

curl "https://api.dmchamp.com/v1/subaccounts/agency-pricing" \
  -H "X-API-Key: THE_SUB_ACCOUNTS_OWN_API_KEY"

الاستجابة

{
  "success": true,
  "data": {
    "tiers": [{ "credits": 1000, "price_cents": 2900, "currency": "usd" }],
    "price_per_credit_cents": 125,
    "price_per_credit_currency": "brl",
    "price_per_credit_note": "USD 0.25 per credit at our reference rate",
    "agency_display_name": "Client Co's Growth Partner"
  }
}

يعكس هذا تماماً ما تُرجعه GET /v1/agency/pricing-tiers و GET /v1/agency/credit-price لك كوكالة، مطروحاً منه أي شيء لا يحتاج العميل إلى رؤيته (معرفات Stripe، و max_tiers، وما إلى ذلك). يعمل هذا فقط مع حساب هو في الواقع حساب فرعي مرتبط بوكالة — استدعاؤه من حساب وكالتك الخاص يُرجع خطأ في الصلاحيات.


أمور يجب وضعها في الاعتبار

  • استخدم مفتاح الوكالة الخاص بك. قم بمصادقة كل استدعاء باستخدام مفتاح API الخاص بحساب الوكالة - وليس الحساب الفرعي. المعلمة sub_account_id هي التي توجه الإجراء.
  • تُخصم الأرصدة من الحساب الفرعي. تؤثر عمليات الشراء والرسوم المتكررة على رصيد الحساب الفرعي المستهدف، وليس رصيدك.
  • يعني الرمز 404 “ليس حسابك الفرعي”. تحقق جيداً من المعرف ومن أن الحساب هو أحد الحسابات التي تديرها.
  • المعلمة اختيارية في كل مكان تُقبل فيه. إذا حذفتها، سيعمل نفس نقطة النهاية على حساب الوكالة الخاص بك، مما يتيح لك إعادة استخدام تكامل واحد لكليهما.

ذات صلة