المحتويات
توثيق واجهة API
واجهة برمجية RESTful لإدارة المستندات والاعتمادات برمجياً
نظرة عامة
توفر واجهة WAQTUM API إمكانية الوصول الكامل لجميع وظائف النظام برمجياً. جميع الطلبات والاستجابات بصيغة JSON.
https://www.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 حسب الباقة:
| الباقة | الحد |
|---|---|
| أساسي | 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 (إلغاء يدوي)
| الحالة | الإجراءات المتاحة |
|---|---|
draft | PUT, DELETE, POST /send |
pending / in_progress | POST /void, GET /status |
approved | GET /download (الملف موقّع رقمياً) |
rejected / expired / voided | للقراءة فقط |
المستندات
/documents
قائمة المستندات
المعاملات الاختيارية:
status | draft, pending, in_progress, approved, rejected, expired, voided |
page | رقم الصفحة |
per_page | عدد النتائج (افتراضي: 15) |
/documents/{id}
عرض مستند
إرجاع تفاصيل المستند مع المعتمدين والحالة.
/documents
إنشاء مستند (يُنشأ بحالة draft)
Content-Type: multipart/form-data
حقول العنوان (اختر إحدى الصيغتين):
| الحقل | النوع | الوصف |
|---|---|---|
title | string | مختصر — يُستخدم لكلا اللغتين تلقائياً |
| — أو — | ||
title_ar + title_en | string | إصداران منفصلان بالعربية والإنجليزية |
الحقول الأخرى:
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
file | file (PDF) | نعم | ملف PDF (حسب الباقة، حد أقصى 20MB) |
department | string | — | مفتاح القسم (مثل: hr, finance, legal) |
workflow_type | string | — | sequential | parallel (افتراضي: sequential) |
expires_in_days | integer | — | مدة الصلاحية بالأيام (افتراضي: 7) |
approvers[] | array | — | قائمة المعتمدين (انظر تفاصيل المعتمد أدناه) |
حقول كل معتمد (approvers[N][...]):
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
name أو (name_ar + name_en) | string | نعم | اسم المعتمد (مختصر أو منفصل) |
phone | string | نعم | رقم WhatsApp بتنسيق E.164 (مثل: 96812345678) |
role_ar, role_en | string | — | المسمى الوظيفي |
action_type | string | — | sign | stamp | approve_only | review_only (افتراضي: sign) |
order_index أو order | integer | — | الترتيب (يبدأ من 1، مهم للسير التسلسلي) |
مثال (curl):
curl -X POST https://www.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"
/documents/{id}
تحديث مستند
تحديث المستند (فقط المستندات بحالة draft).
/documents/{id}
حذف مستند
حذف مستند (فقط المستندات بحالة draft).
/documents/{id}/send
إرسال للاعتماد
إرسال المستند لمسار الاعتماد وإشعار المعتمدين.
/documents/{id}/void
إلغاء مستند
إلغاء مستند مرسل (يرسل إشعار للمعتمدين).
/documents/{id}/status
حالة المستند
إرجاع الحالة الحالية للمستند وتقدم الاعتماد.
/documents/{id}/download
تحميل المستند المعتمد
إرجاع URL لتحميل الملف النهائي الموقّع رقمياً (PDF). يعمل فقط عندما status == approved.
الاستجابة:
{
"data": {
"download_url": "https://www.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"
}
}
المعتمدون
/documents/{documentId}/approvers
قائمة المعتمدين
/documents/{documentId}/approvers
إضافة معتمد (لمستند بحالة draft)
نفس حقول approvers[] في إنشاء المستند:
| الحقل | مطلوب | الوصف |
|---|---|---|
name أو (name_ar + name_en) | نعم | اسم المعتمد |
phone | نعم | رقم WhatsApp بتنسيق E.164 |
role_ar, role_en | — | المسمى الوظيفي |
action_type | — | sign | stamp | approve_only | review_only |
order_index أو order | — | ترتيب الاعتماد |
/approvers/{id}
تحديث معتمد
/approvers/{id}
حذف معتمد
/approvers/{id}/remind
إرسال تذكير
إعادة إرسال إشعار WhatsApp للمعتمد.
الويب هوك (Webhooks)
استقبل إشعارات فورية عند حدوث أحداث في النظام.
الأحداث المتاحة
| الحدث | الوصف |
|---|---|
document.created | عند إنشاء مستند جديد |
document.sent | عند إرسال مستند للاعتماد |
document.approved | عند اعتماد المستند بالكامل |
document.rejected | عند رفض المستند |
approver.completed | عند إتمام معتمد لإجرائه |
إدارة الويب هوك
/webhooks/events
الأحداث المتاحة
/webhooks
قائمة الويب هوك
/webhooks
إنشاء ويب هوك
url | string | عنوان URL الذي سيستقبل الإشعارات |
events | array | قائمة الأحداث المطلوبة |
/webhooks/{id}/test
اختبار ويب هوك
/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');
}
رموز الأخطاء
| الرمز | الوصف |
|---|---|
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."]
}
}
}