الخدمة 7
صفحة — OCR واستخراج المستندات
POST
/Integration/upload · /Integration/templatesهذا الـ API تابع لصفحة مباشرة، وليس عبر Agent Hub ولا Inbound Gateway؛ الـ host والـ authentication مختلفان عن باقي المستند.
ترسل مستنداً (PDF أو صورة أو Word) فتستخرج صفحة البيانات منه وترسلها إلى الـ webhook الخاص بك. هذا هو المصدر الذي تأتي منه attachments في complaint-recommendation.
Hosts: production https://api.safha-ai.com — staging https://api-staging.safha-ai.com — test https://api-test.safha-ai.com. المسار case-sensitive (Integration بحرف I كبير).
Authentication: الـ header هو Authorization: Bearer <token>. الـ token يُنشأ من داشبورد صفحة ومرتبط بالـ tenant، وقد يكون له تاريخ انتهاء.
- •في الـ multipart يُكتب الـ webhook هكذا: webhook[link] و webhook[body][ref] و webhook[headers][X-Key].
- •رد الرفع (200) يرجع فوراً والمعالجة تستكمل في الخلفية؛ status = processing رغم أن الرسالة تقول processed.
- •Webhook delivery: بعد انتهاء الاستخراج ترسل صفحة POST JSON إلى webhook.link مع headers الخاصة بك + X-Velents-Authorization.
- •extracted_data كائن key: value. في الـ free-form الـ keys تُستخرج من المستند نفسه (غالباً بالعربية) وليست ثابتة. مع template_id هي حقول الـ template، والحقل الذي لم يُعثر عليه يرجع null، والقيم المتكررة تأخذ _1 و _2.
- •الـ payload لا يحتوي invoice id ولا status؛ اربط النتيجة بالطلب عن طريق الـ reference في webhook.body.
- •إذا كان الاستخراج فارغاً يُرسل {"extracted_data": []}. إذا فشلت المعالجة نفسها لا يُرسل webhook، وتعيد صفحة المحاولة حتى 3 مرات.
- •الـ webhook لا يُعاد إذا رد سيرفرك بـ 4xx أو 5xx؛ يُعاد فقط إذا فشل الاتصال نفسه. أرجع 2xx.
- •Templates: GET /Integration/templates?per_page=15&page=1 — templates الـ tenant، الأحدث أولاً. complaint-recommendation لا تحتاج template_id إطلاقاً.
- •شكل الخطأ مختلف عن شكل النجاح: {"ok": false, "message": "...", "code": <status>}.
جرّب الطلب
المفتاح يُحفظ في متصفحك فقط ويُرسل مع الطلب عند التجربة.
GEThttps://api-test.safha-ai.com
المفتاح يُحفظ في متصفحك فقط ويُرسل مع الطلب عند التجربة.
POSThttps://api-test.safha-ai.com
Request
| الحقل | النوع | مطلوب | الشرح |
|---|---|---|---|
file_url | string (URL) | إن لم يوجد file | رابط public للملف. صفحة تنزّله بنفسها. |
file | file | إن لم يوجد file_url | multipart فقط. pdf, jpg, jpeg, png, doc, docx — أقصى 20 MB. |
template_id | string | اختياري | id من GET /Integration/templates. عدم الإرسال = free-form. |
webhook.link | string (URL) | اختياري | الـ URL الذي تُرسل إليه النتيجة. يجب أن يكون اسمه link. |
webhook.body | object | اختياري | ضع هنا الـ reference الخاص بك. الـ keys تُضاف إلى top level في الـ payload. |
webhook.headers | object | اختياري | headers تُرسل مع الـ webhook. |
need_approval | boolean | اختياري | true = النتيجة لا تُرسل تلقائياً؛ تنتظر مراجعتها وإرسالها من داشبورد صفحة. |
request
curl -X POST 'https://api.safha-ai.com/Integration/upload' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"file_url": "https://insaf.example/files/hearing-minutes.pdf",
"webhook": {
"link": "https://insaf.example/safha/webhook",
"body": { "document_ref": "INSAF-123" }
}
}'response
// رد الرفع — 200
{
"status": true,
"code": 200,
"message": "Invoice uploaded and processed successfully",
"data": {
"invoice": {
"id": 123, "status": "processing", "source": "upload",
"file_name": "hearing-minutes.pdf", "file_path": "https://...", "file_url": "https://...",
"webhook_url": "https://insaf.example/safha/webhook",
"webhook_body": { "document_ref": "INSAF-123" }, "webhook_headers": null,
"created_at": "2026-10-17 10:00:00"
}
}
}
// Webhook delivery
{
"extracted_data": {
"نوع_المستند": "محضر جلسة",
"التاريخ": "14-02-2026",
"حضور_وكيل_المدعي": "لم يحضر"
},
"document_ref": "INSAF-123"
}
// GET /Integration/templates
{
"data": [
{ "id": 12, "name": "Free form Template", "desc": null, "is_default": 1,
"modified_at": "2026-01-01T00:00:00.000000Z", "is_constant": true }
],
"links": { "first": "...?page=1", "last": "...?page=1", "prev": null, "next": null },
"meta": { "current_page": 1, "last_page": 1, "per_page": 15, "total": 1 }
}Errors
| Status | Code | السبب |
|---|---|---|
| 401 | Unauthenticated | الـ token غير موجود أو خاطئ أو منتهٍ. |
| 422 | Validation error + errors: { field: [...] } | file_url / file ناقصان، نوع أو حجم الملف خاطئ، أو webhook.link ليس URL. |
| 404 | Resource not found | المسار خاطئ (تأكد من حرف I الكبير). |
| 500 | Unexpected error | خطأ عند صفحة. |