Logistivo CLI: أدِر عملياتك اللوجستية من الطرفية ومن نظام ERP لديك

كتالوج أوامر واحد يغذّي ثلاث واجهات: عميل الطرفية lg، ومساعد الذكاء الاصطناعي داخل لوحة التحكم، والقناة التي تتصل عبرها مساعدات الذكاء الاصطناعي الخارجية. تُكتب القدرة مرة واحدة وتظهر في الواجهات الثلاث — وأصبح لكل إجراء كتابة في لوحة التحكم أمرٌ مقابل، بحيث تستطيع نصوصك البرمجية ووكلاء الذكاء الاصطناعي الخاصون بك إنجاز العمل الذي يؤديه فريقك على الشاشة. أما المدفوعات والموافقة القانونية وإغلاق الحساب فتبقى في المتصفح عن قصد. هذه الصفحة عقد. جدول الأوامر أدناه ليس مكتوبًا يدويًا؛ بل يُولَّد من سجل الأوامر الحي مع كل طلب.

ما هو Logistivo CLI؟

Logistivo CLI (lg) عميل لسطر الأوامر ينفّذ أعمال حسابك في Logistivo — الشحنات والرحلات، والطلبات، والعروض والمناقصات، والأسطول والسائقين، والمستندات، وجهات الاتصال والحسابات الجارية، والفواتير والمحاسبة، والمستودع والمخزون، وأعضاء الفريق والتعريفات الجمركية — من الطرفية أو من نص برمجي أو من وكيل الذكاء الاصطناعي الخاص بك. الأوامر ليست مدمجة في العميل: إذ يجلب العميل كتالوج الأوامر من الخادم ويبني نفسه منه. ويمكن استدعاء الأوامر نفسها عبر HTTP دون تثبيت أي شيء — وهو المسار الذي تستخدمه تكاملات ERP و CRM — وكذلك عبر قناة MCP التي تتصل بها مساعدات الذكاء الاصطناعي الخارجية.

ما المتاح اليوم، وما هو قادم

وُضع هذا القسم في أعلى الصفحة عن قصد. فأغلى خطأ يمكن أن ترتكبه وثيقة تكامل هو أن تصف نقطة نهاية (endpoint) لم تُفتح بعد كأنها متاحة: يكتب المطوّر المسؤول عن التكامل الشيفرة، فتُعيد نقطة النهاية 404، ولا تعود الثقة بعدها.

لأن العقد مُجمَّد، تظل شيفرة التكامل التي تكتبها اليوم تعمل مع افتتاح الأجزاء المتبقية. ويجب تجاهل الحقول التي لا تعرفها؛ فهذه القاعدة هي ما يتيح لنا الإضافة دون كسر أي شيء.

ما الذي يميّز هذا النهج: العميل لا يعرف أي أوامر، بل يبنيها من الكتالوج

هذا هو القرار الوحيد الذي يمنح بقية الصفحة معناها. في أي CLI تقليدي تعيش الأوامر داخل العميل؛ أما في Logistivo فتعيش على الخادم.

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

في Logistivo يكون تعريف الأمر سجلًا واحدًا: اسمه، وما يفعله، ومعاملات JSON Schema الخاصة به، والأدوار التي يحق لها رؤيته، وما إذا كان يحتاج إلى تأكيد، وما إذا كان أثره قابلًا للتراجع. وعندما يبدأ lg يجلب هذا الكتالوج ويولّد منه نص المساعدة والخيارات (flags) والتحقق من صحة المدخلات. وفي اللحظة التي يُضاف فيها أمر على الخادم، يعرفه lg — دون أي تحديث للعميل.

يغذّي الكتالوج نفسه مساعدَ الذكاء الاصطناعي في لوحة التحكم والقناةَ التي تتصل بها مساعدات الذكاء الاصطناعي الخارجية. تُكتب القدرة مرة واحدة وتظهر في ثلاثة أماكن — وتمر الثلاثة جميعًا عبر بوابة الدور نفسها وبوابة التأكيد نفسها وسجل التدقيق نفسه. لا توجد قائمة أوامر منفصلة خاصة بـ CLI؛ ولو وُجدت لتباعدت الواجهات الثلاث بصمت في غضون ستة أشهر.

قاعدة التسمية — كيف تنمو أسماء الأوامر

سينمو الكتالوج. ولا تُسمّى الأوامر الجديدة اعتباطًا؛ بل تُطبَّق ست قواعد. ننشرها هنا لأن هذه هي الأسماء التي سيكتبها تكاملك لسنوات، وقابليتها للتنبؤ لها قيمة لديك.

التغطية: كل ما في لوحة التحكم، عبر أمر

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

هذا مَقيس، لا مجرد ادعاء. فكل نقطة نهاية للكتابة خلف لوحة التحكم تُفحص مقابل سجل الأوامر، ولا تُعدّ نقطة النهاية مغطاة إلا إذا أعلنها أمرٌ نسخةً مطابقة له عبر HTTP أو استدعى الخدمة المشتركة نفسها. ومن نقاط نهاية الكتابة المشمولة بالنطاق، 100% مغطاة ولا توجد نقطة غير مُثبتة. وكل نقطة نهاية مستبعدة تحمل سببًا مكتوبًا — خطوات الهوية والدفع، ومستوى التحكم في التكامل، ونقاط النهاية الخاصة بتطبيق السائق، وقياسات العميل عن بُعد (telemetry)، والنسخ الميتة التي لا يستدعيها أحد — والنقاط التي تهم المطوّر المسؤول عن التكامل مدرجة أدناه.

والأوامر التي تأخذ ملفًا تخضع للقاعدة نفسها: إذ يأخذ 33 أمرًا في الجدول مستندًا أو صورة، وجميعها تعمل من lg وعبر HTTP وعبر MCP (انظر «الأوامر التي تأخذ ملفات»).

وأعمال الإدارة مغطاة أيضًا، خلف مفتاح أقوى: إذ يحتاج 62 أمرًا في الجدول — أعضاء الفريق والأدوار، وإعدادات الشركة، والحسابات المصرفية، والبطاقات المحفوظة، ومفاتيح التكامل — إلى مفتاح تكامل بمستوى manager. أما المفتاح بمستوى employee، وهو الافتراضي، فينفّذ العمليات اليومية ويُرفض في تلك الأوامر بالخطأ INSUFFICIENT_KEY_LEVEL.

لحسابات الشريك بالإحالة (affiliate) كتالوج خاص بها: 55 أمرًا في مجالات عددها 20 — الإحالات، والعملاء المحتملون، وملاحظات CRM ومهامه، وعروض المبيعات التقديمية، والأرباح والمدفوعات، إضافة إلى أوامر الحساب والفريق التي يملكها كل دور. والأوامر الخاصة بالشريك بالإحالة وحده ليست في الجدول العام أدناه، الذي يسرد أدوار لوحة التحكم الثلاثة؛ إذ يراها حساب الشريك بالإحالة في GET /api/common/commands وفي lg commands. والشركة التي تكون شريكًا بالإحالة وفي الوقت نفسه شاحنًا أو ناقلًا أو مخلّصًا جمركيًا ترى المجموعتين كلتيهما.

ينبغي للوكيل أن يبدأ بـ lg users get (واسمه في API هو get_current_user): فهو يعيد الدور، ومستوى وصول المفتاح المستخدم، والصلاحيات الفعلية، وما إذا كانت موافقة قانونية معلّقة أو رقم هاتف غير مُتحقَّق منه يحجب عمليات الكتابة حاليًا — كي يتمكن الوكيل من توقّع الرفض بدلًا من تلقّيه.

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

التثبيت والهوية

lg نص Node برمجي في ملف واحد بلا تبعيات (Node 18+)، منشور على npm باسم @lgstv/lg. تثبّت الحزمة أمرين متطابقين، lg و logistivo — استخدم logistivo إذا كان lg معرَّفًا مسبقًا كاسم مستعار (alias) على جهازك. ولأنه ملف واحد، فإن نسخ lg.mjs إلى خادم ERP لدى أحد العملاء يعمل أيضًا. ولا تحتاج إلى العميل لبناء تكامل ERP/CRM — فالأوامر نفسها متاحة عبر HTTP.

1. التثبيت — كل ما تحتاجه هو Node 18 أو أحدث؛ ولا توجد أي تبعيات أخرى. ثبّته على مستوى النظام (globally) أو شغّله دون تثبيت عبر npx.

2. تسجيل الدخول برمز موافقة — يعرض lg login رمز موافقة قصيرًا ويفتح logistivo.com/connect في متصفحك؛ أما عبر SSH أو في CI أو مع --no-browser فيكتفي بطباعة العنوان، ويمكنك فتحه على أي جهاز، بما في ذلك هاتفك. سجّل الدخول هناك كالمعتاد، وتحقّق من أن الرمز الظاهر في الصفحة هو نفسه الظاهر في الطرفية، واختر وصولًا للقراءة فقط أو للقراءة والتنفيذ، ثم وافِق. لا يُكتب أي شيء سري في الطرفية: لا كلمة مرور ولا مفتاح ولا رمز لمرة واحدة. وبعد ذلك تبقى الجلسة مسجّلة الدخول على ذلك الحاسوب — فإغلاق الطرفية لا يسجّل خروجك، ويجدّد lg رمز الوصول (access token) بنفسه قبل انتهاء صلاحيته. ويُنهي lg logout الجلسة على الخادم أيضًا، ويمكنك إزالتها من لوحة التحكم في Settings › Integration keys › AI and CLI connections. ويبقى lg login --password (البريد الإلكتروني وكلمة المرور) متاحًا طريقًا احتياطيًا. يتطلب ذلك lg 0.11 أو أحدث.

3. للخوادم و CI: مفتاح، لا رمز موافقة — على الخادم أو في مهمة CI لا يوجد أحد ليوافق على رمز في المتصفح. أصدر مفتاحًا من لوحة التحكم (Settings › Integration keys) أو عبر lg keys create — ويمكنك اختياريًا إصداره نيابةً عن عضو فريق مخصص بصلاحيات ضيقة — ثم ضعه في LOGISTIVO_TOKEN، أو احفظه عبر lg login --api-key. وما دام المتغير مضبوطًا فلن يُقرأ ملف الإعدادات أبدًا. التفاصيل: قسم «الاتصال بمفتاح API».

4. تحقّق واستكشف الكتالوج — يسرد lg commands كل أمر يستطيع دورك رؤيته، مجمّعًا حسب المجال؛ ويطبع lg help أفعال ذلك المجال، ويطبع lg help قائمة المعاملات الكاملة لأمر واحد مع أنواعها وأيّها إلزامي. ولا يعيش أي من هذا النص داخل العميل — بل يأتي كله من الكتالوج. وتذكّر أن القائمة تعتمد على دورك: فأفعال المجال الواحد ليست نفسها لدى الناقل ولدى الشاحن (فالأمر loads set-status، على سبيل المثال، موجود في كتالوج الناقل فقط). وإذا كان فعل ما مفقودًا، فتحقق من دورك قبل أن تتحقق من التثبيت.

لا تضع المفتاح أبدًا في نظام التحكم بالإصدارات أو في سجل CI أو في نافذة محادثة. إذا سجّلت الدخول برمز موافقة أو بمفتاح تكامل، فإن lg logout يُنهي ذلك على الخادم أيضًا؛ أما في جلسة كلمة المرور (lg login --password) فإنه يحذف النسخة المحلية فقط ويصرّح بذلك بوضوح. ويخزّن سجل التدقيق وسائطك (arguments) لكنه يُخفي بالقيمة *** كل حقل يحتوي اسمه على token أو password أو IBAN أو card أو OTP، وكل معامل يعلنه الأمر سريًا.

سهولة استخدام العميل

تجعل هذه الميزات الاستخدام اليومي للعميل `lg` أسهل. ولا يغيّر أي منها عقد HTTP — تخطَّ هذا القسم إذا كنت تتكامل عبر HTTP مباشرة.

الاتصال بمفتاح API

يتصل نظام ERP أو CRM أو نص برمجي أو وكيل ذكاء اصطناعي بـ Logistivo بمفتاح تكامل صادر من لوحة التحكم أو عبر lg keys create. ويعمل المفتاح نيابةً عن عضو حقيقي في الفريق: فدور ذلك الشخص يحدد قائمة الأوامر، ومستوى وصول المفتاح يحدد مدى ثقل العمل المسموح به، وعندما يغادر ذلك الشخص الفريق يموت المفتاح معه. لا يوجد «حساب خدمة» اصطناعي ولن يوجد — فعزل المستأجرين المتعددين مرتبط بالمستخدم، والجسر الذي بلا مالك هو من النوع الذي يظل يكتب بصمت لسنوات.

1. أصدر مفتاحًا من لوحة التحكم — Settings › Integration keys › New key. امنحه اسمًا («ERP nightly sync»)، واختر النطاق ومستوى الوصول، ويمكنك اختياريًا تقصير مدة صلاحيته. يُعرض المفتاح مرة واحدة، على تلك الشاشة فقط؛ ولا يخزّنه الخادم. فإذا فقدته، يُصدر Rotate مفتاحًا جديدًا — ويصبح القديم غير صالح فورًا.

2. اتصل من الطرفية — يتحقق lg login --api-key من المفتاح، ويطبع الهوية والنطاق، وينزّل كتالوج الأوامر. ويسأل lg whoami الخادم عن المستخدم والشركة والدور والنطاق التي تعمل بها. ويلغي lg logout المفتاح على الخادم أيضًا، تمامًا كما يُنهي هناك الجلسة المفتوحة برمز موافقة (وحده lg logout في جلسة كلمة المرور لا يستطيع ذلك).

3. أو HTTP عادي — المفتاح رمز وصول يُحمل في الترويسة Authorization: Bearer ويعمل مباشرة مع نقاط نهاية الأوامر الثلاث. وعلى الخادم أو في CI ضعه في LOGISTIVO_TOKEN؛ وما دام ذلك المتغير مضبوطًا فلن يُقرأ ملف الإعدادات أبدًا.

4. أو أدِر المفاتيح من الطرفية: lg keys — lg keys هو النظير الطرفي لشاشة لوحة التحكم: نقاط النهاية نفسها، والبوابة نفسها (صلاحية إدارة الفريق، ومفتاح بمستوى manager عند استدعائه بمفتاح). وتعيد create و rotate و transfer رمزًا مميزًا جديدًا مرة واحدة: فمع --save-profile=NAME يذهب مباشرة إلى ملف شخصي محلي ولا يُطبع أبدًا؛ وإلا فيطبعه lg مرة واحدة. وفي وضع --json لا يُضمَّن الرمز إلا إذا أضفت --show-secret، واستدعاء --json الذي لا يحمل أيًّا من الخيارين يُرفض قبل إرسال الطلب، كي لا يستقر الرمز بصمت في مخرجات نص برمجي. وتطلب rotate و transfer و revoke التأكيد (--yes)؛ ويُخاطَب المفتاح باسمه الدقيق أو بمعرّف uuid الخاص به، لا بالتخمين أبدًا. وينتقل مستوى الوصول دون تغيير إلى المفتاح المُدوَّر أو المنقول.

يُفرض النطاق على سطح API بأكمله، لا على كتالوج الأوامر فحسب: فالمفتاح ذو القراءة فقط يمرّر طلبات القراءة (GET/HEAD/OPTIONS)، وكل طلب كتابة آخر يُجاب بـ 403 forbidden. وهناك استثناءان مقصودان، وكلاهما محمي ببوابة أدق: نقطة نهاية تنفيذ الأوامر (إذ يأتي القرار من علَم read_only الخاص بالأمر نفسه، لأن الأوامر التي لا تكتب تُستدعى أيضًا بـ POST)، والمفتاح الذي يلغي نفسه (lg logout، المسموح به للمفتاح ذي القراءة فقط أيضًا). والنطاق ومنح المجالات ومستوى الوصول ثلاثة محاور مستقلة ويجب اجتيازها جميعًا: فمفتاح القراءة لا يستطيع الكتابة حتى بمستوى manager، ومفتاح الكتابة بمستوى employee لا يستطيع إدارة الفريق، ومنح المجال loads:write لا يفتح أعمال الإدارة. أصدر المفتاح نيابةً عن العضو صاحب أقل الصلاحيات التي تغطي احتياجاتك: فالدور يحدد السجلات التي يمكنك رؤيتها أصلًا.

الدقائق العشر الأولى: من لوحة التحكم إلى استدعائك الأول

أغلى دقائق التكامل هي الدقائق العشر الأولى. وتعرض الخطوات الأربع أدناه هذا المسار بالترتيب؛ والترتيب نفسه موجود في لوحة التحكم على شكل معالج (Settings › Integration › Setup wizard)، ويستدعي المعالج بالضبط نقاط النهاية الموصوفة هنا. والمطوّر الذي لا يملك وصولًا إلى المعالج يصل إلى المكان نفسه بقراءة هذا القسم.

لا تنتهي أيٌّ من الخطوات الأربع بعبارة «لقد أرسلته». فسجل الطلبات هو ما يجيب عمّا إذا كان المفتاح يعمل فعلًا؛ وسجل التسليمات هو ما يجيب عمّا إذا كان webhook يصل فعلًا. وكلاهما متاح في لوحة التحكم وفي lg. والإعداد الذي لا يُقاس أبدًا هو إعداد يُعتقد فحسب أنه يعمل.

بيئة الاختبار (sandbox): تدرّب على الكتابة دون المساس ببيئة الإنتاج

يخبرك الفحص المسبق (dry_run) بما سيفعله الأمر؛ لكن ما إذا كان عدم التكرار يعيد النتيجة فعلًا، وما إذا كان webhook يُسلَّم فعلًا، وكيف تبدو فروع الأخطاء، ومن أين يُخصم الرصيد، كل ذلك لا يمكن رؤيته إلا في عملية كتابة حقيقية. ولهذا وُجدت بيئة sandbox: مستأجر منفصل يحاكي شركتك — بالشيفرة نفسها، وكتالوج الأوامر نفسه — ولا يمس أبدًا دفترك الحي.

بيئة sandbox ليست علَمًا في الطلب، بل مستأجر (tenant). شركة Logistivo منفصلة تُفتح لشركتك: بمستخدمها الخاص، وباقتها الخاصة، ودفتر رصيدها الخاص، واشتراكات webhook الخاصة بها. وتُستنتج البيئة من شركة المفتاح ولا يمكن للمستدعي تمريرها، لذا حتى لو اخترت الملف الشخصي الخاطئ يتوقف الطلب في جهة الخادم بالخطأ 403 ENVIRONMENT_MISMATCH. فعبارة «ظننت أنني أكتب في sandbox فكتبت في بيئة الإنتاج» مستحيلة بنيويًا.

السطح متطابق — وهذا مَقيس: فالكتالوج الذي يحصل عليه مفتاح sandbox هو نفسه الذي يحصل عليه مفتاحك الحي (في مفتاح الشاحن، 448 أمرًا في الجانبين). والجسر الذي يعمل في sandbox يعمل في بيئة الإنتاج؛ ولا شيء مما تتعلمه يحتاج إلى أن يُتعلَّم مرتين.

لا تُفتح بيئة sandbox فارغة: بل تحتوي على بيانات أولية مُولَّدة (غير منسوخة) — جهات اتصال، وشحنات في الاتجاهين، وطلبات. والأسماء مختلَقة بشكل صريح، وعناوين البريد الإلكتروني تقع في النطاق @sandbox.invalid؛ ولا يُقرأ أبدًا صف أي مستأجر حقيقي ولا يُستنسخ ولا يُستخدم كقالب.

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

نموذج الأوامر

هناك قواعد صياغة واحدة بلا استثناءات. ولمعرفة كيفية استدعاء أمر، كل ما تحتاجه هو ما يقوله الكتالوج عنه.

lg loads list --status=in_transport --limit=20 --json

أسماء الخيارات هي أسماء المعاملات في المخطط، ويقبل lg كلا الهجاءين: --load_code و --load-code يصلان إلى الحقل نفسه (ويطبع lg help صيغة kebab-case). لذا فرؤية الخيار تخبرك بحقل JSON الذي ينتهي إليه، والانتقال من CLI إلى HTTP لا يحتاج إلى أي ترجمة للأسماء. والمعامل المنطقي (boolean) المكتوب بلا قيمة يساوي true (--only_open)؛ وعكسه --no-only_open. اكتب الوسيط الذي تبدأ قيمته بشَرطة على الصورة --flag=value ، وإلا فإن خيارًا منسيًّا سيبتلع الخيار التالي بصمت على أنه قيمته. وفي الأمر الذي يأخذ ملفًا، ضع @ قبل المسار المحلي (--attachment_uuid=@./cmr.pdf) — انظر «الأوامر التي تأخذ ملفات».

أمثلة حقيقية

كل أمر أدناه موجود في الكتالوج اليوم؛ ولا يوجد هنا اسم أو معامل مختلَق. المخرجات مختصرة. وتعرض المخرجات مستوى `data.result`؛ أما عبر HTTP فيصل الكائن نفسه داخل الغلاف `{success, data:{…}}` (انظر «واجهة API للأوامر عبر HTTP»).

دون العميل: واجهة API للأوامر عبر HTTP

lg وسيلة للراحة، لا البوابة الوحيدة. فالكتالوج والتنفيذ كلاهما يمران عبر ثلاث نقاط نهاية HTTP (وللملفات نقطة رابعة هي نقطة نهاية الرفع — انظر «الأوامر التي تأخذ ملفات»)؛ ويتصل تكامل ERP أو CRM هنا مباشرة. والهوية رمز وصول شخصي يُحمل في Authorization: Bearer. وكل استجابة، دون استثناء، تعود في الغلاف نفسه: `{ "success": bool, "data": { … }, "code": "…", "message": { … } }`. ويعيش العقد كله داخل `data` — `contract_version` و `command` و `status`، و `result` بوصفه مخرجات الأمر؛ وعند الإخفاق `error_code` و `error_key` و `error`. وتعرض أمثلة الاستجابات في هذه الصفحة الكائن `data` بدلًا من الغلاف توفيرًا للمساحة؛ فلا تنسَ فك الغلاف واستخراج `data` في شيفرتك. كما يطبع `lg --json` الغلاف كاملًا، ولهذا تبدأ مسارات jq بـ `.data.result…`. والاستثناء الوحيد هو `/api/public/status`: فنقطة النهاية هذه بلا غلاف كي تتمكن أدوات المراقبة من إطلاق التنبيه دون تحليلها.

طلب التأكيد عبر 200 + ok:false محظور ولن يحدث أبدًا. والسبب بسيط: فالعملاء يعاملون 200 على أنها نجاح، لذا فإن طلب تأكيد يُعاد بالرمز 200 سيقتل التدفق بصمت ولن يلاحظ أحد. التأكيد دائمًا 409.

الأوامر التي تأخذ ملفات

يأخذ 33 أمرًا في الجدول مستندًا أو صورة: إرفاق CMR بشحنة، وقراءة رموز HS من فاتورة، وإنشاء مركبة من مستند تسجيلها، وتقدير منصّة نقّالة (pallet) من الصور، ورفع مستند للشركة، ومطابقة فاتورة مع قائمة التعبئة (packing list). في المتصفح تُسقط الملف في نموذج؛ أما في أي مكان آخر فيتطلب الأمر خطوتين — ارفع الملف، ثم مرّر معرّفه إلى الأمر.

يأخذ المعامل ملفًا عندما ينتهي اسمه بـ attachment_uuid أو attachment_uuids — مثل photos[].attachment_uuid داخل قائمة، و front_attachment_uuid في الشيك. ولا يتعين عليك تذكّر ذلك: فكل صف في الكتالوج يحمل file_params بالمسارات الدقيقة، ويَسِم المخطط تلك الحقول (format: uuid، x-logistivo-file: true)، وتحمل استجابة الكتالوج كتلة attachments تتضمن عنوان الرفع، والأنواع المقبولة، وحدود الحجم، ومدة الصلاحية. ويُظهرها lg help أيضًا.

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

مرفقات محادثة لوحة التحكم والملفات المرفوعة للأوامر مساحتان منفصلتان: فالملف المرفق في محادثة المساعد لا يمكن تمريره إلى أمر بمعرّفه، والملف المرفوع لأمر لا يظهر أبدًا في سلسلة محادثة.

الرفع ليس أمرًا وليس له أثر على الأعمال بمفرده: فلا يحدث شيء لبياناتك إلى أن يستخدم أمرٌ المعرّف. ولهذا السبب أيضًا لا يطلب الرفع تأكيدًا أبدًا — فالأمر الذي يستهلك الملف هو الذي يحمل البوابة.

بوابة التأكيد والأوامر غير القابلة للتراجع

يحمل كل أمر في الكتالوج علَمين: confirmation_needed (هل يتطلب موافقة صريحة قبل التشغيل) و irreversible (هل يمكن التراجع عن أثره). وهما سؤالان منفصلان، ويُفرض كلاهما على الخادم بدلًا من تركهما لحسن تصرّف العميل.

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

تُقرأ البوابة من الأمر الفعلي. فعندما يغلّف أمرٌ أمرًا آخر — كما يفعل المنفّذ العام في المحادثة — تأتي البوابة من أعلام الأمر الذي سيُنفَّذ فعلًا، لا من الغلاف. ومع علَم ثابت كان لا بد من وقوع أحد إخفاقين: إما أن يعمل أمر الفاتورة دون تأكيد، أو أن يُظهر كل بحث عن دولة بطاقة تأكيد.

read_only وعدم الخضوع للبوابة ليسا الشيء نفسه. فهناك ثلاث حالات متمايزة: invoices preview لا يخضع للبوابة ولا يكتب شيئًا؛ و loads create يخضع للبوابة ويكتب؛ و invoices create لا يخضع للبوابة لكنه يكتب — إذ تنشأ مسودة. واختبار واحد يحسم الأمر: عندما يعود الأمر، هل تغيّر صف في قاعدة البيانات؟

بعض الإجراءات ليست خلف هذه البوابة لأنها ليست أوامر أصلًا: شراء باقة، وإضافة بطاقة عبر 3D Secure، والموافقة على النصوص القانونية، وإغلاق الحساب، كلها تتم في متصفح الشخص نفسه. ولهذه الإجراءات يعيد lg handoff-links generate رابطًا على logistivo.com — مجانيًا، لا يكتب شيئًا، ولا يحمل أي سر — ويُكمل الشخص الخطوة هناك. ولا يوجد خيار، مهما كان ضبطه، يحوّل دفعة أو موافقة إلى استدعاء API.

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

الفحص المسبق: اعرف ما سيفعله أمر الكتابة دون تشغيله

أغلى خطوة في ربط جسر ERP هي اكتشاف ما إذا كان جسم طلبك صحيحًا عبر تشغيل الأمر فعليًا: مسودة فاتورة في الدفتر الحي، ورصيد مستهلَك، وتنظيف يدوي. و dry_run يُنهي ذلك — تضيف حقلًا واحدًا إلى الطلب، فلا يُنفَّذ الأمر، وتقرأ ما كان سيحدث.

يضم السجل اليوم 519 أمرًا؛ منها 233 تقرأ فقط ولا تكتب شيئًا. ومن أوامر الكتابة المتبقية البالغ عددها 286، يخضع 251 للبوابة: فعند استدعائها دون confirm تجيب أصلًا بالرمز 409 وتصف ما كانت ستفعله. أما الثغرة فكانت في الأوامر الأخرى البالغ عددها 35 — مسودات الفواتير، ومسودات مستندات التصدير، والبنود: أي بالضبط السلسلة التي يربطها الجسر أولًا. ففي هذه الأوامر كان الاستدعاء يعني التنفيذ.

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

وأكثر أخطاء الجسور شيوعًا — وآخرها اكتشافًا — هو التالي: ترسل حقلًا غير موجود في المخطط (customer_id حيث يُتوقع recipient_contact_id)، فيُسقطه الخادم بصمت، ويعيد الأمر 200، ويستقر السجل في المكان الخاطئ. وتسرد استجابة الفحص المسبق هذه الحقول بأسمائها تحت arguments.ignored؛ وهذا ما لن تفعله أي رسالة خطأ أبدًا.

الفحص المسبق لا يكتب شيئًا، وهذا أمر بنيوي قبل أن يكون نتيجة قياس: فمسار الفحص المسبق لا يدخل أبدًا إلى معالج الأمر، لذا يصح ذلك على كل أمر، بما في ذلك الأوامر المضافة لاحقًا. وقد قيس ذلك أيضًا عند إطلاقه: إذ التُقطت كل عبارة SQL صدرت أثناء إجراء الفحص المسبق لكل أوامر الكتابة في الكتالوج آنذاك (مجموعتا وسائط، ودوران، و 178 فحصًا مسبقًا). فلم تصدر ولا عبارة INSERT/UPDATE/DELETE واحدة، ولا مهمة واحدة في الطابور، ولا بريد إلكتروني واحد؛ وبقيت أعداد الصفوف في 31 جدولًا والرصيد المتاح دون تغيير.

رمز الخروج هو نفسه الذي سيُنتجه الاستدعاء الحقيقي — 0 إذا كان سيُنفَّذ، و 4 لبوابة التأكيد، و 2 لتعارض عدم التكرار، و 1 لأي شيء آخر — لذا فإن "lg … --dry-run || exit" بوابة ذات معنى في خطوة CI.

عدم التكرار (idempotency): لماذا لا تُنشئ إعادة المحاولة تكرارات

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

الاستدعاء الذي يحمل idempotency_key يُنفَّذ مرة واحدة على الأكثر. فالاستدعاء الثاني لا يعيد تنفيذ الأمر؛ بل يعيد النتيجة المسجّلة مع الحالة replayed. وعندما تنقطع الشبكة، أو تنتهي مهلة الطلب، أو يلتقط الطابور المهمة نفسها مرتين، تحصل على النتيجة الأولى بدلًا من فاتورة مكرّرة.

استخدم مفتاحًا مع كل أمر كتابة. فالحقل read_only في الكتالوج يمنحك هذا التمييز مجانًا: كل أمر قيمة read_only فيه false يستحق مفتاح عدم تكرار (idempotency key).

ينبغي أن تستخدم استراتيجية إعادة المحاولة لديك التراجع الأسي (exponential backoff) وأن تحمل المفتاح نفسه في كل محاولة. فتوليد مفتاح جديد لكل محاولة يعادل عدم استخدام عدم التكرار على الإطلاق. ولا ترسل المفتاح نفسه بالتوازي: فضمان «مرة واحدة على الأكثر» يسري على إعادات المحاولة المتتابعة، لا على طلبين يتسابقان.

المزامنة التزايدية وترقيم الصفحات

ينبغي لجسر ERP/CRM أن يسحب ما تغيّر، لا كل شيء كل ساعة. فكل أمر قائمة — loads list و demands list-own و contacts list و invoices list و teammates list و load-groups list و reservations list و drivers list و tenders list و products search و warehouses search — يقبل معاملَين مشتركين ويعيد حقلًا مشتركًا واحدًا.

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

التحميل الأولي الكامل هو الآلية نفسها: ابدأ بـ updated_since=1970-01-01T00:00:00Z وتتبّع next_cursor حتى يصبح null. ولا توجد نقطة نهاية منفصلة لـ «التصدير» لأنه لا حاجة إليها.

الشيء نفسه مع lg: lg loads list --updated_since=2026-09-01T00:00:00Z --limit=100 --json ، ثم lg loads list --cursor= --json.

في المزامنة التالية، اضبط updated_since على أكبر قيمة updated_at رأيتها. ودقة الطوابع الزمنية ثانية واحدة، لذا قد يصل السجل الواقع على الحد مرتين — وهذا غير ضار ما دمت تُجري upsert (إدراجًا أو تحديثًا) حسب external_ref أو code في جانبك. ومن دون updated_since أو cursor يعمل الأمر في وضع المحادثة: ترتيب مخصص للبشر، و 20 صفًا على الأكثر، و next_cursor بقيمة null، و truncated يقول «يوجد المزيد». لا تستخدم هذا الوضع للمزامنة.

مفاتيح الأخطاء المقروءة آليًا لهذا القسم: INVALID_CURSOR و INVALID_UPDATED_SINCE و DUPLICATE_EXTERNAL_REF و EXTERNAL_REF_TOO_LONG و EXTERNAL_REF_INVALID. وجميعها تجيب بـ HTTP 422 مع error_code: "failed" و result.error_key في الجسم. ابنِ التفرّع على المفتاح، لا على النص أبدًا.

مفتاحك الخاص: external_ref

لا تجعل معرّفاتنا ذات الزيادة التلقائية (invoice_id و contact_id) مفتاح الأعمال في نظام ERP لديك؛ فهي معتمة وخاصة بشركتك. بل تحمل الشحنات والطلبات وجهات الاتصال والفواتير والمنتجات والمستودعات مفتاحك أنت بدلًا منها.

Webhooks الصادرة: نرسل إليك طلب POST عند وقوع حدث

كل ما سبق كان سحبًا (pull): أنت تسأل ونحن نجيب. فكان على جسر ERP أن يسأل مرة كل دقيقة ليعرف أن شحنة غيّرت حالتها، أو أن فاتورة صدرت، أو أن عرضًا وصل. لم يعد الأمر كذلك: سجّل عنوان https، واختر الأحداث التي تهمك، وسيصلك طلب POST موقَّع عند وقوعها.

أُضيف الدفع (push) إلى جانب السحب، لا بديلًا عنه. فالمزامنة التزايدية (updated_since + cursor) لم تُمس وما تزال الأداة الصحيحة: التحميل الكامل الأول، وتعبئة السجل التاريخي، والإجابة عن سؤال «هل فاتني شيء»، كلها تعيش هناك. أما webhooks فتقلّص زمن الاستجابة من دقائق إلى ثوانٍ. والجسر السليم يستخدم الاثنين — webhook كمُحفّز، والمزامنة كشبكة أمان.

الحمولة (payload) إشارة، لا نسخة من السجل. فهي تحمل المعرّفات (id، و external_ref الخاص بك، والحالة، والوقت)؛ وتجلب التفاصيل بمفتاحك أنت عبر GET، وهذا الاستدعاء يمر أصلًا عبر بوابات التفويض الخاصة بك. لذا يبقى سطح الانكشاف عند مستوى المعرّفات. وهناك حقلان غائبان عن قصد: هوية الشركة التي قدّمت العرض (فالعروض العمياء تظهر باسم مستعار في لوحة التحكم؛ ووضع الهوية في webhook سيخترق هذه الخصوصية عبر قناة ثانية)، وبيانات الاتصال الخاصة بالحجز (فلا حاجة إلى نقل البيانات الشخصية عبر قناة إضافية).

أسماء الأحداث مُجمَّدة. فإذا تغيّر معنى اسم ما، يُفتح اسم جديد ويعيش الاسم القديم خلال نافذة إهمال (deprecation). وإضافة حقل جديد إلى الحمولة لا ترفع إصدار العقد — إذ يجب على المستهلك تجاهل الحقول التي لا يعرفها.

كتالوج الأحداث

كل حدث من الأحداث أدناه البالغ عددها 13 يقابله صنف حدث يُرسَل فعلًا. لا توجد في الكتالوج أسماء من قبيل «سيكون من الجيد وجودها»: فالحدث الذي يُعلَن عنه ولا يُطلق أبدًا هو حدث ينتظره المطوّر المسؤول عن التكامل إلى الأبد، وهذا الإخفاق صامت. وهذا الجدول أيضًا ليس مكتوبًا يدويًا — بل يُستمد من الكتالوج الحي مع كل تحميل للصفحة.

الحدث invoice.payment_recorded غائب عن قصد: فصنف هذا الحدث موجود في الشيفرة لكنه لا يُرسَل من أي مكان. وسيُضاف حدث الدفع في اليوم الذي يُطلق فيه الصنف فعلًا — لا قبل ذلك. فالإعلان عن حدث مبكرًا أسوأ من عدم إضافته أبدًا.

التحقق من التوقيع

يحمل كل طلب الترويسة X-Logistivo-Signature: t=,v1=. والسلسلة الموقَّعة هي "." والخوارزمية HMAC-SHA256. وتُبقي البادئة v1 المخطط قابلًا للإصدار: فإذا ظهر مخطط ثانٍ يومًا ما، تحمل الترويسة t=…,v1=…,v2=… وتختار أنت المخطط الذي تعرفه.

ننشر مستقبِلَين مرجعيين بلا تبعيات، أحدهما لـ Node والآخر لـ PHP الخالص. يطبّق كلاهما القواعد الأربع أعلاه ويختبران نفسيهما عبر --selftest: توقيع صالح، وجسم معبوث به، وسرّ خاطئ، وطابع زمني خارج النافذة، وترويسة مشوّهة، وفخ إعادة التسلسل، ونوعا التكرار كلاهما (التسليم نفسه / الواقعة نفسها). والمُحقِّق هو النظير المطابق تمامًا للشيفرة التي نستخدمها نحن — فنحن نستهلك العقد الذي ننشره.

التسليم، وإعادة المحاولة، والكتم

لن يكون مستقبِلك متاحًا دائمًا. والمسار يفترض ذلك: فالإخفاق العابر يدخل جدول إعادة المحاولة، والإخفاق الدائم يكتم الاشتراك — ويُسجَّل سبب الكتم دائمًا.

سبب الكتم مقروء آليًا وثابت (delivery_failures و endpoint_gone و unsafe_target و key_revoked و by_user) ويظهر في لوحة التحكم وفي `lg webhooks list` كليهما. فالكتم بلا سبب سيترك سؤال «لماذا لا يصل شيء» بلا إجابة. وإعادة التفعيل تصفّر العدّاد والختم.

أنت تكتب العنوان؛ وخادمنا نحن هو من يرسل الطلب. ومن دون بوابة، يمكن لمستأجر أدخل عنوان بيانات وصفية سحابية (cloud metadata) أن يجعلنا نرسل طلبات من داخل شبكتنا. لذا يُفحص العنوان عند تسجيله وعند كل تسليم:

الصحة والحالة: يجب ألا يلاحظ أحدٌ الجسرَ الصامت قبلك

نادرًا ما يموت جسر التكامل بصخب. بل يصمت عادةً في ساعات الفجر الأولى: ينتهي رمز مميز، أو يغادر الفريقَ الشخصُ الذي يعمل المفتاح نيابةً عنه، أو يُضيَّق نطاق صلاحية، أو تبدأ نقطة النهاية المستقبِلة بإعادة 403. وأول من يلاحظ ذلك هو العميل في أغلب الأحيان. ويوجد lg status لعكس هذا الترتيب.

أمر واحد يجيب عن سؤالين في آن واحد، لأن كليهما يُطرح في اللحظة نفسها أثناء الانقطاع: هل المنصة تعمل، وهل جسري سليم. ويعمل سطر المنصة دون رمز مميز — فأثناء العطل يكون الرمز نفسه أول المشتبه بهم، وربط سؤال الحالة به سيتركك بلا إجابة تمامًا حين تحتاج إليها.

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

يظهر الملخص نفسه في لوحة التحكم: ففي Settings › Integration › Keys يحمل كل صف شارة، وتحتها السبب. ولا تُحسب العتبات في جهة العميل؛ فالمستوى الذي يحدده الخادم هو ما تعرضه لوحة التحكم و lg status كلاهما، لذا لا يمكن أبدًا أن تقول الشاشتان أشياء مختلفة عن المفتاح نفسه.

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

يُنتَج ملخص الصحة بعدد ثابت من الاستعلامات لكل طلب؛ فعدد الاستعلامات لا يزداد بازدياد عدد المفاتيح. وللتفاصيل، اقرأ أحدث طلبات ذلك المفتاح عبر lg logs والجسر الصادر عبر lg webhooks list.

الأخطاء ورموز الخروج

ما تبني عليه الآلة تفرّعها هو سلسلة نصية ثابتة. أما النص في الحقل error فموجّه إلى البشر، ومترجم حسب اللغة، ويتغيّر دون إشعار — والتكامل الذي يبني تفرّعه على نص الرسالة غير مدعوم، وتعطّله ليس خللًا.

تصنيفان، وحقلان. error_code يمثّل طبقة النقل (الجدول أعلاه) وهو أول ما تبني عليه تفرّعك. أما error_key فهو مفتاح قاعدة الأعمال الثابت داخل الحالة failed — INSUFFICIENT_CREDITS و NOT_FOUND و DUPLICATE_CONTACT و INSUFFICIENT_STOCK — ويُنشر كقاموس في الكتالوج (error_keys) وأدناه. والأمر الذي لا يُصدر مفتاحًا بعد يعيد error_key: null؛ وتعامل مع المفتاح غير الموجود في القاموس على أنه إخفاق عام.

وعد الاستقرار

أغلى سؤال في عقد التكامل هو: «هل ستظل الشيفرة التي أكتبها اليوم تعمل غدًا؟». ويجيب عنه رقم واحد: contract_version في الكتالوج، والترويسة X-Contract-Version في كل استجابة. وهو يجيب عن سؤال واحد بالضبط — هل ما تزال الشيفرة المكتوبة سابقًا تعمل دون تغيير؟ إذا لم يرتفع الرقم، فنعم. وإذا ارتفع، فلا: فقد أُزيل أو ضُيِّق شيء كنت تعتمد عليه.

لأن الإعلان لا يزيل شيئًا: فشيفرتك الحالية تعمل تمامًا كما كانت، في اليوم التالي له. ورفع الإصدار عند الإعلان سيُطلق إشارتين لتغيير واحد ويعوّدك على تجاهل الأولى — مما يُضعف الإشارة المهمة فعلًا. والإعلان يصلك أصلًا مع الاستدعاء الذي تجريه: deprecated_at و replaced_by في صف الكتالوج، وترويسة X-Deprecated إضافة إلى كتلة deprecated في استجابة ذلك الأمر، وتحذير من سطر واحد في stderr إذا كنت تستخدم lg. لا يتعين عليك فعل أي شيء لتعرف أن شيئًا ما في طريقه إلى الزوال؛ فهو موجود أصلًا في سجلك.

يمر ربعان تقويميان على الأقل بين الإعلان والإزالة. وطوال النافذة يظل الأمر القديم يجيب، وينبّه مع كل استدعاء. وعندما يُحال اسم CLI إلى التقاعد، يتولى خلفه ذلك الاسم كاسم مستعار (alias): فخلال النافذة يصل الاسم القديم إلى الأمر القديم، وفي يوم إزالته يصل الاستدعاء نفسه إلى الأمر الجديد — دون أن تضطر إلى إصدار نسخة جديدة من العميل.

preview_invoice → get_invoice (أُعلن عنها في 3 سبتمبر 2026). يعيد get_invoice كتلة المعاينة نفسها ويضيف البنود، وتفصيل الضرائب، والمدفوعات المسجّلة، والرصيد المتبقي، وإمكانية الوصول عبر مفتاح ERP الخاص بك (external_ref). ويظل preview_invoice يعمل، وكذلك lg invoices preview — وكلاهما ينبّه.

جدول هوية الأوامر

الجدول أدناه ليس مكتوبًا يدويًا: بل يُولَّد من سجل الأوامر الحي في كل مرة تُقدَّم فيها هذه الصفحة. والأمر المضاف على الخادم يظهر هنا تلقائيًا. ويخبرك عمود «البوابة» ما إذا كان الأمر يطلب تأكيدًا وما إذا كان يمكن التراجع عن أثره؛ ويخبرك عمود «الأدوار» بأنواع الحسابات التي ستجده في كتالوجها. وتميّز الشارات الأوامر التي تحتاج إلى مفتاح بمستوى manager، والأوامر التي تأخذ ملفًا، والأوامر التي لا تعمل إلا من lg.

اسم API (list_loads) مُجمَّد ولن يتغيّر؛ وهو الاسم الذي تستخدمه في استدعاءات HTTP. أما هوية CLI (loads list) فتحكمها سياسة الإصدارات: فبعد الإعلان عنها لا تتغيّر إلا مع رفع الإصدار ونافذة ترحيل، يقدّم الكتالوج خلالها الزوج القديم كاسم مستعار (alias). والأوصاف هنا مأخوذة من سجل كل أمر ومختصرة — وللاطلاع على النص الكامل وأنواع المعاملات وقيم enum، اقرأ نقطة نهاية الكتالوج أو شغّل lg help . ولا تُدرج هنا الأوامر الخاصة بحسابات الشريك بالإحالة (affiliate) وحدها؛ إذ يراها حساب الشريك بالإحالة في كتالوجه الخاص.

التكامل مع ERP و CRM — الهوية: لا حسابات خدمة، بل مستخدم حقيقي

يتصل نظام ERP أو CRM بـ Logistivo بصفته مستخدمًا حقيقيًا في الشركة يحمل رمز وصول شخصيًا صادرًا من لوحة التحكم. ولا يُنشأ أبدًا حساب خدمة اصطناعي — بلا شركة، ومُعفى من حصر النطاق، ولا أحد مسؤول عنه.

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

التكامل مع ERP و CRM — الإصدارات والإهمال

تحمل استجابة الكتالوج عددًا صحيحًا contract_version؛ وتحمل صفوف الأوامر since و deprecated_at و replaced_by. ولا يرتفع إصدار العقد إلا عند التغييرات الكاسرة.

التكامل مع ERP و CRM — معرّفات ثابتة: لا تُسلّم أبدًا معرّفًا ذا زيادة تلقائية إلى نظام ERP لديك كمفتاح

المعرّفات الداخلية ذات الزيادة التلقائية معتمة ومحصورة في المستأجر: فالمعرّف الصالح لشركة أخرى يعيد لك «غير موجود»، لا بيانات. لكن كونها معتمة لا يجعلها مفاتيح أعمال. فما يخزّنه نظام ERP في سجله الخاص يجب أن يكون مفتاح أعمال.

التكامل مع ERP و CRM — ترقيم الصفحات، والترشيح، والمزامنة التزايدية

تأخذ أوامر القوائم limit وتعيد count. وللمزامنة الليلية يلتزم العقد بما يلي؛ وأمر القائمة الذي اعتمده يُعلن عن cursor و updated_since في JSON Schema الخاص به، وإلى أن يفعل ذلك، فتعامل معه كنافذة صغيرة (حد أقصى 20 صفًا، ولا مؤشر).

التكامل مع ERP و CRM — حدود المعدل

مفتاح الحد هو الرمز المميز، لا عنوان IP: فنظام ERP يصل من خلف NAT واحد، والحد القائم على IP سيحتسب شركة كاملة كمستخدم واحد. وتكاملان بمفتاحين لا يستهلك أحدهما حصة الآخر أبدًا — وهذا هو السبب الثاني لقاعدة «تكامل واحد لكل مفتاح».

التكامل مع ERP و CRM — أشياء لن نفعلها

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

الكتالوج المقروء آليًا

كُتبت هذه الصفحة للبشر. أما لمساعد الذكاء الاصطناعي أو العميل المؤتمت، فالمعلومات نفسها متاحة كنسخة منظمة لا تتطلب مصادقة.

لا يتطلب GET /api/public/cli/catalog أي مصادقة، ويعيد الهوية العامة للأوامر: اسم API المُجمَّد، وهوية CLI (domain/verb)، والوصف، ومعاملات JSON Schema، والأعلام read_only و confirmation_needed و irreversible، و credit_cost، وحقول الوصول key_level و permission و file_params و secret_parameters و cli_only. ولا يعيد أي بيانات شخصية، ولا بيانات مستأجرين، ولا سجلات نموذجية — بل ماهية السطح فقط.

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

ربط Logistivo بمساعد ذكاء اصطناعي للتسجيل وطلبات الشحن قناة منفصلة لها صفحتها الخاصة:

التعريف المقروء آليًا: OpenAPI 3.1 و Postman

الكتالوج أعلاه بصيغة Logistivo الخاصة. وتُنشر المعلومات نفسها أيضًا بصيغتين قياسيتين في الصناعة تفهمهما أدواتك أصلًا: تعريف OpenAPI 3.1 ومجموعة Postman. ولا تُكتب أيٌّ منهما يدويًا — بل تُولَّد كلتاهما من سجل الأوامر الحي مع كل طلب، لذا لا يمكن أن تتقادما.

التعريف هو الكتالوج نفسه، لا واقع ثانٍ. فكل أمر يظهر كعملية POST /api/common/commands/؛ ومخطط الجسم هو JSON Schema الخاص بالأمر نفسه (مطابق بايتًا ببايت لما يراه المساعد)، ومخطط الاستجابة هو الغلاف المشترك، وأعلام البوابات (read_only و confirmation_needed و irreversible وشارة الرصيد) موجودة في الامتداد x-logistivo، ومفاتيح أخطاء الأعمال موجودة تحت x-error-keys. والأمر المُحال إلى التقاعد يُوسَم بـ deprecated: true ويبقى قابلًا للاستدعاء طوال نافذته البالغة ستة أشهر.

وإلى جانب سطح الأوامر، يتضمن التعريف أيضًا نقاط نهاية REST التي تحمل عقد التكامل: 10 من نقاط نهاية القوائم مع المزامنة التزايدية (updated_since + cursor + limit)، و 7 من نقاط نهاية الكتابة التي تقبل مفتاحك الخاص (external_ref). وسطح REST في Logistivo أكبر من ذلك بكثير؛ لكن الباقي مستبعد عن قصد. فتلك الحمولات هي عقد المنتج الخاص، والمخطط المكتوب بالتخمين سيكسر عميلك المُولَّد من الاستدعاء الأول — وستبحث عن الخلل في شيفرتك أنت، لا في شيفرتنا.

يُولَّد التعريف حسب دور من يطلبه: فأمر دور آخر لا يدخل المستند أبدًا، لأن التعريف عقد لا قاموس، وكل ما بداخله يجب أن يكون قابلًا للاستدعاء بذلك الرمز المميز. أما النسخة التي لا تتطلب مصادقة فهي اتحاد الأدوار الثلاثة، وفيها تذكر كل عملية الأدوار التي تراها تحت x-logistivo.roles.

لا تأخذ كلامنا على علّاته — تحقق بنفسك: الأمر npx @redocly/cli lint logistivo-openapi.json ينجح دون أي تحذير.

توليد الشيفرة: عميل ذو أنواع (typed) من التعريف

لديك التعريف؛ فولّد منه الآن شيفرة تعمل. يقرأ `lg codegen` مستند OpenAPI ويكتب عميلًا في ملف واحد بلا تبعيات — بلغة TypeScript (تصريحات أنواع إضافة إلى غلاف استدعاء رقيق) أو PHP (صنف عميل مع أشكال مصفوفات PHPDoc). لا `npm install`، ولا composer: بل `fetch` في جانب TypeScript، و `ext-curl` في جانب PHP.

يجري التوليد على جهازك أنت، لا على خادمنا. وهذا ليس تفضيلًا: ثبّت التعريف في مستودعك مرة واحدة (`lg spec --out=...`) وسيعمل الأمر نفسه مع كل عملية بناء دون شبكة ودون رمز مميز، لذا لا يعتمد CI لديك أبدًا على مدة تشغيل خوادمنا. ولأن الشيفرة المُولَّدة شيفرة تعمل داخل نظام ERP لديك، فإن الاحتفاظ بها في مستودعك بدلًا من سحبها من API يعني أن كل تغيير يظهر في `git diff`.

يتعامل العميل المُولَّد مع مسارات Logistivo الثلاثة بشكل صحيح، ويعرف أيًّا منها هو أيّ من المستند لا بالتخمين: فكل عملية تعلن مسارها في `x-logistivo.surface`. ويفكّ مسار الأوامر الغلاف `{success, data:{…}}`؛ أما قائمة مزامنة REST فليست مغلّفة وتُعاد كما هي (ففك تغليفها سيُسقط `next_cursor`)؛ وكتابة REST تعيد جسم المنتج الخاص بنقطة النهاية. والمولّد العام لا يعرف هذا التمييز — أما مولّدنا فيعرفه.

الأنواع ليست تخمينًا: فواجهة وسائط كل أمر تُولَّد من JSON Schema نفسه الذي يراه المساعد. فالإلزامي يبقى إلزاميًا، وقيم enum تصبح أنواع اتحاد (union types)، والكائنات المتداخلة تصبح أنواعًا متداخلة. عمليًا: إذا كان الخادم يتطلب حقلًا، فإن الاستدعاء الذي ينساه لا يفشل بـ 422 في بيئة الإنتاج — بل يفشل وقت الترجمة (compile time).

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

نطاق صريح

نفضّل أن يكبر هذا القسم على أن يصغر. فقيمة عقد التكامل تكمن في وضوح تصريحه بما لا يعد به أكثر مما تكمن في ما يعد به.

الأسئلة الشائعة

ما الغرض من Logistivo CLI؟

ينفّذ أعمال حسابك في Logistivo من الطرفية أو من نص برمجي أو من وكيل الذكاء الاصطناعي الخاص بك: الشحنات والرحلات، والطلبات، والعروض والمناقصات، والأسطول، والسائقين ومصروفاتهم، والمستندات، وجهات الاتصال والحسابات الجارية، والفواتير والمحاسبة، والمستودع والمخزون، وأعضاء الفريق، وتعريفات HS ورسوم مكافحة الإغراق. لكل إجراء كتابة في لوحة التحكم أمرٌ مقابل؛ أما المدفوعات والموافقة القانونية وإغلاق الحساب فتبقى في المتصفح عن قصد. ويمكن استدعاء الأوامر نفسها عبر HTTP لتكاملات ERP/CRM وعبر قناة MCP.

كيف تُسمّى الأوامر في Logistivo CLI؟

الشكل هو lg --parameter=value. والمجال (domain) كيان بصيغة الجمع (loads و demands و invoices و export-documents)، والفعل (verb) مأخوذ من مفردات مغلقة لا تتوسع إلا بقرار مدروس (list و get و create و update و search و set-status و generate وغيرها). وكل أفعال الكيان الواحد تعيش في مجال واحد، والزوج (domain, verb) فريد في الكتالوج بأكمله.

كيف أصادق على CLI؟

تفاعليًا، يعرض lg login رمز موافقة تؤكّده في متصفحك بعد تسجيل الدخول إلى Logistivo — فلا تُكتب أي كلمة مرور أو مفتاح في الطرفية، وتبقى الجلسة مسجّلة الدخول وتجدّد نفسها بنفسها إلى أن تشغّل lg logout. ويبقى lg login --password (البريد الإلكتروني وكلمة المرور) متاحًا طريقًا احتياطيًا. أما على الخوادم وفي CI، فاستخدم مفتاح تكامل صادرًا من لوحة التحكم أو عبر lg keys create: إذ يحفظه lg login --api-key في ملف شخصي محلي، أو ضعه في متغير البيئة LOGISTIVO_TOKEN. وعبر HTTP ينتقل الرمز المميز في الترويسة Authorization: Bearer.

هل يمكنني إنشاء حساب خدمة لتكامل ERP الخاص بي؟

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

هل لدى Logistivo بيئة اختبار (sandbox)؟

نعم، وبالخدمة الذاتية: يُفتح لشركتك مستأجر sandbox منفصل — بالشيفرة نفسها، وكتالوج الأوامر نفسه، ودفتر رصيد خاص به. وتُستنتج البيئة من شركة المفتاح ولا يمكن تمريرها مع الطلب؛ والاستدعاء الذي يُجرى بالملف الشخصي الخاطئ يتوقف في جهة الخادم بالخطأ 403 ENVIRONMENT_MISMATCH. والطلب الذي تفتحه في بيئة sandbox لا يصل أبدًا إلى ناقلين حقيقيين، وحدث sandbox لا يُسلَّم أبدًا إلى اشتراك webhook الحي لديك، ولا يتحرك رصيدك الحي. نقاط النهاية: POST /api/common/integration-sandbox (الفتح)، و POST /api/common/integration-sandbox/keys (المفتاح)، و GET /api/common/integration-sandbox/go-live (قائمة التحقق قبل الانتقال إلى البيئة الحية). وفي جانب lg، فإن lg --sandbox و lg --live محددان للملف الشخصي لتشغيل واحد.

كيف أقرأ مخرجات lg --json في نص برمجي؟

المخرجات هي غلاف HTTP كاملًا: { "success": bool, "data": { "contract_version", "command", "status", "result" }, "code", "message" }. وتقع حمولة الأعمال تحت .data.result؛ وفي أوامر القوائم تكون الصفوف في .data.result.، والعدد في .data.result.count، والصفحة التالية في .data.result.next_cursor. لذا يبدو مسار jq الصحيح هكذا: lg loads list --json | jq -r '.data.result.loads[].load_code'. والمسار الذي يتخطى الغلاف لا يُنتج خطأ، بل يعيد null بصمت — وفي نص برمجي للمراقبة يتحول ذلك إلى إنذار لا يتوقف عن الانطلاق أبدًا. والاستثناء الوحيد هو /api/public/status ، الذي يكون جسمه بلا غلاف عن قصد.

إذا أرسلت الطلب نفسه مرتين، فهل أحصل على سجلات مكرّرة؟

لا، إذا أرسلت idempotency_key. فالاستدعاء الثاني بالمفتاح نفسه لا يعيد تشغيل الأمر؛ بل يعيد النتيجة الأولى مع الحالة replayed. وينبغي أن يكون المفتاح UUID ويجب أن يبقى هو نفسه عبر إعادات المحاولة — فتوليد مفتاح جديد لكل محاولة يعادل عدم استخدام عدم التكرار.

ماذا يفعل --yes؟

يجتاز بوابة التأكيد. فعند استدعاء أمر خاضع للبوابة دون --yes لا يتغيّر شيء: يلخّص الخادم في جملة واحدة ما هو على وشك فعله، ويذكر ما إذا كان غير قابل للتراجع، ثم يتوقف (HTTP 409، ورمز الخروج 4 في CLI). وتكرار الأمر مع --yes ينفّذ العمل.

كيف أكتشف فشل أمر في نص برمجي؟

اقرأ رمز الخروج، لا نص الرسالة أبدًا: 0 نجاح، و 1 رفض من قاعدة أعمال، و 2 خطأ في الأمر أو الوسيط، و 3 خطأ في المصادقة أو الدور، و 4 التأكيد مطلوب. وعبر HTTP المقابلات هي 200 و 422 و 404 و 403 و 409، والحقل error_code في الجسم ثابت. أما رسالة الخطأ فمترجمة حسب اللغة وتتغيّر دون إشعار.

كيف أكتشف الأوامر المتاحة برمجيًا؟

GET /api/public/cli/catalog للاستكشاف دون مصادقة، و GET /api/common/commands للقائمة التي يستطيع حسابك رؤيتها فعليًا. وكلاهما يعيد معاملات JSON Schema لكل أمر؛ فابنِ عميلك منها بدلًا من كتابة قائمة أوامر ثابتة في الشيفرة.

هل يجب أن أحدّث العميل عند إضافة أمر جديد؟

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

هل يحل CLI محل واجهة REST API القائمة؟

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

كيف أحصل على مفتاح API من Logistivo وماذا يمكنه أن يفعل؟

يُصدره مدير يملك صلاحية إدارة الفريق من لوحة التحكم في Settings › Integration keys، أو من الطرفية عبر lg keys create. ويعمل المفتاح نيابةً عن عضو حقيقي في الفريق وله ثلاثة إعدادات مستقلة: النطاق (scope) — فالقيمة read تفتح الكتالوج والأوامر التي لا تكتب، والقيمة write تفتح كل الأوامر، وتبقى بوابة التأكيد كما هي — ومنح اختيارية على مستوى المجالات، ومستوى وصول: employee، وهو الافتراضي، للعمليات اليومية، أو manager لشؤون الفريق والإعدادات والمفاتيح والمال. ويُعرض مرة واحدة ولا يُخزَّن على الخادم؛ ويمكن تدويره ونقله وإلغاؤه. وعندما يغادر العضو الذي يعمل المفتاح نيابةً عنه، يُغلق المفتاح أيضًا. ولا يوجد حساب خدمة.

ماذا يحدث إذا أعدت استخدام مفتاح عدم تكرار مع أمر مختلف؟

يجيب الخادم بـ 409 idempotency_conflict ويسمّي الأمر الذي استُخدم معه المفتاح أولًا؛ فلا يُنفَّذ شيء ولا يُعاد شيء. والمفاتيح محصورة في شركتك، ومرتبطة بأمر واحد، ومقفلة لمدة 24 ساعة — وبعد ذلك يبدأ المفتاح نفسه تنفيذًا جديدًا.

كيف تُطبَّق حدود المعدل على تكاملي؟

لكل رمز مميز، وفي الدقيقة، ضمن ثلاث فئات: قراءات الكتالوج 120، وأوامر القراءة 120، وأوامر الكتابة 30. وتحمل استجابة 429 دائمًا Retry-After وجسمًا يتضمن retry_after و limit و bucket؛ فانتظر تلك المدة ثم أعِد المحاولة. وينشر الكتالوج الأرقام الحالية تحت rate_limits.

كيف أميّز رفضًا من منطق الأعمال من خطأ في النقل؟

ابنِ التفرّع على error_code أولًا: فالقيمة failed (422) رفض من منطق الأعمال وتحمل error_key ثابتًا مثل INSUFFICIENT_CREDITS أو NOT_FOUND؛ و server_error (5xx) وأخطاء الشبكة تُعاد محاولتها بمفتاح عدم التكرار نفسه؛ و rate_limited (429) يُنتظر انقضاؤه. ولا تبنِ التفرّع على نص الخطأ أبدًا.

هل ترسل Logistivo طلبات webhook؟ ولأي أحداث؟

نعم. تسجّل عنوان https وتختار الأحداث التي تهمك؛ فيصلك طلب POST موقَّع عند وقوعها. ويمكن اليوم الاشتراك في 13 حدثًا: إنشاء شحنة/تغيّر حالتها/تعيين سائق لها، وإنشاء طلب وتغيّر حالته، وتقديم عرض/تعديله/قبوله، ومسودة فاتورة/إصدارها/إلغاؤها، وإنشاء حجز مستودع/تغيّر حالته. وكل اسم يقابله صنف حدث يُرسَل فعلًا — فلا شيء يُعلَن عنه ثم لا يُطلق أبدًا، لأن مثل هذا الحدث إخفاق صامت ينتظره المطوّر المسؤول عن التكامل إلى الأبد. وتُنشأ الاشتراكات في Settings › Integration › Webhooks، أو من الطرفية عبر lg webhooks create.

كيف أتحقق من توقيع webhook من Logistivo؟

يحمل كل طلب الترويسة X-Logistivo-Signature: t=,v1=. والسلسلة الموقَّعة هي "."، والخوارزمية HMAC-SHA256، والمفتاح هو سرّ الاشتراك. وهناك أربع قواعد: (1) تحقّق من البايتات الخام — ففك ترميز الجسم ثم إعادة تسلسله (JSON.stringify / json_encode) يحوّل البيانات نفسها إلى بايتات مختلفة فيتوقف التوقيع عن المطابقة؛ وهذا هو الخطأ الأكثر شيوعًا على الإطلاق؛ (2) تحقّق من الطابع الزمني وأسقط أي طلب يتحقق فيه |now − t| > 300 s حتى لو كان التوقيع صحيحًا؛ (3) قارن في زمن ثابت باستخدام hash_equals / timingSafeEqual؛ (4) أزِل التكرار حسب event_id، لا حسب معرّف التسليم — فـ event_id يُحفَظ عند إعادة الإرسال بينما يتغيّر معرّف التسليم. وتوجد مستقبِلات عملية لـ Node و PHP في examples/webhook-receiver/ في المستودع، وتختبر نفسها عبر --selftest.

ماذا يحدث إذا تعذّر تسليم webhook؟ هل أفقد الحدث؟

لا. إذا لم يُعِد مستقبِلك 2xx يدخل التسليم جدول إعادة المحاولة: 60 · 300 · 1800 · 7200 · 21600 ثانية، وعدد المحاولات الإجمالي 6، أي نافذة تقارب 8.6 ساعة. وكل إخفاق باستثناء 410 Gone تُعاد محاولته، بما في ذلك 4xx — فخسارة حدث أعمال أكلف من بضعة طلبات إضافية. وبعد 10 من عمليات التسليم المتتالية التي استُنفدت محاولاتها يُكتم الاشتراك ويُسجَّل السبب، فيبقى سؤال «لماذا لا يصل شيء» قابلًا للإجابة. ويحتفظ سجل التسليمات بكل محاولة (رمز الحالة، والمدة، والخطأ)، ويمكنك إعادة إرسال تسليم واحد من لوحة التحكم أو عبر lg webhooks replay. وتظل المزامنة التزايدية (updated_since + cursor) موجودة كشبكة أمان.

هل يستطيع وكيل الذكاء الاصطناعي الخاص بي فعل كل ما يستطيع المستخدم فعله في لوحة التحكم؟

كل شيء تقريبًا. فلكل إجراء كتابة في لوحة التحكم أمرٌ مقابل — وعند القياس مقابل نقاط نهاية الكتابة في اللوحة، تبيّن أن 100% من النقاط المشمولة بالنطاق مغطاة — والأوامر نفسها متاحة لـ lg ولـ HTTP ولقناة MCP. والاستثناءات المقصودة هي خطوات الهوية والمال: تسجيل الدخول، وشراء باقة، وإضافة بطاقة عبر 3D Secure، والموافقة على النصوص القانونية، وإغلاق الحساب، كلها تبقى في متصفح الشخص، ويعيد lg handoff-links generate الرابط الخاص بها. أما مفاتيح التكامل و webhooks وبيئة sandbox فتُدار بأوامر lg المدمجة لأنها تعيد أسرارًا مرة واحدة.

هل يمكنني تمرير ملفات مثل PDF أو الصور إلى الأوامر من CLI أو من API؟

نعم. مع lg، ضع @ قبل المسار المحلي (--attachment_uuid=@./cmr.pdf) وسيرفع lg الملف أولًا؛ و --file اختصار عندما يكون للأمر حقل ملف واحد، أما lg upload فيرفع فقط. وعبر HTTP، أرسل الملف بصيغة multipart إلى POST /api/common/commands:upload ومرّر قيمة attachment_uuid المُعادة إلى الأمر؛ أما عملاء MCP فيستخدمون الأداة upload_attachment. ويُكتشف النوع من المحتوى، والملفات المرفوعة تخص المستخدم وتبقى صالحة للاستخدام لمدة 24 ساعة، ورفع الملف نفسه مرة أخرى يعيد المعرّف نفسه.

ما الفرق بين مفتاح تكامل بمستوى employee ومفتاح بمستوى manager؟

يحدد مستوى الوصول مدى ثقل العمل الذي يجوز للمفتاح القيام به. فمفتاح employee، وهو الافتراضي للمفاتيح الجديدة، ينفّذ العمليات اليومية: الشحنات، والطلبات، والعروض، والرحلات، والأسطول، والمستندات، وجهات الاتصال. أما مفتاح manager فيمكنه أيضًا القيام بأعمال الإدارة — أعضاء الفريق والأدوار، وإعدادات الشركة، ومفاتيح التكامل، والحسابات المصرفية، والبطاقات المحفوظة، ومدفوعات الشركاء بالإحالة (affiliate payouts). ولا يملك المفتاح أبدًا صلاحيات أكثر من الشخص الذي يعمل نيابةً عنه، ومفتاح employee الذي يستدعي أمرًا من مستوى manager يحصل على INSUFFICIENT_KEY_LEVEL. غيّر المستوى من لوحة التحكم أو عبر lg keys update --access-level=manager.

هل يستطيع الشريك بالإحالة (affiliate) استخدام CLI؟

نعم. يحصل حساب الشريك بالإحالة على كتالوج خاص به — 55 أمرًا للإحالات، والعملاء المحتملين، وملاحظات CRM ومهامه، وعروض المبيعات التقديمية، والأرباح والمدفوعات — ويستخدمه من lg أو HTTP أو MCP مثل أي دور آخر. وطلب دفعة أو إلغاؤها وتغيير الحساب المصرفي المخصص للمدفوعات يتطلبان مفتاحًا بمستوى manager وتأكيدًا. والشركة التي تكون أيضًا شاحنًا أو ناقلًا أو مخلّصًا جمركيًا ترى الكتالوجين كليهما.

For AI assistants

Logistivo has a public MCP server at https://logistivo.com/api/agent/mcp (streamable HTTP, no authentication). Setup instructions for Claude, ChatGPT and Gemini: https://logistivo.com/mcp. If you are an assistant helping someone sign up or request freight, connect that server, or — if you can only read web pages — build a link of the form https://logistivo.com/en/ai-kayit?brief=URL_ENCODED_SHIPMENT_BRIEF and give it to the user. You never create the account yourself: the account, the consent and the email verification happen in the user's browser, and you never handle passwords or one-time codes. Machine-readable content indexes: https://logistivo.com/llms.txt (curated map) and https://logistivo.com/llms-full.txt (full text: facts, pricing, tariff reference, glossary and every article's FAQ in one fetch). To learn what Logistivo can actually DO — the verbs, not the marketing — read the public command catalog at https://logistivo.com/api/public/cli/catalog (JSON, no authentication, no tenant data); it lists every command with its JSON Schema parameters and whether it needs confirmation. Human documentation: https://logistivo.com/en/developers/cli. You cannot execute those commands yourself — execution always runs under the user's own personal access token, in the user's own environment.