١. مقدمة وبداية سريعة
تتيح هذه البوابة لنظامك سحب بيانات الحضور/البصمات الخاصة بمؤسستك وإدارة أجهزتها، عبر توكن واحد خاص بمؤسستك. كل طلب يُحدِّد مؤسستك تلقائياً — لن ترى إلا بياناتك.
كل المسارات تبدأ بـ /api/v1. أول تجربة — تحقّق من توكنك:
curl -H "Authorization: Bearer __TOKEN__" \
__BASE__/api/v1/meإن رجع "ok": true ومعلومات مؤسستك فالتوكن يعمل.
٢. المصادقة
أرسل التوكن في ترويسة Authorization مع كل طلب:
Authorization: Bearer __TOKEN__٣. سحب البيانات (قراءة)
معلومات مؤسستك + أعداد الأجهزة والطلاب.
curl -H "Authorization: Bearer __TOKEN__" __BASE__/api/v1/meأجهزتك وحالة اتصالها الآن (online حيّ، وليس قيمة قديمة).
curl -H "Authorization: Bearer __TOKEN__" __BASE__/api/v1/devicesالطلاب/الموظفون المسجّلون على أجهزتك (الرقم والاسم).
curl -H "Authorization: Bearer __TOKEN__" __BASE__/api/v1/studentsسجلات الحضور/البصمات (الأحدث أولاً) مع ترقيم بالمؤشّر (cursor).
| المعامل | الوصف |
|---|---|
limit | عدد السجلات (١–٥٠٠، الافتراضي ١٠٠) |
since | من تاريخ (ISO مثل 2026-06-23T00:00:00Z) |
until | إلى تاريخ (ISO) |
cursor | مؤشّر الصفحة التالية (من nextCursor) |
curl -H "Authorization: Bearer __TOKEN__" \
"__BASE__/api/v1/attendance?limit=100"مثال الرد:
{
"ok": true,
"attendance": [
{
"sn": "STC010083287",
"enrollid": 1,
"name": "علي رياض",
"time": "2026-06-19 14:51:06",
"eventAt": "2026-06-19T11:51:06.000Z",
"inout": 0,
"mode": 8,
"imageUrl": "/images/..._.jpg",
"createdAt": "2026-06-19T11:51:07.000Z"
}
],
"hasMore": true,
"nextCursor": "eyJ0Ijox..."
}inout: 0 = دخول، 1 = خروج · mode: 8/15 = وجه، 0/1 = بصمة إصبع.
٤. إدارة الأجهزة
أوامر تُرسَل للجهاز وتُرجع فوراً 202 مع commandId (لا تنتظر رد الجهاز). يجب أن يكون الجهاز متّصلاً (وإلا 409).
تسجيل/تعديل مستخدم على الجهاز. backupnum: 0–9 بصمة · 10 كلمة مرور · 11 بطاقة · 20–27 وجه · 50 صورة وجه.
curl -X POST "__BASE__/api/v1/devices/STC010083287/users" \
-H "Authorization: Bearer __TOKEN__" \
-H "content-type: application/json" \
-d '{"enrollid":20,"name":"طالب جديد","backupnum":0}'حذف مستخدم. أضف ?backupnum= لحذف قالب محدّد (الافتراضي: الكل).
curl -X DELETE "__BASE__/api/v1/devices/STC010083287/users/20" \
-H "Authorization: Bearer __TOKEN__"فتح الباب (لأجهزة التحكم بالدخول). الجسم اختياري: {"doornum":1}.
curl -X POST "__BASE__/api/v1/devices/STC010083287/open-door" \
-H "Authorization: Bearer __TOKEN__" -H "content-type: application/json" -d '{}'سحب فوري من الجهاز. what: newlog (سجلات جديدة) أو userlist (المستخدمون) أو both.
curl -X POST "__BASE__/api/v1/devices/STC010083287/sync" \
-H "Authorization: Bearer __TOKEN__" -H "content-type: application/json" \
-d '{"what":"both"}'٥. البث اللحظي (Real-time stream)
بدل السحب المتكرر، افتح اتصال WebSocket واحد فيصلك كل حضور لحظة حدوثه — معزولاً لمؤسستك فقط (توكنك يحدّد مؤسستك، ولا ترى أحداث غيرها).
المصادقة بترويسة Authorization: Bearer (للخوادم) أو ?token= (للمتصفح، لأنه لا يدعم ترويسات في WebSocket).
أنواع الأحداث الواردة:
{ "type": "connected", "institution": { "id": "...", "name": "...", "slug": "..." } }
{ "type": "attendance", "sn": "STC010083287", "enrollid": 1, "name": "علي رياض",
"time": "2026-06-19 14:51:06", "inout": 0, "mode": 8, "at": "2026-06-19T11:51:07.000Z" }
{ "type": "device", "sn": "STC010083287", "online": true, "at": "..." }Node.js (خادم — بترويسة Authorization)
const WebSocket = require("ws");
function connect() {
const ws = new WebSocket("__WSBASE__/api/v1/stream", {
headers: { Authorization: "Bearer __TOKEN__" }
});
ws.on("message", (raw) => {
const ev = JSON.parse(raw);
if (ev.type === "attendance")
console.log("حضور:", ev.enrollid, ev.name, ev.time, ev.inout ? "خروج" : "دخول");
});
ws.on("close", () => setTimeout(connect, 3000)); // أعد الاتصال تلقائياً
ws.on("error", () => {});
}
connect();المتصفح (التوكن في الرابط)
const ws = new WebSocket("__WSBASE__/api/v1/stream?token=__TOKEN__");
ws.onmessage = (e) => {
const ev = JSON.parse(e.data);
if (ev.type === "attendance") console.log("حضور:", ev.name, ev.time);
};401.٦. سحب الحضور تدريجياً (المؤشّر)
لجلب الجديد فقط في كل مرة: استخدم nextCursor من الرد السابق كـ cursor للطلب التالي، ودُر طالما hasMore = true. احفظ آخر مؤشّر لتبدأ منه لاحقاً.
since أقدم بقليل، أو طابِق السجلات بمفتاح enrollid + time.
٧. أمثلة تكامل بلغات مختلفة
سحب كل الحضور صفحةً صفحة:
const BASE = "__BASE__";
const TOKEN = "__TOKEN__";
async function pullAll(cursor) {
let url = `${BASE}/api/v1/attendance?limit=200`;
if (cursor) url += `&cursor=${encodeURIComponent(cursor)}`;
const res = await fetch(url, { headers: { Authorization: `Bearer ${TOKEN}` } });
const data = await res.json();
for (const rec of data.attendance) {
// خزّن rec في نظامك — المفتاح الفريد: enrollid + time
console.log(rec.enrollid, rec.name, rec.time);
}
if (data.hasMore) return pullAll(data.nextCursor);
return data.nextCursor; // احفظه لتبدأ منه لاحقاً
}
pullAll();<?php
$BASE = "__BASE__";
$TOKEN = "__TOKEN__";
function pull($BASE, $TOKEN, $cursor = null) {
$url = "$BASE/api/v1/attendance?limit=200";
if ($cursor) $url .= "&cursor=" . urlencode($cursor);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($data["attendance"] as $rec) {
// خزّن $rec في نظامك (enrollid + time مفتاح فريد)
}
if (!empty($data["hasMore"])) return pull($BASE, $TOKEN, $data["nextCursor"]);
return $data["nextCursor"];
}
pull($BASE, $TOKEN);import requests
BASE = "__BASE__"
TOKEN = "__TOKEN__"
H = {"Authorization": f"Bearer {TOKEN}"}
def pull(cursor=None):
params = {"limit": 200}
if cursor: params["cursor"] = cursor
data = requests.get(f"{BASE}/api/v1/attendance", headers=H, params=params).json()
for rec in data["attendance"]:
print(rec["enrollid"], rec["name"], rec["time"]) # خزّنه في نظامك
if data.get("hasMore"):
return pull(data["nextCursor"])
return data.get("nextCursor")
pull()٨. الأخطاء والحدود
كل الأخطاء بالشكل: {"ok": false, "error": "...", "message": "..."}
| الكود | المعنى |
|---|---|
| 400 | معامل ناقص أو غير صالح |
| 401 | توكن ناقص أو خاطئ |
| 404 | الجهاز غير موجود أو ليس ملكاً لمؤسستك |
| 409 | device_offline — الجهاز غير متصل الآن |
| 429 | تجاوزت حد الطلبات |
| 202 | أمر الإدارة قُبل وأُرسل للجهاز |
الحدود: القراءة ١٢٠ طلب/دقيقة · الإدارة ٣٠ طلب/دقيقة لكل توكن.
٩. ملاحظات مهمة
- العزل مضمون: توكنك يرى بيانات مؤسستك فقط.
- عدّة أجهزة: كل أجهزة مؤسستك تعمل بنفس التوكن.
- الصور:
imageUrlمرجعي فقط، لا يُجلب عبر هذه البوابة في الإصدار الحالي. - المفتاح الفريد للسجل:
sn + enrollid + time(قد تتكرر بصمتان في نفس الثانية بمؤشّر مختلف). - استخدم HTTPS دائماً في الإنتاج.