Nordlet

← الأساسيات / حزم تطوير البرمجيات (SDK)

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

هيكل الطلب، نطاقات المصادقة، استعلامات القوائم، المبالغ النقدية، الأخطاء، الثبات (idempotency)، حدود معدل الاستخدام.

هيكل الطلب

كل عملية هي طلب POST بنمط RPC:

POST /v1/{module}/{resource}/{action}

الوحدات النمطية: reference، partners، catalog، sales، purchases، ledger، bank، declarations، files، webhooks، audit. والإجراءات هي أفعال: create، get، update، delete، list، بالإضافة إلى إجراءات النطاق مثل issue، register، match، apply-advance، generate.

المصادقة والنطاقات (Scopes)

Authorization: Bearer <api key>. تحمل المفاتيح نطاقات يتم التحقق منها لكل إجراء:

  • {module}:read - إجراءات العرض/القائمة (get/list)
  • {module}:write - التعديلات (mutations)
  • {module}:* أو * - الرموز العامة (wildcards)

النطاق المفقود ← 403 forbidden. المفتاح المفقود أو غير الصالح ← 401 unauthorized.

استعلامات القوائم

تتشارك جميع إجراءات list في عقد واحد:

{
  "page": 1,
  "pageSize": 50,
  "sort": [{ "field": "createdAt", "dir": "desc" }],
  "filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}

عوامل التصفية: eq (يساوي)، ne (لا يساوي)، contains (مطابقة نصية لا تتأثر بحالة الأحرف، للحقول النصية فقط)، gte (أكبر من أو يساوي)، lte (أقل من أو يساوي)، in (أي قيمة من قائمة تصل إلى 500 قيمة). الحقول القابلة للفرز والتصفية مدرجة في القائمة البيضاء لكل نقطة نهايات (راجع مواصفات OpenAPI)؛ وترجع الحقول غير المعروفة الخطأ 400. أضف totals: ["field", …] إلى الطلب لجمع الحقول الرقمية عبر كل صف مطبق؛ وعندما تحمل السجلات عملة ما، يوفر الحقل totalsByCurrency نفس المجاميع مقسمة حسب رمز العملة. الاستجابات: { rows, total, page, pageSize, totals?, totalsByCurrency? }.

المبالغ النقدية والتواريخ

القيم النقدية هي سلاسل عشرية تحتوي على ما يصل إلى 4 منازل عشرية ("121.0000") - وليست أعداداً عائمة أبداً. يتم احتساب ضريبة القيمة المضافة (VAT) لكل بند مع التقريب إلى أعلى في حال النصف (half-up rounding). التواريخ بالتنسيق YYYY-MM-DD؛ والطوابع الزمنية بالتنسيق ISO 8601 UTC.

الأخطاء

هيكل موحد في كل مكان:

{
  "error": {
    "code": "validation",
    "message": "Request validation failed",
    "requestId": "k1x…",
    "key": "request_invalid",
    "fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
  }
}

الرموز: validation (400/422، و413 عندما يكون الملف المرفع أو نص الطلب كبيراً جداً)، unauthorized (401)، payment_required (402، انتهت الفترة التجريبية أو الرصيد المدفوع مقدماً؛ توضح الرسالة طريقة المتابعة)، forbidden (403)، not_found (404)، conflict (409)، idempotency_key_reuse (422)، idempotency_in_progress (409)، rate_limited (429)، internal (5xx). عندما تكون الرسالة إحدى الرسائل الثابتة، يحددها الحقل key لكي يتمكن العميل من عرض ترجمته الخاص، بينما يحمل الحقل params القيم المضمنة فيها (على سبيل المثال { "period": "2026-09" } لفترة محاسبية مقفلة). يرجى تضمين requestId عند الإبلاغ عن المشكلات.

الثبات (Idempotency)

أضف Idempotency-Key: <any string ≤255 chars> إلى أي طلب تعديل:

  • إعادة المحاولة بنفس المفتاح والحمولة (payload) ← يتم تشغيل الاستجابة المخزنة حرفياً مع ترويسة x-idempotent-replay: true.
  • نفس المفتاح، حمولة مختلفة ← 422 idempotency_key_reuse.
  • طلب متزامن مكرر بينما الطلب الأول قيد التنفيذ ← 409 idempotency_in_progress.
  • تنتمي المفاتيح إلى مفتاح واجهة برمجة التطبيقات أو المستخدم الذي أرسلها، ضمن الشركة التي يُنفذ الطلب لصالحها، بحيث يمكن لعمليتي تكغام تابعة لنفس الشركة استخدام نفس المفتاح. الطلبات المُجراة قبل إنتاج الشركة، وطلبات account/*, تحتفظ بالمفاتيح لكل مستخدم، بحيث يؤدي تكرار استدعاء account/companies/create إلى إنشاء شركة واحدة.
  • لا يتم إرجاع الاستجابة المخزنة إلا بعد اجتياز المستدعي لفحوصات الأذن مرة أخرى بنجاح (النطاق، الدور، الشركة، وحالة الفوترة)؛ وإلا يحصل الطلب على الخطأ الحالي.
  • تنتهي صلاحية المفاتيح بعد 24 ساعة. يتم إعادة تشغيل استجابات الأخطاء (4xx) أيضاً؛ بينما لا يتم تخزين استجابات (5xx) لكي يتم إعادة تنفيذ الطلبات عند إعادة المحاولة.

حدود معدل الاستخدام (Rate limits)

300 طلب/دقيقة لكل مفتاح واجهة برمجة التطبيقات (لكل بيانات اعتماد مقدمة؛ والطلبات غير المصادق عليها يتم تحديدها بناءً على عنوان IP). عند ظهور الخطأ 429، يرجى الالتزام بترويسة retry-after. توضح ترويسات x-ratelimit-* رصيدك المتاح.

الويب هوك (Webhooks)

تتم كتابة الأحداث في جدول معاملات خارج الصندوق (transactional outbox) ضمن نفس معاملة قاعدة البيانات الخاصة بالتغيير - المستند الذي تم التراجع عن معاملته لا يصدر حدثاً أبداً، ولا يضيع أي حدث. عمليات التسليم:

  • إرسال طلب POST إلى عنوان URL الخاص بك مع بيانات الحدث بصيغة JSON.
  • x-nordlet-timestamp: <unix seconds>، وهو الوقت الذي تم فيه توقيع عملية التسليم.
  • x-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>"> باستخدام سر الاشتراكات الخاص بك.
  • x-nordlet-signature: sha256=<hex HMAC-SHA256 of the raw body>، مُبقاة دون تغيير للمستقبلين الحاليين.
  • x-nordlet-delivery يحمل معرف التسليم، وهو ثابت في كل إعادة محاولة لنفس عملية التسليم.
  • تتم إعادة محاولة إرسال الاستجابة التي لا تتبع نطاق 2xx أو عمليات إعادة التوجيه بعد 30 ثانية، دقيقتين، 10 دقائق، 30 دقيقة، ساعة واحدة، 3 ساعات، 6 ساعات، و12 ساعة، أي ما يقارب 24 ساعة إجمالاً، قبل وسم عملية التسليم بالفشل.
  • يتم إرسال كل عملية تسليم بواسطة خادم واحد في كل مرة، لذا فإن تشغيل عدة نُسخ من واجهة برمجة التطبيقات لا يؤدي إلى إرسالها مرتين.

تحقق من صحة x-nordlet-signature-v2 باستخدام مقارنة زمنية ثابتة (constant-time comparison) قبل الوثوق بالحمولة، وارفض عملية التسليم التي يبتعد طابعها الزمني عن وقت ساعتك بأكثر من 5 دقائق. الطابع الزمني هو جزء من النص الموقع، لذا لا يمكن إعادة تشغيل عملية تسليم ملتقطة لاحقاً باستخدام طابع زمني جديد. قم بتخزين معرفات x-nordlet-delivery التي عالجتها لتجاهل التكرارات خلال تلك النافذة الزمنية. يمكن إعادة إرسال عملية التسليم الفاشلة باستخدام webhooks/deliveries/redeliver.

التدقيق (Audit)

يتم تسجيل كل عملية تعديل (actor، action، entity، diff) ويمكن الاستعلام عنها عبر audit/list.

الضمانات المحاسبية

  • قيود دفتر اليومية متوازنة - ويتم فرض ذلك بواسطة مشغل قاعدة بيانات مؤجل (deferred database trigger) وقت الاعتماد، وليس فقط عبر رمز التطبيق.
  • أرقام المستندات خالية من الفجوات لكل سلسلة/سنة؛ وتخصيصها آمن من حيث التزامن.
  • الفترات المحاسبية المقفلة ترفض أي قيد يحمل تاريخاً يقع ضمن نطاقها (409).
  • المستندات المحذوفة صورياً (soft-deleted) تحتفظ بمسار التدقيق الخاص بها؛ ولا يمكن حذف المستندات الصادرة أو المسجلة.