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)، استخدام مفتاح API الخاص بك (BYOK) للرسائل القصيرة وإعدادات الحساب الأخرى، التحليلات، سجل الأخطاء

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

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

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

  • إدارة الحسابات الفرعية نفسها — نقاط نهاية الحسابات الفرعية (إنشاء / سرد / تحديث حساب فرعي) ونقطة نهاية حد الإنفاق BYOK تحدد بالفعل الحساب الفرعي في مسار URL الخاص بها. تتبع نقاط نهاية التسعير والسياسة ونقاط نهاية مراقبة الدردشة نفس النمط.
  • نسخ وكيل بين الحسابات — 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، وتقارير استخدام الوكالة، وإدارة الفريق، ومستويات التسعير الخاصة بك تعمل دائماً على حساب وكالتك.
  • إضافة جهات اتصال إلى قائمة أو إزالتها منها: POST / DELETE /v1/contacts/lists وPOST /v1/contacts/lists/batch تعمل على الحساب الذي يمتلك المفتاح. إن إنشاء القوائم نفسها وتحريرها وحذفها (/v1/lists) يتطلب sub_account_id.
  • خطافات الويب للرسائل الواردة — نقاط النهاية التي تنشر فيها الأنظمة الخارجية إلى الداخل مرتبطة بالحساب الذي قامت بيانات اعتماده بتكوينها، لذا لا يوجد شيء لإعادة توجيهه.

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

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

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


سرد الحسابات الفرعية الخاصة بك، أو التحقق من بريد إلكتروني واحد

GET /v1/subaccounts

عند استدعائها بدون معلمات، فإنها تُرجع كل حساب فرعي تابع لوكالتك في مصفوفة data. أضف معلمة الاستعلام الاختيارية email للبحث عن عميل واحد:

curl "https://api.dmchamp.com/v1/[email protected]&apiKey=YOUR_API_KEY"
  • إذا كان هذا البريد الإلكتروني ينتمي إلى أحد حساباتك الفرعية النشطة ← HTTP 200، مع ذلك الحساب فقط: { "success": true, "data": { ... } }.
  • إذا لم يكن كذلك ← HTTP 404، Agency Sub Account not found.

لا توجد معلمة تجيب بـ “نعم” أو “لا” بشكل مباشر، لذا اقرأ رمز الحالة: 200 يعني أن البريد الإلكتروني هو أحد عملائك، و 404 يعني أنه ليس كذلك. يتم استبعاد الحسابات الفرعية المحذوفة، لذا فإن الحساب الذي قمت بإزالته سيظهر أيضاً كـ 404.

يتم إرجاع كل حساب مع ملفه الشخصي، وإعداداته، وحدود استخدامه، والميزات التي تم تفعيلها فيه، وهو كل ما تحتاجه لعرض صف العميل في لوحة التحكم الخاصة بك.

لا تتضمن الاستجابة أبداً بيانات الاعتماد. تتم إزالة مفاتيح API، وكلمات المرور، ورموز تسجيل الدخول، وتفاصيل القنوات التي ربطها العميل (Twilio، وGoogle، وMeta، ومفاتيحك الخاصة) قبل إرسالها. لا توجد معلمة لاختيار الحقول التي تحصل عليها، لذا اقرأ الحقول التي تحتاجها وتجاهل الباقي.

يتطلب الوصول إلى API وحساب وكالة.


إنشاء حساب عميل

POST /v1/subaccounts

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

لا يمكنك اختيار كلمة المرور. لا يوجد حقل لكلمة المرور: يتم إنشاء واحدة لك وتسليمها مرة واحدة، كـ temporary_password في استجابة 201. قم بتخزينها أو تمريرها على الفور، لأنه لن يتم عرضها لك مرة أخرى. يمكن للعميل تغييرها من ملفه الشخصي، أو إعادة تعيينها من شاشة تسجيل الدخول.

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "first_name": "Alex",
    "last_name": "Client",
    "business_name": "Client Co",
    "send_account_info_to_sub_account": true
  }'

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

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

أرصدة الافتتاح متروكة لك لتعيينها. usage_limits.credits هو حد الإنفاق المبدئي للعميل و usage_limits.monthly_credits هو المخصص الشهري المتكرر. أرسل "credits": 0 وسيبدأ الحساب بدون رصيد للإنفاق؛ اترك credits فارغًا وسيبدأ برصيد أولي قدره 100 نقطة حتى يتمكن الذكاء الاصطناعي من الإجابة على الفور. لا يؤدي أي منهما إلى خصم أي شيء من رصيد وكالتك عند الإنشاء: يتم خصم الرصيد من حسابك فقط عندما يستخدم العميل النقاط فعليًا.

يجب أن تكون أسماء الأنشطة التجارية فريدة داخل وكالتك. لا يمكن لعميلين من عملائك أن يحملا اسم “Client Co”، لأن هذا الاسم هو ما يحدد الحساب عبر لوحة التحكم وتقاريرك. أسماء الوكالات الأخرى لا تؤثر في ذلك.

عند فشل الاستدعاء:

الحالة ماذا حدث
400 حقل مفقود أو خاطئ، أو البريد الإلكتروني ليس عنواناً صالحاً، أو المفتاح الذي استخدمته لا ينتمي إلى حساب وكالة.
401 مفتاح API خاطئ، أو منتهي الصلاحية، أو تم إلغاؤه.
402 اشتراكك الخاص غير نشط، لذا لا يمكن إنشاء حسابات عملاء جديدة حتى يتم تسوية فواتيرك.
403 لقد وصلت إلى عدد حسابات العملاء الذي تسمح به خطتك.
409 اسم النشاط التجاري هذا مستخدم بالفعل من قبل أحد عملائك، أو أن البريد الإلكتروني ينتمي بالفعل إلى حساب آخر.

حذف حساب عميل

DELETE /v1/[email protected] (أو ?uid=SUB_ACCOUNT_UID)

curl -X DELETE "https://api.dmchamp.com/v1/[email protected]" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

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

{
  "success": true,
  "message": "Sub-account deletion started",
  "data": { "uid": "SUB_ACCOUNT_UID", "email": "[email protected]", "status": "deletion_started" }
}
  • مرر email أو uid. إذا قمت بتمرير كليهما، فيجب أن يشيرا إلى نفس العميل.
  • لا يمكن حذف سوى عملائك الخاصين. أي بريد إلكتروني أو معرف مستخدم (uid) آخر، أو عميل تم حذفه بالفعل، سيؤدي إلى إرجاع 404.
  • استدعاء هذه الوظيفة مرة أخرى أثناء استمرار عملية الحذف سيؤدي إلى إرجاع 200 مع "status": "already_in_progress".
  • المساعدون المدعومون بالذكاء الاصطناعي المتصلون عبر خادم MCP لديهم هذه الأداة كأداة delete_subaccount عند الاتصال بعنوان MCP القياسي (يتم استبعاد أدوات الوكالة من عنوان MCP ذي العلامة البيضاء).
  • لإيقاف عميل مؤقتًا لفترة دون فقدان أي شيء، أوقفهم مؤقتًا بدلاً من ذلك: سيتم حظر دخولهم، ويتم الاحتفاظ بكل شيء، ويمكن استعادتهم بمكالمة واحدة.

مثال عملي: ربط 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 عبر pending ← token_received ← pages_loaded ← connected. انتظر 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

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

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "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": "[email protected]",
    "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, "Deals": false, "Automations": false },
      "settings_nav": { "team": false }
    }
  }'

الاستجابة

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

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

يأخذ نفس الكائن menuVisibility أيضاً حقلين اختياريين للوحة تحكم العميل الرئيسية. يقوم dashboard_widgets بتعيين معرف الأداة (widget id) إلى true (معروض) أو false (مخفي)، و dashboard_order عبارة عن قائمة بمعرفات الأدوات بالترتيب الذي يجب أن تظهر به. المعرفات، بترتيبها الافتراضي، هي kpis، و performance، و credits (استخدام الرصيد)، و funnel، و inbox، و outcomes، و channel_health، و ai_cost، و ai_human، و heatmap (أوقات النشاط الأكبر)، و top_campaigns (أفضل الوكلاء)، و contacts_by_country، و activity، و tasks_deals. تظل المعرفات المفقودة مرئية، وتتبع المعرفات التي تم استبعادها من dashboard_order الترتيب الافتراضي. على سبيل المثال، يقوم "dashboard_widgets": { "credits": false } بإخفاء لوحة الأرصدة عن العميل.

إخفاء صفحة من القائمة لا يمنح الوصول إليها أبداً. يحتاج 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 اتصالات، وفقط عبر Chat Widget أو WhatsApp Web أو Instagram”.
  • تسمح automations_edit و broadcasts_send و smart_lists_create للعميل بإنشاء وتعديل وحذف الأتمتة والبث والقوائم الذكية الخاصة به. القائمة التي لا تذكر أياً من الثلاثة تتركها كما هي (في حساب فرعي جديد: يتم تفعيل الثلاثة)، لذا يستمر التكامل القديم في العمل. إذا ذكرت واحدة على الأقل، فستقوم القائمة بضبط الثلاثة جميعاً: تلك التي تستبعدها سيتم إيقاف تشغيلها. لا يزال بإمكان العميل استخدام ما قمت بإعداده له في كلتا الحالتين، ولا يتم تقييد مفتاح API الخاص بوكالتك وجلساتك الخاصة في حساب العميل أبداً بواسطة هذه الثلاثة.
  • كل ميزة أخرى هي بالضبط ما تنص عليه القائمة، عند الإنشاء وعند التحديث. العميل الذي يتم إنشاؤه أو تحديثه بقائمة features يحصل على تلك الميزات ولا شيء غيرها. ويشمل ذلك crm_erp_integrations (قسم تكاملات CRM & ERP، حيث يقوم العميل بربط Odoo): لا يتم تفعيله إلا عندما تتضمنه قائمتك، لذا أضفه إذا كان يجب على العميل ربط نظام CRM أو ERP. العميل الذي يتم إنشاؤه بدون أي قائمة features يحصل على المجموعة الافتراضية، والتي تتضمنه.
  • إرسال معرفات 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 — أرسل فقط المفاتيح التي تريد تغييرها. يقوم مستوى creditManagementMode العلوي ("manual" أو "reselling") بتبديل وضع رصيد العميل؛ يبدأ الحساب الفرعي الذي تم إنشاؤه عبر واجهة برمجة التطبيقات في الوضع اليدوي، لذا قم بتبديله إلى "reselling" قبل أن يدفع العميل من خلال عملية الدفع الخاصة بوضع SaaS (راجع الحسابات الفرعية، تشغيل نسخة تجريبية مجانية).

كيف يتفاعل هذا مع حدود المقاعد في خطط 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) إلى تغيير تكلفة الذكاء الاصطناعي لديه من “0 رصيد، مدفوعة عبر مفتاحي الخاص” إلى “تُخصم من رصيد حسابي”، لذا فهو قرار متعمد لكل عميل على حدة بدلاً من كونه إعداداً افتراضياً على مستوى الوكالة بالكامل.

لتقييد المستويات (tiers) التي يمكن لوكلاء العميل الاختيار من بينها (بدلاً من مجرد تقييد الحد الأقصى)، استخدم 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 (أو []) لمسح القيد والسماح لهم باختيار أي مستوى. تُعد القائمة المحددة هنا بمثابة قفل يدوي: لم يعد allowed_ai_tiers الخاص بالخطة (راجع إدارة مستويات التسعير الخاصة بك عبر واجهة برمجة التطبيقات) يؤثر على هذا العميل عند التجديد. هذا الأمر مهم لأن الحساب الفرعي الذي يختار مستوى الذكاء الاصطناعي الخاص به يستهلك من رصيدك أنت، لذا فهي الأداة للتحكم في النماذج التي قد يتسبب عميل إعادة البيع في تحميلك تكاليفها.

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

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 و Mini، وعملاء 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 هي قائمة بأقسام دليل التشغيل (playbook) المراد تجميدها، وهي تحل محل القائمة المقفلة الخاصة بالعميل. أرسل null (أو []) لإلغاء قفل كل شيء. مفيدة للعملاء الذين تقدم لهم خدمة متكاملة حيث تمتلك أنت دليل التشغيل وتتم محاسبتك بناءً على النتائج.

تحتفظ الوكلاء الذين تم إنشاؤهم في المحرر الحالي بدليل التشغيل الخاص بهم في هذه الأقسام، لذا فهذه هي الأقسام التي يجب قفلها:

القسم في محرر الوكيل مفتاح API
مسار المحادثة conversation_flow
معلومات الشركة company_info
العرض offer
مصدر العميل المحتمل lead_source
نقاط البيع الفريدة unique_selling_points
تموضع السوق market_positioning
التسعير pricing_info
التعامل مع الاعتراضات objection_handling
أسئلة لطرحها questions
تنبيه أحد أعضاء الفريق عند alert_human_when
أخرى other
الموارد resources
تعليمات البريد الإلكتروني email_instructions
الشخصية personality
الهدف goal
القواعد rules
شروط الاستنتاج conclude_unless
التعليمات (الوكلاء القدامى فقط) instructions

لا يقرأ الوكلاء الحاليون instructions أبداً، لذا فإن قفل هذا القسم وحده لا يوفر أي حماية لهم: قم بقفل conversation_flow و rules والأقسام الأخرى التي لا ينبغي للعميل العبث بها.

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

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

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 }
      }
    }
  }'

تتغير فقط الفئات التي ترسلها: يتم دمج كل منها فوق إعدادات العميل الحالية، وتحتفظ كل فئة تستبعدها بقيمتها. تقبل كل فئة تحت settings القيمة enabled (من النوع boolean) وما يصل إلى ثلاث قيم 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

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

الحقل مطلوب الوصف
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 على عنوان MCP القياسي (يتم استبعاد أدوات الوكالة من عنوان MCP ذي العلامة البيضاء).

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

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 نعم عدد صحيح غير صفري من الأرصدة، بحد أقصى 100,000 لكل استدعاء. القيم الموجبة تضيف، والقيم السالبة تخصم.
description لا يظهر بجانب التعديل في سجل رصيد العميل. القيمة الافتراضية هي “تم التعديل بواسطة الوكالة عبر API”.
idempotency_key لا أي سلسلة نصية فريدة (تصل إلى 255 حرفاً، بدون مسافات) تختارها لهذا التعديل. يمكنك إرسالها كترويسة Idempotency-Key بدلاً من ذلك.

إعادة المحاولة بأمان. أرسل نفس مفتاح التكرار (idempotency key) عند إعادة محاولة استدعاء، على سبيل المثال بعد انتهاء المهلة، وسيتم إضافة الأرصدة أو خصمها مرة واحدة فقط. لمدة 24 ساعة، سيؤدي تكرار الطلب بنفس المفتاح ونفس التفاصيل إلى إرجاع الإجابة الأولى مرة أخرى (مع ترويسة Idempotent-Replayed: true) بدلاً من تغيير الرصيد مرة ثانية. يتم رفض نفس المفتاح مع بريد إلكتروني أو مبلغ أو وصف مختلف (422)، والتكرار الذي يصل بينما لا يزال الاستدعاء الأول قيد التشغيل سيحصل على 409: انتظر لحظة وأعد المحاولة. الاستدعاءات بدون مفتاح تعمل كما كانت من قبل.

cURL

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

الاستجابة

{
  "success": true,
  "data": {
    "email": "[email protected]",
    "previous_balance": 1200,
    "adjustment": 500,
    "new_balance": 1700
  }
}

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


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

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": "[email protected]",
        "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": "[email protected]",
    "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": "[email protected]",
        "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": "[email protected]",
        "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
  }
}

يحتوي كل صف أيضًا على أعداد وكلاء الذكاء الاصطناعي الخاصين بالعميل (totalAgents، activeAgents، pausedAgents، draftAgents)، ويضيف المستوى الأعلى totalActiveAgents و totalPausedAgents للصفحة. تغطي حقول الحملة الحملات الكلاسيكية فقط. تشير hasIssues / issueDetails إلى الحسابات الفرعية التي تستحق المراجعة. في الحساب الذي يحتوي على وكلاء، تأتي هذه الإشارات من درجة جاهزية الوكلاء المُفعّلين (على سبيل المثال "WhatsApp Web is disconnected" أو "Agent \"Front desk\": Routed on a channel that is not connected")؛ بينما لا يتم الإشارة أبدًا إلى الوكلاء غير المُفعّلين. أما في الحساب الذي لا يحتوي على وكلاء، فإنها تشير إلى الحملات الكلاسيكية، مثل الحملة المتوقفة مؤقتًا. استخدم هذا لبناء لوحة تحكم لفحص الحالة عبر كامل سجل العملاء بدلاً من فتح كل عميل على حدة لمعرفة أي الوكلاء غير مُفعّلين.

للحصول على بيانات المراسلات ونشاط الرصيد عبر جميع العملاء (سلسلة زمنية جاهزة للرسم البياني بدلاً من لقطة في لحظة زمنية معينة)، راجع 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 الرصيد الذي يحصل عليه العميل شهرياً في الخطط الشهرية أو السنوية، ولكل فترة فوترة في الخطط الأسبوعية. رقم صحيح لا يقل عن 1، أو 0 في الخطة التي تتضمن features الخاص بها byok (يقوم العميل بتشغيل الذكاء الاصطناعي باستخدام مفتاح API الخاص به، لذا لا تمنح الخطة أي أرصدة ولا تأخذ شيئاً من رصيدك المجمع).
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 لعدد غير محدود.
allowed_ai_tiers نماذج الذكاء الاصطناعي التي يمكن للعملاء في الخطة استخدامها، مستمدة من standard (Pro)، economy، max، mini. يتم تطبيقها عند اشتراك العميل وعند كل تجديد. null أو [] (الافتراضي) تعني أن الخطة لا تدير النماذج. القفل الذي يتم تعيينه يدوياً على حساب فرعي باستخدام PUT /v1/subaccounts/:uid/ai-tiers لا يتم استبداله أبداً بواسطة الخطة.
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 “ليس حسابك الفرعي”. تحقق جيداً من المعرف ومن أن الحساب هو أحد الحسابات التي تديرها.
  • المعلمة اختيارية في كل مكان تُقبل فيه. إذا حذفتها، سيعمل نفس نقطة النهاية على حساب الوكالة الخاص بك، مما يتيح لك إعادة استخدام تكامل واحد لكليهما.

ذات صلة