المطورون
Formalini API
قراءة المستندات وحقولها المستخرجة، وإرسال المستندات من أنظمتك، وتصحيح القيم، واستلام إشعارات webhook موثقة عند حدوث أي تغيير. جميع الأمثلة أدناه موضحة بلغات curl وJavaScript وPython وPHP وC#.
عنوان URL الأساسي
تندرج جميع نقاط النهاية تحت عنوان URL الأساسي هذا. الإرسال والاستلام بصيغة JSON.
https://api.formalini.com/api/public/v1العنوان المختصر api.formalini.com متاح ونشط، وهو العنوان الموضح أعلاه.
المصادقة
أنشئ مفتاح API في التطبيق ضمن قسم عمليات الربط (Integrations)، ثم أرسله كرمز bearer token مع كل طلب. يرتبط كل مفتاح بمساحة عمل واحدة ولا يمكنه الوصول إلا لبياناتها فقط.
documents.read— قراءة المستندات وحقولهاdocuments.write— إنشاء المستندات وتصحيح الحقولworkflows.run— إرسال الأحداث إلى نقاط webhook لديك عند الطلب
يخضع كل مفتاح لحد أقصى من الطلبات في الدقيقة (60 افتراضياً). تتضمن الاستجابات ترويستي X-RateLimit-Limit وX-RateLimit-Remaining؛ وعند تجاوز الحد ستتلقى رمز الحالة 429 مع Retry-After.
عرض قائمة المستندات
GET /documents?limit=25&status=approved — documents.read
مرتبة من الأحدث إلى الأقدم. تقبل المعلمة limit من 1 إلى 100 (25 افتراضياً)، وتتم تصفية status حسب: queued أو processing أو review أو approved أو exported أو failed.
curl -X GET "https://api.formalini.com/api/public/v1/documents?limit=25&status=approved" \
-H "Authorization: Bearer pf_live_your_key"{
"documents": [
{
"id": "b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90",
"name": "Job sheet 4821.jpg",
"status": "approved",
"average_confidence": 0.94,
"source": "upload",
"created_at": "2026-09-11T09:12:04.000Z",
"fields": [
{ "name": "engineer", "value": "M. Byrne", "type": "text",
"confidence": 0.97, "page": 1, "valid": true }
]
}
]
}تحل القيم المصححة محل القراءة الأصلية، لذا فإن value هي دائماً القيمة المعتمدة للاستخدام.
جلب مستند واحد
GET /documents/{id} — documents.read
إرجاع المستند متضمناً فئته والمورّد والمبلغ والتاريخ وكافة الحقول.
curl -X GET "https://api.formalini.com/api/public/v1/documents/b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90" \
-H "Authorization: Bearer pf_live_your_key"رفع ملف واستخراج بياناته
POST /documents/upload — documents.write
أرسل صورة الصفحة واستلم البيانات المنظمة مباشرة في الاستجابة نفسها. يظهر المستند في صندوق وارد مساحة العمل مثل أي مستند ممسوح ضوئياً، ويستهلك رصيد ذكاء اصطناعي واحداً لكل صفحة، ويرسل إشعارات webhook فور اكتماله.
file— صورة الصفحة؛ كرر الحقل لكل صفحة (حتى 25 صفحة) في المستندات متعددة الصفحاتname— اسم اختياري للمستند؛ يُعتمد اسم الملف تلقائياً عند تركه فارغاًtemplate_id— معرّف قالب (template id) اختياري، لإرجاع الحقول بالمسميات المعرفة لديكasync— عيّنه كـ true لتلقي الاستجابة 202 فوراً والاستعلام الدوري عبر GET /documents/{id} لجلب النتيجة
curl -X POST "https://api.formalini.com/api/public/v1/documents/upload" \
-H "Authorization: Bearer pf_live_your_key" \
-F "file=@invoice-page-1.jpg" \
-F "file=@invoice-page-2.jpg" \
-F "name=Invoice 2026-0041"{
"document": {
"id": "8c2a1f76-4d33-4a1e-8f10-72b9e5c4a118",
"name": "Invoice 2026-0041",
"status": "review",
"average_confidence": 0.93,
"vendor": "Northbridge Supplies",
"amount": 1249.5,
"currency": "EUR",
"document_date": "2026-09-14",
"pages": 2,
"credits_spent": 2,
"fields": [
{ "name": "invoice_number", "value": "2026-0041", "type": "string",
"confidence": 0.98, "page": 1, "valid": true }
]
}
}تُقبل صيغ JPEG وPNG وWebP وHEIC، بحجم يصل إلى 100 ميغابايت لكل صفحة. تستغرق قراءة الصفحة بضع ثوانٍ، لذا يرجى ضبط مهلة كافية أو تعيين async=true. يشير الرمز 402 إلى نفاد الرصيد أو السعة التخزينية أو الحد اليومي لمساحة العمل، مع تحديد السبب في الاستجابة.
ملفات PDF غير مدعومة عبر هذه النقطة حالياً: حوّل كل صفحة إلى JPEG أو PNG وأرسلها كحقول ملفات متكررة. يظل رفع ملفات PDF متاحاً عبر التطبيق، حيث تتم معالجة الصفحات محلياً في متصفحك.
إنشاء مستند
POST /documents — documents.write
إرسال مستند تتوفر بياناته لديك مسبقاً. الحقل name إلزامي؛ والحقل fields اختياري ويستوعب حتى 400 إدخال. ينتقل المستند المتضمن لحقول إلى حالة review، بينما ينتقل غير المتضمن لحقول إلى قائمة الانتظار.
curl -X POST "https://api.formalini.com/api/public/v1/documents" \
-H "Authorization: Bearer pf_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Invoice 2026-0041.pdf",
"category": "invoice",
"vendor": "Northbridge Supplies",
"amount": 1249.5,
"document_date": "2026-09-14",
"fields": [
{
"name": "invoice_number",
"value": "2026-0041",
"type": "text",
"confidence": 0.99,
"page": 1
},
{
"name": "total",
"value": "1249.50",
"type": "number",
"confidence": 0.96,
"page": 1
}
]
}'{
"document": {
"id": "8c2a…",
"name": "Invoice 2026-0041.pdf",
"status": "review",
"created_at": "2026-09-18T10:02:11.000Z",
"fields": 2
}
}تحديث مستند
PATCH /documents/{id} — documents.write
تغيير الحالة أو تصحيح قيم الحقول بالاسم. يؤدي تعيين الحالة إلى approved أو exported أو review إلى إطلاق إشعار webhook المطابق أيضاً.
curl -X PATCH "https://api.formalini.com/api/public/v1/documents/b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90" \
-H "Authorization: Bearer pf_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"status": "approved",
"fields": [
{
"name": "total",
"value": "1249.50"
}
]
}'{ "ok": true, "updated_fields": 1 }تشغيل إشعارات webhook
POST /workflows/dispatch — workflows.run
إرسال حدث إلى كل webhook نشط ومشترك فيه، لبدء إجراء في نظام آخر عند الطلب. الأحداث المسموح بها: document.processed وdocument.needs_review وdocument.approved وdocument.exported.
curl -X POST "https://api.formalini.com/api/public/v1/workflows/dispatch" \
-H "Authorization: Bearer pf_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"event": "document.approved",
"document_id": "b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90",
"payload": {
"target": "erp"
}
}'{ "ok": true, "event": "document.approved", "document_id": "b0f1…" }نقاط Webhook
أضف عنوان URL للـ webhook في التطبيق وحدد الأحداث المطلوبة. يُرسل كل إشعار عبر طلب POST يحتوي على نص JSON وترويسة توقيع مشفرة باستخدام مفتاح webhook السري الخاص بك.
POST https://your-app.example.com/hooks/formalini
Content-Type: application/json
X-Paperflow-Signature: sha256=<hex hmac of the raw body>
{ "event": "document.processed", "document_id": "b0f1…", "payload": { … } }تتم إعادة محاولة الإرسال الفاشلة حتى خمس مرات بفترات تأخير متزايدة، مع إمكانية إعادة إرسال أي عملية يدوياً من التطبيق.
تحقق من صحة التوقيع بمطابقته مع نص الطلب الأصلي (raw request body) قبل اعتماد الإشعار:
// Node.js
import crypto from "node:crypto";
function verify(rawBody, header, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const got = (header || "").replace(/^sha256=/, "");
return got.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}
# Python
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, (header or "").removeprefix("sha256="))
// PHP
$expected = hash_hmac('sha256', $rawBody, $secret);
$got = str_replace('sha256=', '', $_SERVER['HTTP_X_PAPERFLOW_SIGNATURE'] ?? '');
$ok = hash_equals($expected, $got);
// C#
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = Convert.ToHexString(hmac.ComputeHash(rawBodyBytes)).ToLowerInvariant();
var ok = CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(expected),
Encoding.UTF8.GetBytes(header.Replace("sha256=", "")));الأخطاء
400— نص الطلب ليس بصيغة JSON، أو توجد قيمة مطلوبة مفقودة أو غير صالحة401— المفتاح غير موجود، أو تم إلغاؤه، أو منتهي الصلاحية403— لا يملك المفتاح الصلاحية اللازمة للوصول لنقطة النهاية هذه404— لا يوجد مستند بهذا المعرّف في مساحة العمل هذه429— تم الوصول إلى الحد الأقصى للطلبات في الدقيقة — يرجى الانتظار ثم إعادة المحاولة500— حدث خطأ في النظام؛ توضح الاستجابة تفاصيل الخطأ