دليل مطوري تكامل واجهة برمجة تطبيقات الويب FormRead
كيف تعمل واجهة برمجة تطبيقات FormRead
تنقسم واجهة برمجة تطبيقات FormRead إلى جزأين: واجهة برمجة تطبيقات REST لإدارة النماذج (الإنشاء والتحديث والحذف وتخزين البيانات)، وإطار iframe مضمّن لتحرير النماذج وقراءة المستندات الممسوحة ضوئيًا. لا تقوم واجهة برمجة التطبيقات وحدها بمعالجة النماذج أو قراءتها - تتم القراءة بالكامل من خلال iframe.
- واجهة برمجة تطبيقات REST (هذه الصفحة): استخدمها لإنشاء بيانات تعريف النموذج وتحديثها وحذفها واسترجاعها. تخزّن واجهة برمجة التطبيقات بيانات النموذج الخاصة بك وتعيد الرموز المطلوبة لتضمين إطار iframe.
- إطار iframe (عارض مضمّن): استخدمه لتحرير قوالب النماذج وتحميل المستندات الممسوحة ضوئيًا واستخراج النتائج (OMR، OCR، BCR). تتم جميع عمليات قراءة النماذج واستخراج البيانات داخل إطار iframe.
هل تبحث عن معالجة من خادم إلى خادم؟
إذا كنت لا تحتاج إلى واجهة مرئية وتريد فقط إرسال الصور واستلام النتائج بصيغة JSON، فراجع واجهة برمجة تطبيقات المعالجة من جانب الخادم.
سير عمل التكامل النموذجي
- قم بالمصادقة باستخدام رمز مميز من نوع Bearer (يتم إنشاؤه من لوحة التحكم).
- استخدم نقطة النهاية
POST /api/formsلإنشاء نموذج والحصول علىiframe_token. - قم بتضمين إطار iframe في صفحتك باستخدام
iframe_tokenللسماح للمستخدمين بتحرير النماذج ومسح المستندات ضوئيًا. - استمع إلى أحداث iframe (
editForm،getResults،rowResult) لتلقي بيانات النموذج والنتائج المستخرجة، ثم قم بتخزينها في نظامك.
المصادقة
للاستخدامات المؤسسية، يمكن استخدام API عن طريق إنشاء رمز Bearer Auth.
سجل الدخول إلى FormRead لوحة التحكم وادخل إلى خيار رمز API:
أنشئ رموز API للسماح للخدمات الخارجية بالمصادقة مع تطبيقنا نيابة عنك:
انسخ الرمز المُنشأ في مكان آمن (سيُعرض مرة واحدة فقط):
إنشاء نموذج جديد
العناوين
| الاسم | القيمة |
|---|---|
Authorization |
Bearer YOUR_API_TOKEN |
Accept |
application/json |
الطلب
curl --location --request POST 'https://formread.org/api/forms' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--form 'form_name="new form"' \
--form 'custom_css="{ingest custom css to edit FormRead View}"'
استجابة
{
"id": 8,
"form_name": "new form",
"iframe_token": "6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb",
"created_at": "2022-02-28T21:22:55.000000Z",
"updated_at": "2022-02-28T21:22:55.000000Z"
}
المتغير custom_css سيسمح بإدخال قواعد CSS لتعديل مظهر FormRead وإضافة نص مخصص، مثل:
#app-title::after{
content: 'Your Tittle';
color: white;
}
#app-subtitle::after{
content: 'Your Custom sub-tittle Your Custom sub-tittle Your Custom sub-tittle';
color: white;
}
#upload-from-cam{
display: none;
}
#upload-from-system{
background: lightblue;
}
#upload-from-csv{
display: none;
}
#app > div.bg-gray-50.h-screen.overflow-auto > div > div{
background-color: black;
}
الحصول على النموذج بواسطة المعرف
الطلب
curl --location --request GET 'https://formread.org/api/forms/8' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN'
استجابة
{
"id": 8,
"form_name": "adsf",
"iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
"created_at": "2022-02-28T21:22:55.000000Z",
"updated_at": "2022-03-01T01:40:19.000000Z"
}
تعديل نموذج
بعد إنشاء النموذج Created أو GET يمكن عرضه في إطار Iframe باستخدام iframe_token المقدم في الاستجابة (هذا الرمز يتغير لذا تأكد من GET نموذجك قبل عرض الإطار)
أنشئ أيضًا سكريبت يستمع إلى أحداث الإطار المضمن كما في المثال أدناه:
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body style="height: 100%">
<iframe src="https://formread.org/{lang}/api/forms/{form_id}/edit/{iframe_token}/{read_only}"
style="height: 100%; width: 100%"></iframe>
<script>
window.addEventListener('message', function (e) {
// if (e.origin !== 'https://formread.org') return;
console.log(e.data.method)
if (e.data.method === "editForm") {
let formData = e.data.formData // data used to saved your form
let schema = JSON.parse(e.data.schema)
console.log(schema)
console.log(formData)
}
if (e.data.method === "getResults") {
let results = JSON.parse(e.data.results)
console.log(results)
}
if (e.data.method === "rowResult") {
let rowResult = JSON.parse(e.data.rowResult)
console.log(rowResult)
}
});
</script>
</body>
</html>
معاملات عنوان URL لإطار iframe
| المعامل | الوصف |
|---|---|
lang |
قم بتعيين متغير lang لعرض أوامر التطبيق باللغة المطلوبة. حاليًا، ندعم الإنجليزية (en) والفرنسية (fr) والإسبانية (es) والبرتغالية البرازيلية (pt) والهندية (hi) |
read_only |
يمكن تعيين المتغير read_only إلى 1 لتعطيل تحرير النموذج أو 0 للسماح بتحرير النموذج |
أحداث iframe
عندما ينقر المستخدمون على زر الحفظ، سيتم تشغيل طريقة <code class="language-plaintext">editForm</code>، وهناك يمكنك الوصول إلى متغيرين:
- سيحتوي متغير
formDataعلى سمات النموذج المشفرة التي يمكن إرسالها باستخدام Update لحفظ التغييرات التي تم إجراؤها على نموذجك: -
سيُعلمك متغير
schemaبالحقول التي تم إنشاؤها حتى الآن:{ "file_name": { "type": "text" }, "BCR-0": { "type": "text" }, "OCR-1": { "type": "text" }, "OMR-2-0": { "type": "select", "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], "questionIndex": "0" }, "OMR-2-1": { "type": "select", "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], "questionIndex": "1" }, "OMR-2-2": { "type": "select", "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], "questionIndex": "2" } }المتغير
schemaمخصص فقط لكي تعرض بعض التنبيهات للمستخدمين في حال كنت تطلب إنشاء حقول منطقة إلزامية:
عندما ينقر المستخدم على تنزيل النتائج، سيتم تشغيل طريقة getResults، وهناك ستحصل على بيانات النتيجة بتنسيق JSON حتى تتمكن من تخزينها في نظامك
أيضًا، يمكنك الحصول على النتائج صفًا تلو الآخر باستخدام طريقة rowResult، التي سيتم تشغيلها في كل مرة تتم فيها معالجة صفحة
تحديث النموذج
الطلب
curl --location --request POST 'https://formread.org/api/forms/8?_method=PUT' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--form 'form_data="eyJ2dWV4X3N0YXRlIjp7ImZvcm1OYW1lIjoiYWRzZiIsImZvcm1zIjp7f
Swic2VsZWN0ZWRGb3JtSWQiOiIiLCJmb3JtUmVhZEFyZWFzIjp7IkJDUi
0wIjp7ImNvbHVtblBvc2l0aW9uIjoxLCJ3aWR0aCI6MC4xMTQ5NTA0NTM
0MDUzNTE2NCwiaGVpZ2h0IjowL...' \
--form 'custom_css="{ingest custom css to edit FormRead View}"'
استجابة
{
"id": 8,
"form_name": "adsf",
"iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
"created_at": "2022-02-28T21:22:55.000000Z",
"updated_at": "2022-03-01T02:30:14.000000Z"
}
حذف النموذج
الطلب
curl --location --request DELETE 'https://formread.org/api/forms/8' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN'
استجابة
1
مثال كامل: تضمين سير عمل التصحيح
فيما يلي مثال شامل يوضح كيف يمكن للمعلم تصميم نموذج، ومسح الامتحانات ضوئيًا، ودفع النتائج المصححة إلى الخلفية الخاصة بك - كل ذلك من صفحة واحدة تقوم بتضمين إطار FormRead.
سيناريو
يفتح المعلم تطبيقك، ويصمم ورقة إجابة "Math 101 - Midterm"، ويطبعها، ويمسح الامتحانات المملوءة ضوئيًا، وينقر على "تنزيل النتائج". تستمع صفحتك لأحداث iframe، وتحفظ التخطيط، وتُرسل الإجابات المصححة إلى نظام التصحيح الخاص بك.
الخطوة 1 - إنشاء النموذج من الخادم الخاص بك
في الخلفية الخاصة بك، قم بإنشاء نموذج للمعلم. ستحصل على id و iframe_token - وهما ما ستمرره إلى عنوان URL لإطار iframe في الخطوة التالية.
# From YOUR backend (never from the browser)
curl --location --request POST 'https://formread.org/api/forms' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--form 'form_name="Math 101 - Midterm"'
{
"id": 42,
"form_name": "Math 101 - Midterm",
"iframe_token": "6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb",
"created_at": "2026-04-20T10:00:00.000000Z",
"updated_at": "2026-04-20T10:00:00.000000Z"
}
احفظ id و iframe_token في سجل المعلم في قاعدة بياناتك الخاصة. ستستخدمهما لعرض iframe القابل للتعديل في الخطوة 2.
الخطوة 2 - فتح iframe في وضع التحرير
تقوم الخلفية الخاصة بك بعرض صفحة تحتوي على إطار FormRead مع read_only=0، حتى يتمكن المعلم من رسم فقاعات OMR، ومناطق OCR، والباركود على الورقة. عندما ينقرون على "حفظ" داخل إطار iframe، يتم إطلاق حدث editForm - ويقوم المتصفح بإعادة توجيه formData الخام إلى الخلفية الخاصة بك. لا يقوم المتصفح بالاتصال بـ FormRead مباشرة أبدًا.
<!-- /design-form page rendered by YOUR backend.
read_only = 0 → editable mode -->
<iframe id="formread-frame"
src="https://formread.org/en/api/forms/42/edit/6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb/0"
style="width:100%; height:100vh; border:0"></iframe>
<script>
// The browser ONLY talks to your own backend. Never to FormRead.
const FORM_ID = 42;
window.addEventListener('message', async function (e) {
if (e.origin !== 'https://formread.org') return;
// Teacher clicked "Save" inside the iframe
if (e.data.method === 'editForm') {
await fetch(`/api/forms/${FORM_ID}/layout`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ form_data: e.data.formData })
});
}
});
</script>
الخطوة 3 - حفظ التخطيط من الخلفية الخاصة بك
تستقبل الخلفية الخاصة بك سلسلة formData وتقوم بإعادة توجيهها إلى FormRead باستخدام طلب PUT، مع رمز Bearer الخاص بك (الذي لا يغادر الخادم أبدًا). هذا ما يحفظ تكوين النموذج بشكل دائم بحيث يمكن إعادة استخدام نفس النموذج لاحقًا لمسح الامتحانات ضوئيًا.
# Inside your backend handler for POST /api/forms/42/layout
# $formData is the raw string your browser posted.
curl --location --request POST 'https://formread.org/api/forms/42?_method=PUT' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--form "form_data=${formData}"
{
"id": 42,
"form_name": "Math 101 - Midterm",
"iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
"created_at": "2026-04-20T10:00:00.000000Z",
"updated_at": "2026-04-20T10:15:42.000000Z"
}
يتم تدوير iframe_token
كل تحديث لنموذج يُرجع iframe_token جديدًا. احصل دائمًا على أحدث رمز من الخلفية الخاصة بك مباشرة قبل عرض إطار iframe - لا تقم بترميزه بشكل ثابت أو تخزينه مؤقتًا على المدى الطويل.
الخطوة 4 - جلب iframe_token الحالي
لاحقًا، عندما يكون المعلم مستعدًا لمسح الامتحانات ضوئيًا، تقرأ الخلفية الخاصة بك النموذج عن طريق id للحصول على أحدث iframe_token.
# From YOUR backend, right before rendering the scan page
curl --location --request GET 'https://formread.org/api/forms/42' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN'
{
"id": 42,
"form_name": "Math 101 - Midterm",
"iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
"created_at": "2026-04-20T10:00:00.000000Z",
"updated_at": "2026-04-20T10:15:42.000000Z"
}
الخطوة 5 - إعادة فتح iframe في وضع القراءة فقط للمسح الضوئي
اعرض إطار iframe مرة أخرى - هذه المرة مع read_only=1 في نهاية عنوان URL. لم يعد بإمكان المعلم تعديل التخطيط، فقط تحميل المسوحات الضوئية. يقوم المتصفح بإعادة توجيه rowResult (تقدم كل ورقة) و getResults (التنزيل النهائي) إلى الخلفية الخاصة بك.
<!-- /scan-exams page. Note read_only = 1 at the end of the URL. -->
<iframe id="formread-frame"
src="https://formread.org/en/api/forms/42/edit/po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6/1"
style="width:100%; height:100vh; border:0"></iframe>
<script>
const FORM_ID = 42;
window.addEventListener('message', async function (e) {
if (e.origin !== 'https://formread.org') return;
// Live progress while each sheet is processed
if (e.data.method === 'rowResult') {
const row = JSON.parse(e.data.rowResult);
console.log('Processed', row.file_name);
}
// Teacher clicked "Download results"
if (e.data.method === 'getResults') {
const results = JSON.parse(e.data.results);
await fetch('/api/grades/bulk', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ form_id: FORM_ID, results })
});
}
});
</script>
الخطوة 6 - معالجة النتائج في الخلفية الخاصة بك
يقوم حدث getResults بتسليم مصفوفة تحتوي على إدخال واحد لكل امتحان تمت معالجته. تتبع المفاتيح النمط {AreaType}-{AreaIndex}[-{QuestionIndex}]. فيما يلي ما سينشره المتصفح إلى نقطة النهاية /api/grades/bulk الخاصة بك:
[
{
"file_name": "student_001.jpg",
"BCR-0": "20260420-001",
"OCR-1": "Alice Johnson",
"OMR-2-0": "3",
"OMR-2-1": "7",
"OMR-2-2": "9"
},
{
"file_name": "student_002.jpg",
"BCR-0": "20260420-002",
"OCR-1": "Ben Carter",
"OMR-2-0": "3",
"OMR-2-1": "6",
"OMR-2-2": "9"
}
]
احتفظ برمزك على الخادم
لا تعرض رمز الحامل (Bearer token) أبدًا في الكود الذي يعمل في المتصفح. جميع استدعاءات الإنشاء/التحديث/القراءة إلى واجهة برمجة تطبيقات FormRead تمر عبر الخادم الخلفي الخاص بك - لا يرى المتصفح أبدًا سوى iframe_token، وهو مقتصر على نموذج واحد.
الأسئلة الشائعة
ما هي واجهة برمجة تطبيقات دمج إطار FormRead المضمن (Iframe)؟
إنها واجهة برمجة تطبيقات REST بالإضافة إلى إطار iframe قابل للتضمين. يدير الخادم الخلفي النماذج عبر نقاط نهاية REST؛ بينما يتم عرض الإطار iframe داخل تطبيق الويب الخاص بك ليتمكن المستخدمون من تصميم النماذج ورفع الصور الممسوحة ومراجعة النتائج دون مغادرة واجهتك.
هل تنتهي صلاحية iframe_token أو يتغير؟
يتم إعادة إنشاء iframe_token في كل مرة يتم فيها تحديث النموذج. احصل دائمًا على أحدث قيمة من واجهة برمجة تطبيقات FormRead REST (GET /api/forms/{id}) من الخادم الخلفي، مباشرة قبل عرض الإطار iframe - لا تخزنه مؤقتًا لفترة طويلة.
ما الفرق بين read_only=0 و read_only=1؟
يفتح read_only=0 الإطار iframe في وضع التحرير ليتمكن المستخدم من تصميم النموذج (وضع دوائر OMR، OCR، مناطق الباركود). بينما يفتح read_only=1 الإطار في وضع المسح فقط - يمكن للمستخدم رفع الأوراق المملوءة وتنزيل النتائج، لكن لا يمكنه تغيير التخطيط.
هل يمكنني الاحتفاظ برمز API في المتصفح؟
لا. يجب أن يبقى رمز الحامل (Bearer token) على الخادم. جميع استدعاءات الإنشاء والتحديث والقراءة إلى واجهة برمجة تطبيقات FormRead REST يجب أن تمر عبر الخادم الخلفي الخاص بك. يحتاج المتصفح فقط إلى iframe_token، وهو مقتصر على نموذج واحد.
كيف أتلقى نتائج المسح؟
يُرسل الإطار iframe رسائل عبر window.postMessage. استمع إلى method="getResults" لاستلام مصفوفة النتائج الكاملة (إدخال واحد لكل ورقة ممسوحة)، وإلى method="rowResult" لعرض تقدم كل ورقة أثناء المسح.