إلزامية الفوترة الإلكترونية تتوسّع تدريجياً في الأردن — اعرف إن كان منشأتك مُلزَمة ومتى
الإصدار v1 — مستقر

واجهة فواترا البرمجية

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

الأساس: https://fawtara.codexal.co/api/v1 المصادقة: ترويسة X-Api-Key الصيغة: JSON · UTF-8 احصل على مفتاح ←
هذه صفحة مرجعية سريعة. التوثيق الكامل والتفاعلي — بما فيه الإشعارات الدائنة، معاينة UBL، الأمثلة بستّ لغات، ومواصفة OpenAPI — داخل بوابة المطوّرين: افتح التوثيق الكامل · OpenAPI 3.1 · أنشئ حساباً واحصل على مفتاح

العنوان الأساسي

جميع النداءات تمرّ عبر HTTPS. الطلبات غير المشفّرة تُرفض.

Base URL
https://fawtara.codexal.co/api/v1
إن كان خادمك لا يدعم الروابط النظيفة تعمل الصيغة /api/v1/index.php/invoices في كل الإعدادات دون أي تهيئة إضافية، وتعطي النتيجة نفسها.

المصادقة

كل طلب يحمل مفتاحك في ترويسة Authorization: Bearer <key> (وتُقبل X-Api-Key كبديل متوافق). نحفظ هاش SHA-256 للمفتاح فقط — لا يمكننا استرجاعه لك، فاحفظه عند إنشائه.

Headers
X-Api-Key: fwt_live_7Kd2pQw9xZmR4vT8nL1sB6yH3cF0aJeU
Content-Type: application/json
لا تستخدم المفتاح في المتصفح المفتاح يمنح صلاحية إصدار فواتير باسم منشأتك. استدعِ الواجهة من خادمك فقط، ولا تضعه في كود JavaScript أو تطبيق جوال.

مفاتيح JoFotara — من أين تأتي

مفتاح فواترا (X-Api-Key) يصادقك لدينا. أما الإرسال الفعلي إلى الدائرة فيتم بمفاتيح منشأتك الصادرة من منصة نظام الفوترة الوطني نفسها. لا يصدرهما أي مزوّد خدمة — تولّدهما بنفسك من شاشة «ربط الأجهزة».

يمكن للمستخدم الرئيسي (Admin) من خلال شاشة ربط الأجهزة ربط برنامجه الخاص لإصدار الفواتير (Integration) ليتم ترحيل الفواتير من خلاله.

نظام الفوترة الوطني — دليل المستخدم الخاص بمنصة الـPortal، «ربط الأجهزة»
جدول ربط الأجهزة في منصة الفوترة الوطني: المستخدم وحالته ورقم المستخدم والمفتاح السري وتسلسل مصدر الدخل
شاشة «ربط الأجهزة» بعد إنشاء ربط. رقم المستخدم هو Client-Id، والمفتاح السري هو Secret-Key، وكلاهما مقيّد بـتسلسل مصدر دخل واحد.

الخطوات كما وردت في الدليل

  1. الدخول إلى نظام الفوترة الإلكتروني بالمستخدم الرئيسي (Admin).
  2. الضغط على «ربط الأجهزة» من الشاشة الرئيسية.
  3. الضغط على زر «ربط جديد».
  4. إدخال اسم المستخدم للربط وتحديد تسلسل مصدر الدخل ثم الضغط على زر الإضافة.
  5. الضغط على زر المتابعة للرسالة التنبيهية.

نصّ الرسالة التنبيهية في الخطوة الأخيرة:

لن يتمكن المكلف من تنظيم الفواتير باستخدام المنصة إذا قام بالربط مع الأجهزة.

دليل المستخدم — «ربط الأجهزة»، الخطوة 5

بعد تأكيد الربط يصبح نظامك المصدر الوحيد لفواتير ذلك التسلسل، ولا يعود بالإمكان إصدارها يدوياً من المنصة. اختبر كل مساراتك في Sandbox أولاً.

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

البيئتان

البادئة في المفتاح تحدّد البيئة — لا يوجد عنوان منفصل للاختبار.

البادئةالبيئةالإرسال الحكوميتُحتسب من الحصّة
fwt_test_Sandboxلا — محاكاة فقطلا
fwt_live_Liveنعمنعم

في Sandbox يجري التحقّق الكامل وبناء UBL فعلياً، لكن الملف لا يُرسل إلى الدائرة وتعود الحالة sandbox_accepted. هذا يتيح اختبار منطقك كاملاً دون استهلاك أرقام فواتير حقيقية.

إنشاء فاتورة وإرسالها

النقطة الأساسية: تبني UBL 2.1، تتحقّق منه، ترسله إلى نظام الفوترة الوطني، وتعيد النتيجة في الاستجابة نفسها.

POST/api/v1/invoices
curl -X POST https://fawtara.codexal.co/api/v1/invoices \
  -H "X-Api-Key: fwt_live_•••••••••" \
  -H "Idempotency-Key: INV-2026-0418" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "INV-2026-0418",
    "invoice_type":   "388",
    "payment_method": "011",
    "invoice_date":   "2026-04-18",
    "currency":       "JOD",
    "buyer": {
      "name":    "شركة النور للتجارة",
      "tin":     "9871234",
      "city":    "Amman",
      "phone":   "0791234567"
    },
    "items": [
      { "name": "استشارات تقنية", "qty": 1, "unit_price": 450, "tax_rate": 16 },
      { "name": "ترخيص سنوي",    "qty": 2, "unit_price": 120, "discount": 20, "tax_rate": 16 }
    ]
  }'

استجابة ناجحة — 201 Created

201 تعني قبول الدائرة للفاتورة. إن عادت 202 فقد أُنشئت لدينا ولم تُقبل بعد — اقرأ data.error ولا تعتبرها نجاحاً.

Response
{
  "data": {
    "id":             "inv_5c8d1e9a2b7f3046",
    "object":         "invoice",
    "mode":           "live",
    "status":         "accepted",
    "invoice_number": "INV-2026-0418",
    "uuid":           "8f3c1e42-5a7b-4c9d-9e10-2b7a64f3b41d",
    "icv":            42,
    "type_code":      "388",
    "type_name":      "012",
    "totals": {
      "subtotal":       690.000,
      "discount_total": 20.000,
      "tax_total":      107.200,
      "total":          777.200
    },
    "qr_content":   "AQ3YtNix…",
    "qr_image_url": "https://fawtara.codexal.co/api/v1/invoices/inv_5c8d1e9a2b7f3046/qr.png",
    "ubl_url":      "https://fawtara.codexal.co/api/v1/invoices/inv_5c8d1e9a2b7f3046/ubl",
    "jofotara":     { "status": "SUBMITTED", "http_code": 200 },
    "error":        null,
    "submitted_at": "2026-04-18 09:14:03"
  }
}

فشل التحقّق — 422

لا نستهلك نداءً حكومياً إن كانت الفاتورة سترفَض. حقل fields يسمّي كل حقل خاطئ بمساره الكامل.

422 Unprocessable
{
  "error": {
    "type":    "validation_error",
    "code":    "validation_error",
    "message": "بيانات الطلب غير صحيحة.",
    "fields": {
      "payment_method":   "طريقة الدفع غير متوافقة مع نوع الفاتورة. المسموح: 013 أو 023.",
      "seller.income_seq": "تسلسل مصدر الدخل مطلوب — حقل إلزامي لدى الدائرة.",
      "items[1].qty":      "الكمية يجب أن تكون أكبر من صفر."
    }
  }
}

حقول الطلب

الحقلالنوعإلزاميالوصف
invoice_number string نعم رقم الفاتورة لديك. يجب أن يكون فريداً.
invoice_type string نعم 388 فاتورة ضريبية، 381 إشعار دائن.
payment_method string نعم مع 388: 011 نقدي أو 021 ذمم. مع 381: 013 أو 023.
invoice_date string لا بصيغة YYYY-MM-DD. الافتراضي تاريخ اليوم.
currency string لا JOD (افتراضي) أو USD أو EUR.
seller object لا يتجاوز بيانات البائع المحفوظة مع المفتاح. الحقول: name, tin, income_seq, street, city, country.
buyer object نعم name مطلوب. اختيارياً: tin, city, country, phone.
items[] array نعم بند واحد على الأقل. لكل بند: name, qty, unit_price, واختيارياً discount و tax_rate.
dry_run boolean لا يبني ويتحقّق دون إرسال حكومي. مفاتيح Sandbox تعمل بهذا الوضع دائماً.
include_xml boolean لا يُرجع ملف UBL المُولَّد ضمن الاستجابة للتدقيق.
المبالغ تُحتسب عندنا لا ترسل مجاميع. نحسب لكل بند: الأساس = (الكمية × السعر) − الخصم، والضريبة = الأساس × النسبة، مقرّبة إلى ثلاث خانات عشرية كما تتطلب الدائرة.
تسميات بديلة مقبولة. الواجهة تقبل الصيغتين: buyer/customer، items/lines، qty/quantity، tax_rate/tax_percent، invoice_date/issue_date. كما تُقبل أكواد الدفع الرقمية (011, 021 …) أو القيم النصّية (cash, receivable). التسميات المعتمدة في التوثيق الكامل هي الثانية في كل زوج.

مطابقة حقول شاشة المنصة بحقول الـAPI

إن كنت تصدر فواتيرك اليوم يدوياً من منصة الـPortal، فهذه الخريطة تختصر عليك مرحلة التحليل: كل حقل في شاشة «تنظيم فاتورة» وما يقابله في نداء POST /api/v1/invoices.

يتم تمييز الحقول الإجبارية بوجود علامة *.

نظام الفوترة الوطني — دليل المستخدم الخاص بمنصة الـPortal، «تنظيم فاتورة»
شاشة تنظيم فاتورة في منصة الفوترة الوطني: بيانات الفاتورة وبيانات البائع وبيانات المشتري وبنود السلع والمجاميع
شاشة «تنظيم فاتورة» في المنصة — وهي المرجع الذي بُنيت عليه حقول نداء الإنشاء لدينا.
حقل الشاشةما يقابله في الـAPIملاحظة من الدليل
رقم فاتورة البائع invoice_number الرقم التسلسلي للفاتورة الخاص بالبائع.
تاريخ إصدار الفاتورة * invoice_date يُضبط بتاريخ اليوم مع إمكانية تغييره لتاريخ سابق — لا لتاريخ لاحق.
نوع العملة * currency في المنصة لا يمكن تغييره بعد إضافة أول سلعة. عبر الـAPI تُرسل الفاتورة بعملة واحدة دفعة واحدة.
فاتورة نقدية / فاتورة ذمم payment_method 011 نقدي، 021 ذمم (ومع الإشعار الدائن 013 و023).
نوع الفاتورة: محلية / تصدير / مناطق تنموية * items[].tax_rate + buyer.tin «محلية» مختارة تلقائياً. «تصدير» و«مناطق تنموية/تشجيع استثمار» بنسبة ضريبة 0%، والثانية يجب فيها إدخال الرقم الضريبي للمشتري.
بيانات البائع seller (اختياري) في المنصة تُدخل تلقائياً من بيانات التسجيل. لدينا تُؤخذ من إعدادات المفتاح، وseller يتجاوزها عند الحاجة.
اسم المشتري buyer.name إجباري لفواتير الذمم وللفواتير بقيمة 10,000 وأكثر.
نوع المعرفات الإضافية + رقم المشتري buyer.tin الرقم الوطني أو الرقم الضريبي أو الرقم الشخصي.
رقم الهاتف / المدينة / الرمز البريدي buyer.phone، buyer.city اختيارية، لكنها تُحسّن قابلية مطابقة الفاتورة لدى المشتري.
وصف السلعة أو الخدمة * items[].name تفاصيل السلعة أو الخدمة.
الكمية * / سعر الوحدة * items[].qty، items[].unit_price لا ترسل مجاميع — نحسبها كما تحسبها المنصة.
قيمة الخصم items[].discount خصم على مستوى البند، يُطرح قبل احتساب الضريبة.
نسبة الضريبة العامة * items[].tax_rate لا تظهر لفواتير الدخل. يمكن أن تختلف النسبة من بند لآخر.
النوع (سلعة/خدمة أو بدل خدمة) * — لا تظهر لفواتير الدخل. نضبطها تلقائياً في UBL بما يوافق نوع المكلف المسجّل مع المفتاح.
التصنيف الوطني للأنشطة — اختياري في الشاشة. نرسله من إعدادات منشأتك عند ضبطه.
قيمة الضريبة الخاصة * تواصل معنا تخصّ فواتير الضريبة الخاصة فقط. راسلنا لتفعيلها على مفتاحك.

أشكال الفواتير الثلاثة حسب نوع المكلف

فاتورة الدخل: الفواتير التي لا تحتوي على ضرائب.

فاتورة الضريبة العامة: الفواتير التي تحتوي على ضرائب المبيعات.

فاتورة الضريبة الخاصة: الفواتير التي تحتوي على الضريبة العامة للمبيعات والضريبة الخاصة.

دليل المستخدم — «النظرة العامة»

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

المرتجعات: ما يقوله الدليل وما يعنيه لك برمجياً

لإتمام عملية إرجاع فاتورة، يمكن للمستخدمين إرجاع فاتورة مصدرة عن طريق منصة الـPortal فقط.

دليل المستخدم — «إرجاع فاتورة»

هذه الجملة تصف شاشة الإرجاع داخل المنصة: زر «إرجاع» المرتبط بفاتورة قائمة متاح من واجهة الـPortal، وفيه تحدّد الكمية المراد إرجاعها لكل بند.

برمجياً لا تحتاج إلى تلك الشاشة: المرتجع مستند مستقل من نوع 381 (إشعار دائن) ترسله بنفس نقطة النهاية، مع طريقة دفع 013 أو 023 وبنود تحمل الكميات المرتجعة.

خطأ شائع إرسال 381 مع 011 أو 021. نمنعه قبل الإرسال ونعيد 422 بدل استهلاك نداء حكومي.
نافذة تحرير منتج الفاتورة عند الإرجاع في المنصة مع حقل الكمية المراد إرجاعها
شاشة الإرجاع في المنصة — حقل «الكمية المراد إرجاعها» يقابل items[].qty في إشعارك الدائن.

الاقتباسات أعلاه من «نظام الفوترة الوطني — دليل المستخدم الخاص بمنصة الـPortal»، واللقطات من الدليل نفسه وتعود ملكيتها لجهة إصداره. أُدرجت للتوضيح التقني فقط، والدليل الرسمي هو المرجع عند أي اختلاف.

الاستعلام عن فاتورة

اجلب الفاتورة بمعرّفها لدينا (inv_…) أو برقمها لديك مباشرة — فلا تحتاج لتخزين معرّفنا إن لم ترغب.

GET/api/v1/invoices/{id}
curl "https://fawtara.codexal.co/api/v1/invoices/INV-2026-0418" \
  -H "Authorization: Bearer fwt_live_•••••••••"

// 200 OK
{
  "data": {
    "id":             "inv_5c8d1e9a2b7f3046",
    "status":         "accepted",
    "invoice_number": "INV-2026-0418",
    "uuid":           "8f3c1e42-…-b41d",
    "qr_content":     "AQ3YtNix…",
    "jofotara":       { "status": "SUBMITTED", "http_code": 200 }
  }
}

وللسرد والتصفية: GET /api/v1/invoices?status=rejected&from=2026-10-01&limit=50 — يقبل أيضاً uuid و invoice_number و mode.

فحص المفتاح

نداء خفيف للتأكد من صحة المفتاح وبيئته قبل بناء التكامل.

GET/api/v1/ping
curl https://fawtara.codexal.co/api/v1/ping -H "X-Api-Key: fwt_test_•••"

{
  "ok": true,
  "environment": "sandbox",
  "plan": "growth",
  "rate_limit": "60/min",
  "jofotara_configured": false
}

منع الإرسال المزدوج

أرسل ترويسة Idempotency-Key مع كل طلب إنشاء — استخدم رقم الفاتورة لديك. إن تكرّر النداء بالمفتاح نفسه (انقطاع شبكة، إعادة محاولة تلقائية) نعيد الاستجابة الأصلية حرفياً مع ترويسة Idempotent-Replay: true، ولا تُرسل الفاتورة مرتين إلى الدائرة.

أعد المحاولة بأمان عند 429 أو 503 أعد المحاولة بتراجع أسّي (1s، 2s، 4s…) مع الاحتفاظ بنفس Idempotency-Key. لا تُعد المحاولة على 4xx غير 429 — فهي أخطاء في الطلب نفسه.

Webhooks

بدل الاستعلام الدوري، سجّل عنوان https من لوحة التحكم أو عبر POST /api/v1/webhooks، ونرسل إليه الحدث فور وقوعه. متاح في خطّتي النمو والاحتراف.

POSTعنوانك ← فواترا
// الترويسات
X-Fawtara-Event:     invoice.accepted
X-Fawtara-Delivery:  1842
X-Fawtara-Timestamp: 1791234567
X-Fawtara-Signature: sha256=5e884898da28…   // HMAC‑SHA256 لـ "timestamp.body"

// الجسم
{
  "id":         "evt_6d1e8f3a0b2c4759",
  "object":     "event",
  "type":       "invoice.accepted",
  "created_at": "2026-04-18T09:14:05+00:00",
  "mode":       "live",
  "data":       { … كائن الفاتورة كاملاً … }
}

الأحداث: invoice.accepted · invoice.rejected · invoice.failed · subscription.updated. احسب HMAC_SHA256(timestamp + "." + raw_body, secret) على الجسم الخام قبل أي تحليل، وأعد 2xx خلال 15 ثانية. نعيد المحاولة ستّ مرات بتدرّج: فوراً، دقيقة، 5 دقائق، 30 دقيقة، ساعتان، 6 ساعات. أمثلة التحقّق من التوقيع بثلاث لغات.

حدود المعدّل

الحد يعتمد على خطتك، ويُحتسب في نافذة دقيقة واحدة لكل مفتاح. كل استجابة تحمل الترويسات:

Headers
X-RateLimit-Limit:     120
X-RateLimit-Remaining: 117
X-RateLimit-Reset:     1791234600
X-Fawtara-Mode:        live
الخطةطلب / دقيقةفواتير حقيقية / شهرمفاتيح
البداية 30 50 1
النمو 120 1,000 3
الاحتراف 600 10,000 10
المؤسساتحسب الاتفاقحسب الاتفاقغير محدود

بيئة الاختبار غير محدودة في كل الخطط. عند بلوغ الحصّة الحقيقية يعود 402 quota_exceeded مع رابط الترقية — بلا رسوم تجاوز.

أكواد الأخطاء

كل خطأ يعود بالشكل نفسه: { "error": { "type", "code", "message", … } }. اعتمد على type في منطقك (وcode نسخة مطابقة للتوافق)، لا على نص الرسالة.

HTTPcodeالمعنى
400 invalid_body جسم الطلب فارغ أو ليس JSON صالحاً.
401 missing_api_key لم تُرسل ترويسة Authorization أو X-Api-Key.
401 invalid_api_key المفتاح غير معروف لدينا.
401 revoked_api_key المفتاح أُبطل من لوحة التحكم.
401 expired_api_key انتهت صلاحية المفتاح.
402 quota_exceeded استُنفدت حصة الخطة الشهرية — يحمل الردّ quota و used و upgrade_url.
402 subscription_inactive انتهى أمد الاشتراك أو تأخّر سداده — الإرسال الحقيقي موقوف حتى تأكيد الدفع.
403 insufficient_scope المفتاح لا يملك الصلاحية المطلوبة — يحمل الردّ required_scope.
403 plan_limit الميزة غير متاحة في خطتك (Webhooks أو الإشعارات الدائنة).
403 account_suspended الحساب موقوف إدارياً.
404 invoice_not_found لا توجد فاتورة بهذا المعرّف في حسابك.
404 qr_unavailable الفاتورة لم تُقبل بعد، فلا رمز QR لها.
405 method_not_allowed طريقة HTTP غير مدعومة لهذا المسار.
409 duplicate_invoice_number رقم الفاتورة مستخدم مسبقاً — يحمل الردّ existing_invoice_id.
409 jofotara_credentials_missing مفتاح إنتاج دون ضبط Client-Id و Secret-Key في الإعدادات.
409 already_accepted محاولة إعادة إرسال فاتورة مقبولة أصلاً.
409 too_many_attempts تجاوزت 10 محاولات إرسال لنفس الفاتورة.
422 validation_error الفاتورة لم تجتز التحقّق المسبق — راجع fields لمعرفة كل حقل خاطئ.
429 rate_limited تجاوزت حدّ الطلبات في الدقيقة — انتظر قيمة Retry-After.
500 internal_error عطل مؤقت لدينا. أعد المحاولة بتراجع أسّي بنفس Idempotency-Key.

أمثلة جاهزة

نفس النداء بأربع لغات — انسخه وبدّل المفتاح.

PHP 8 — cURL
$payload = [
  'invoice_number' => 'INV-2026-0418',
  'invoice_type'   => '388',
  'payment_method' => '011',
  'buyer' => ['name' => 'شركة النور', 'tin' => '9871234'],
  'items' => [
    ['name' => 'استشارات', 'qty' => 1, 'unit_price' => 450, 'tax_rate' => 16],
  ],
];

$ch = curl_init('https://fawtara.codexal.co/api/v1/invoices');
curl_setopt_array($ch, [
  CURLOPT_POST           => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER     => [
    'Content-Type: application/json',
    'X-Api-Key: ' . getenv('FAWTARA_KEY'),
    'Idempotency-Key: ' . $payload['invoice_number'],
  ],
  CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
  CURLOPT_TIMEOUT        => 45,
]);

$res  = json_decode(curl_exec($ch), true);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($code === 201) {
  echo "معتمدة: {$res['uuid']}";
} else {
  echo "خطأ: " . $res['error']['code'];
}

جاهز للربط؟

احصل على مفتاح Sandbox مجاني وابدأ التجربة اليوم. عند جاهزيتك، نفعّل المفتاح الحي بنقرة.