توثيق واجهة API

واجهة برمجية RESTful لإدارة المستندات والاعتمادات برمجياً

نظرة عامة

توفر واجهة WAQTUM API إمكانية الوصول الكامل لجميع وظائف النظام برمجياً. جميع الطلبات والاستجابات بصيغة JSON.

Base URL: https://waqtum.qantrah.com/api/v1
فحص الحالة: GET /api/v1/health عام

⚠️ تنبيهات مهمة قبل البدء

إنشاء المستند لا يبدأ الاعتماد

عند POST /documents، يُحفظ المستند بحالة draft فقط. لبدء الاعتماد وإشعار المعتمدين عبر WhatsApp يجب استدعاء POST /documents/{id}/send بشكل منفصل.

الحقول ثنائية اللغة

الحقول مثل title و name لها نسختان في قاعدة البيانات: title_ar / title_en و name_ar / name_en. لتسهيل التكامل، الـ API يقبل إما الإصدار المختصر (title فقط — يُستخدم لكلتا اللغتين) أو الإصدارين منفصلين معاً.

التوقيع الرقمي تلقائي

بمجرد اكتمال اعتماد جميع المعتمدين، يقوم النظام تلقائياً بتوليد PDF نهائي يحتوي على التواقيع والأختام وصفحة شهادة تدقيق، ثم يُضمَّن توقيع رقمي مشفّر (X.509) عبر OpenSSL. لا حاجة لطلب يدوي.

رابط التحميل عام دائم

endpoint /documents/{id}/download يُرجع URL مباشر على storage العام (وليس URL مؤقتاً ينتهي بعد 30 دقيقة). الـ URL غير قابل للتخمين لكنه يعمل من أي عميل. لا تشارك الـ URL بشكل علني.

حالة "approved" هي الحالة النهائية

التحميل يعمل فقط عندما status == approved (ليس completed أو signed). تحقق من الحالة قبل محاولة التحميل.

المصادقة

جميع الطلبات المحمية تتطلب مفتاح API والسر في رأس Authorization:

Authorization: Bearer YOUR_API_KEY:YOUR_API_SECRET
Content-Type: application/json
Accept: application/json
يمكنك إنشاء مفاتيح API من لوحة التحكم في /admin/api

حدود الطلبات

يتم تحديد عدد الطلبات لكل مفتاح API حسب الباقة:

الباقة الحد
أساسي100 طلب/دقيقة
شركات300 طلب/دقيقة
مؤسسات1000 طلب/دقيقة

عند تجاوز الحد يتم إرجاع خطأ 429 (Too Many Requests).

دورة حياة المستند

يمر المستند بالحالات التالية بالترتيب:

POST /documents          ──► draft     (جاهز للتعديل أو الحذف)
POST /documents/{id}/send ──► pending   ──► in_progress   (تم الإرسال للمعتمدين)
اعتماد كل المعتمدين     ──► approved  (PDF موقّع رقمياً ومتاح للتحميل)
رفض أحد المعتمدين        ──► rejected
تجاوز expires_at            ──► expired
POST /documents/{id}/void ──► voided    (إلغاء يدوي)
الحالة الإجراءات المتاحة
draftPUT, DELETE, POST /send
pending / in_progressPOST /void, GET /status
approvedGET /download (الملف موقّع رقمياً)
rejected / expired / voidedللقراءة فقط

المستندات

GET /documents قائمة المستندات

المعاملات الاختيارية:

statusdraft, pending, in_progress, approved, rejected, expired, voided
pageرقم الصفحة
per_pageعدد النتائج (افتراضي: 15)
GET /documents/{id} عرض مستند

إرجاع تفاصيل المستند مع المعتمدين والحالة.

POST /documents إنشاء مستند (يُنشأ بحالة draft)

Content-Type: multipart/form-data

حقول العنوان (اختر إحدى الصيغتين):

الحقلالنوعالوصف
titlestringمختصر — يُستخدم لكلا اللغتين تلقائياً
— أو —
title_ar + title_enstringإصداران منفصلان بالعربية والإنجليزية

الحقول الأخرى:

الحقلالنوعمطلوبالوصف
filefile (PDF)نعمملف PDF (حسب الباقة، حد أقصى 20MB)
departmentstringمفتاح القسم (مثل: hr, finance, legal)
workflow_typestringsequential | parallel (افتراضي: sequential)
expires_in_daysintegerمدة الصلاحية بالأيام (افتراضي: 7)
approvers[]arrayقائمة المعتمدين (انظر تفاصيل المعتمد أدناه)

حقول كل معتمد (approvers[N][...]):

الحقلالنوعمطلوبالوصف
name أو (name_ar + name_en)stringنعماسم المعتمد (مختصر أو منفصل)
phonestringنعمرقم WhatsApp بتنسيق E.164 (مثل: 96812345678)
role_ar, role_enstringالمسمى الوظيفي
action_typestringsign | stamp | approve_only | review_only (افتراضي: sign)
order_index أو orderintegerالترتيب (يبدأ من 1، مهم للسير التسلسلي)

مثال (curl):

curl -X POST https://waqtum.qantrah.com/api/v1/documents \
  -H "Authorization: Bearer KEY:SECRET" \
  -F "title_ar=توقيع التقرير" \
  -F "title_en=Report Signature" \
  -F "department=hr" \
  -F "workflow_type=sequential" \
  -F "expires_in_days=7" \
  -F "file=@document.pdf" \
  -F "approvers[0][name_ar]=علي" \
  -F "approvers[0][name_en]=Ali" \
  -F "approvers[0][phone]=96812345678" \
  -F "approvers[0][action_type]=sign" \
  -F "approvers[0][order_index]=1"
لاحظ: المستند يُنشأ بحالة draft. لبدء الاعتماد استدع POST /documents/{id}/send.
PUT /documents/{id} تحديث مستند

تحديث المستند (فقط المستندات بحالة draft).

DELETE /documents/{id} حذف مستند

حذف مستند (فقط المستندات بحالة draft).

POST /documents/{id}/send إرسال للاعتماد

إرسال المستند لمسار الاعتماد وإشعار المعتمدين.

POST /documents/{id}/void إلغاء مستند

إلغاء مستند مرسل (يرسل إشعار للمعتمدين).

GET /documents/{id}/status حالة المستند

إرجاع الحالة الحالية للمستند وتقدم الاعتماد.

GET /documents/{id}/download تحميل المستند المعتمد

إرجاع URL لتحميل الملف النهائي الموقّع رقمياً (PDF). يعمل فقط عندما status == approved.

الاستجابة:

{
    "data": {
        "download_url": "https://waqtum.qantrah.com/storage/final/.../WAQTUM_WQT-2026-00001_Final.pdf",
        "expires_at": "2026-04-09T20:00:00+00:00",
        "filename": "WQT-2026-00001.pdf"
    }
}
تنبيه أمني: الـ URL عام دائم (وليس مؤقتاً). لا تشاركه علناً — أي شخص لديه الرابط يمكنه التحميل.

المعتمدون

GET /documents/{documentId}/approvers قائمة المعتمدين
POST /documents/{documentId}/approvers إضافة معتمد (لمستند بحالة draft)

نفس حقول approvers[] في إنشاء المستند:

الحقلمطلوبالوصف
name أو (name_ar + name_en)نعماسم المعتمد
phoneنعمرقم WhatsApp بتنسيق E.164
role_ar, role_enالمسمى الوظيفي
action_typesign | stamp | approve_only | review_only
order_index أو orderترتيب الاعتماد
لا يمكن إضافة معتمدين بعد إرسال المستند (بعد POST /send).
PUT /approvers/{id} تحديث معتمد
DELETE /approvers/{id} حذف معتمد
POST /approvers/{id}/remind إرسال تذكير

إعادة إرسال إشعار WhatsApp للمعتمد.

الويب هوك (Webhooks)

استقبل إشعارات فورية عند حدوث أحداث في النظام.

الأحداث المتاحة
الحدث الوصف
document.createdعند إنشاء مستند جديد
document.sentعند إرسال مستند للاعتماد
document.approvedعند اعتماد المستند بالكامل
document.rejectedعند رفض المستند
approver.completedعند إتمام معتمد لإجرائه
إدارة الويب هوك
GET /webhooks/events الأحداث المتاحة
GET /webhooks قائمة الويب هوك
POST /webhooks إنشاء ويب هوك
urlstringعنوان URL الذي سيستقبل الإشعارات
eventsarrayقائمة الأحداث المطلوبة
POST /webhooks/{id}/test اختبار ويب هوك
POST /webhooks/{id}/rotate-secret تدوير المفتاح السري
التحقق من التوقيع

يتم إرسال توقيع HMAC-SHA256 + طابع زمني في رؤوس كل طلب webhook. التوقيع يشمل الـ timestamp + النقطة (.) + الـ payload لمنع replay attacks:

الرؤوس المرسلة:

X-Waqtum-Event: document.completed
X-Waqtum-Timestamp: 1733527200
X-Waqtum-Signature: sha256=HMAC_HASH
X-Waqtum-Delivery: 12345
Content-Type: application/json

طريقة التوليد:

signed_payload = timestamp + "." + payload
signature = hex(hmac_sha256(signed_payload, secret))

التحقق في PHP/Laravel:

$payload   = $request->getContent();
$timestamp = $request->header('X-Waqtum-Timestamp');
$received  = $request->header('X-Waqtum-Signature');  // "sha256=..."

$signedPayload = $timestamp . '.' . $payload;
$expected = 'sha256=' . hash_hmac('sha256', $signedPayload, env('WAQTUM_WEBHOOK_SECRET'));

if (!hash_equals($expected, $received)) {
    abort(401, 'Invalid signature');
}

// Optional: reject old requests (anti-replay)
if (abs(time() - (int) $timestamp) > 300) {
    abort(401, 'Stale timestamp');
}

التحقق في Node.js:

const crypto = require('crypto');

const payload   = req.rawBody;  // raw bytes, NOT parsed JSON
const timestamp = req.headers['x-waqtum-timestamp'];
const received  = req.headers['x-waqtum-signature'];

const signed   = `${timestamp}.${payload}`;
const expected = `sha256=${crypto.createHmac('sha256', SECRET).update(signed).digest('hex')}`;

if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
    return res.status(401).send('Invalid signature');
}
مهم: استخدم الـ raw payload (قبل json_decode). لو حسبت التوقيع على JSON مُعاد ترتيبه ستفشل المطابقة.

رموز الأخطاء

الرمز الوصف
400طلب غير صالح — تحقق من المعاملات
401غير مصادق — مفتاح API غير صالح
403ممنوع — لا توجد صلاحية لهذا الإجراء
404غير موجود — المورد غير موجود
422خطأ تحقق — البيانات غير صالحة
429تجاوز الحد — طلبات كثيرة جداً
500خطأ في الخادم — تواصل مع الدعم
شكل الاستجابة
{
    "success": false,
    "error": {
        "code": 422,
        "message": "Validation failed",
        "details": {
            "title_ar": ["The title_ar field is required."]
        }
    }
}

مستعد للبدء؟

سجّل الآن وابدأ بالتكامل مع WAQTUM API