المطورون

المصادقة ومفاتيح API

كيف تعمل مفاتيح API في وندرفاتورة: إرسالها وصلاحياتها وانتهاؤها وتجديدها، ولماذا لا يستطيع المفتاح أبدًا أكثر مما يستطيعه منشئه.

إرسال المفتاح

كل طلب يحتاج مفتاح API يُرسل في ترويسة Authorization بصيغة bearer: Authorization: Bearer <key>. وتُقبل ترويسة X-Api-Key بديلًا. المفتاح في سلسلة الاستعلام مرفوض، لأن الروابط تُحفظ في السجلات.

# Same as the Bearer header; use whichever your HTTP client makes easier.
curl https://fatoora.tw.sa/api/v1/ping \
  -H "X-Api-Key: wbk_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Accept: application/json"

كل الطلبات عبر HTTPS وبصيغة JSON. أرسل Accept: application/json مع كل طلب، وContent-Type: application/json مع أي محتوى.

الصلاحيات

لا يستطيع المفتاح إلا ما مُنح له. امنح كل نظام أقل ما يحتاجه.

الصلاحية تسمح بـ
companies:read الاطلاع على ملف المنشأة ومدى جاهزيتها للإصدار (GET /company وGET /company/readiness).
customers:read عرض العملاء والاطلاع عليهم (GET /customers وGET /customers/{id}). وتحتاجها أيضًا أحداث العملاء في الـ Webhooks.
customers:write إنشاء العملاء وتعديلهم (POST /customers وPATCH /customers/{id}).
products:read البحث عن المنتجات والخدمات والاطلاع عليها عبر Wonder Fatoora MCP (search_products وget_product). لا تستخدمها أي نقطة نهاية REST حتى الآن.
products:write إنشاء المنتجات والخدمات وتعديلها عبر Wonder Fatoora MCP (create_product وupdate_product). ويجب أيضًا أن يكون الشخص الذي تمثّله بيانات الاعتماد مخوّلًا بإدارة المنتجات.
invoices:read الاطلاع على الفواتير وحالتها وإشعاراتها وقائمة الأحداث (GET /invoices وGET /invoices/{id} وGET /notes/{id} وGET /events). وتحتاجها أحداث الفواتير والإشعارات في الـ Webhooks، ولا يعيد طلب الإنشاء المكرر الفاتورة كاملة إلا لبيانات اعتماد تملكها.
invoices:draft إنشاء الفواتير والإشعارات الدائنة والمدينة كمسودات والتحقق من المسودات (POST /invoices وPOST /invoices/{id}/notes وPOST /invoices/{id}/validate). ويستمر اسمها الأصلي invoices:write في العمل.
invoices:issue إصدار الفواتير والإشعارات (POST /invoices/{id}/issue وPOST /notes/{id}/issue). مطلوبة إضافة إلى invoices:draft كلما أصدر طلب الإنشاء فاتورة، وهو الافتراضي. الإصدار لا رجعة فيه، لذلك له صلاحية مستقلة.
invoices:download تنزيل ملف PDF وملف XML النظامي للفواتير والإشعارات (GET /invoices/{id}/pdf وGET /invoices/{id}/xml، ومثلهما لـ /notes/{id}). لا تشملها invoices:read.
payments:write تسجيل دفعات العملاء على الفواتير الصادرة عبر Wonder Fatoora MCP (record_payment، وتحتاج أيضًا invoices:read). ويجب أيضًا أن يكون الشخص الذي تمثّله بيانات الاعتماد مخوّلًا بتسجيل الدفعات.
webhooks:manage تسجيل نقاط استقبال الـ Webhooks وتعديلها وحذفها وتجديد أسرارها، والاطلاع على عمليات تسليمها وإعادة إرسالها (/webhook-endpoints). ويجب أيضًا أن يكون الشخص الذي تمثّله بيانات الاعتماد مخوّلًا بإدارة الإعدادات.

غياب صلاحية يعيد 403 insufficient_scope، ويسمّي details.required_scope الصلاحية التي يحتاجها المفتاح (ويحمل details.required_ability اسمها الأصلي، invoices:write بدل invoices:draft، للعملاء الأقدم). والمفتاح المنشأ قبل وجود الصلاحيات يملك invoices:read وinvoices:draft وinvoices:issue فقط.

المفتاح يعمل باسم منشئه

يعمل كل مفتاح باسم المستخدم الذي أنشأه (أو آخر من جدّده)، بصلاحيات ذلك المستخدم وقت كل طلب. إنشاء فاتورة يتطلب أن يكون المستخدم مخوّلًا بإنشاء الفواتير، والإصدار يتطلب أيضًا تخويله بإصدارها. إن قُيّد دور المستخدم لاحقًا تقيّد المفتاح أيضًا (403 forbidden)، وإن غادر المستخدم المنشأة توقف المفتاح (401).

الباقة

الوصول إلى الواجهة البرمجية جزء من باقتي الأعمال والمؤسسات. إن انتقلت المنشأة إلى باقة لا تشمله، تعيد مفاتيحها 403 plan_upgrade_required حتى تعود، ويظل بالإمكان عرض المفاتيح وإلغاؤها.

لإيصال عميل جديد إلى مفتاحه مباشرة أعطه https://fatoora.tw.sa/start?plan=enterprise&intent=api: يسجّل أو يدخل، ويدفع اشتراك الباقة، ثم يصل إلى الصفحة التي تنشئ مفتاحه. ومن دون plan يبدأ بالتجربة المجانية وتبيّن له تلك الصفحة ما يشترك فيه.

الانتهاء والتجديد والإلغاء

  • ينتهي المفتاح بعد المدة المختارة عند إنشائه: 30 أو 90 أو 180 أو 365 يومًا. لا يوجد مفتاح دائم.
  • جدّد المفتاح من الإعدادات ← مفاتيح API: يُنشأ بديل بنفس الصلاحيات والمدة، ويتوقف المفتاح القديم في اللحظة نفسها. ضع المفتاح الجديد في مكانه فورًا.
  • ألغِ المفتاح من هناك في أي وقت فيتوقف فورًا.
  • يُظهر كل مفتاح متى استُخدم آخر مرة ومن أي عنوان، فيسهل اكتشاف ربط منسي.
  • قبل انتهاء مفتاح التشغيل بأربعة عشر يومًا ثم بثلاثة أيام، يصل إلى منشئه بريد فيه زر لتجديده؛ وإن كان قد غادر المنشأة يصل إلى مديريها بدلًا منه. والمفتاح الذي لم يعد أحد يستخدمه يمكن تركه ينتهي.

المفتاح المنتهي يجيب بـ 401 token_expired، مع يوم انتهائه في الرسالة، ووقته الدقيق في details.expired_at، والصفحة التي تجدّد منها المنشأة مفاتيحها في details.renew_url. أما كل رفض آخر (مفتاح مفقود أو غير معروف أو ملغى، أو غادر منشئه) فيبقى 401 unauthorized دون ذكر السبب.

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="The API key has expired"

{
  "ok": false,
  "error": {
    "code": "token_expired",
    "message": "This API key expired on 2026-11-03. Create or renew a key in the developer portal.",
    "details": {
      "renew_url": "https://fatoora.tw.sa/settings/developers/keys",
      "expired_at": "2026-11-03T06:12:44+00:00"
    }
  }
}

من يدير المفاتيح

إنشاء المفاتيح وتجديدها وإلغاؤها يتطلب صلاحية إدارة الإعدادات، ويملكها مدير المنشأة. يُعرض المفتاح الجديد مرة واحدة ولا يظهر بعدها أبدًا.

التطبيقات وOAuth 2.1

التطبيق الذي يعمل باسم منشآت غير منشأة ناشره يستخدم OAuth 2.1 بدل المفاتيح. سجّله من الإعدادات ← المطورون ← تطبيقاتي: تحصل على client_id (wfapp_…)، وعلى سرّ عميل (wfsec_…) يُعرض مرة واحدة إن كان التطبيق يعمل على خوادمك. ثم توافق كل منشأة على تطبيقك في شاشة موافقة من وندرفاتورة، فتختار المنشأة وترى بالضبط ما يطلب التطبيق فعله.

نقطة النهاية الاستخدام
GET /oauth/authorize أرسل الشخص إليها ليوافق على تطبيقك: response_type=code وclient_id وredirect_uri وscope وstate وcode_challenge وcode_challenge_method=S256.
POST /oauth/token grant_type بقيمة authorization_code (مع code_verifier) أو refresh_token أو client_credentials. تحقق الهوية بـ HTTP Basic أو بإرسال client_id وclient_secret في المحتوى.
POST /oauth/revoke إلغاء رمز وصول أو رمز تحديث (RFC 7009). تجيب دائمًا 200.
GET /.well-known/oauth-authorization-server بيانات الخادم الوصفية (RFC 8414)، و/.well-known/oauth-protected-resource تصف الواجهة البرمجية (RFC 9728).
  • PKCE إلزامي لكل تطبيق بطريقة S256، وطريقة plain مرفوضة.
  • يجب أن يطابق redirect_uri عنوانًا سجّلته حرفيًا: بلا رموز بدل ولا مسار أو شرطة زائدة. تطبيقات الأجهزة يمكنها تسجيل http://127.0.0.1 واستخدام أي منفذ.
  • state مطلوب ويعود كما هو، ومعه iss باسم الجهة المصدرة.
  • الرمز (code) يعمل مرة واحدة خلال دقيقتين، وتقديمه مرة ثانية يلغي الرموز التي منحها.
  • لنقطتي الرموز والإلغاء حد للطلبات لكل عنوان ولكل تطبيق، وبعد تجاوزه تعيدان 429 مع {"error": "temporarily_unavailable"} وترويسة Retry-After: انتظر عدد الثواني المذكور فيها.
  • رموز الوصول (wfo_at_…، وwfo_test_at_… في منشأة الاختبار) صالحة ساعة واحدة وتُرسل في Authorization: Bearer. رموز التحديث تتجدد مع كل استخدام، وإعادة استخدام رمز قديم تلغي المنح كله.
  • اطلب resource=https://fatoora.tw.sa/api. لا يُقبل الرمز إلا في المورد الذي صدر له.
  • بيانات اعتماد العميل (client credentials) تمنح التطبيق السري رمزًا لمنشأته هو فقط.

يعمل الرمز باسم الشخص الذي وافق على التطبيق وبصلاحياته في تلك المنشأة، كما يعمل المفتاح باسم منشئه. ويتوقف حين تفصل المنشأة التطبيق (الإعدادات ← المطورون ← التطبيقات المرتبطة)، أو يُحذف التطبيق، أو يغادر ذلك الشخص المنشأة أو يفقد صلاحية إدارة إعداداتها. الرمز المرفوض يعيد 401 invalid_token.

جاهز للبدء؟

الوصول إلى الواجهة البرمجية ضمن باقات: الأعمال والمؤسسات. أنشئ مفتاحًا من الإعدادات ← مفاتيح API وأرسل أول طلب خلال دقائق.