المصادقة
تستخدم جميع طلبات API مفتاح API كرمز حامل (bearer token). أنشئ واحدًا من داخل التطبيق عبر المطوّرون ← مفاتيح API. المفاتيح إمّا للقراءة فقط أو للقراءة والكتابة.
curl https://savrsoft.com/api/v1/events \ -H "Authorization: Bearer savr_live_your_key_here"
الرابط الأساسي: https://savrsoft.com/api/v1 · جميع الاستجابات بصيغة JSON. الأخطاء تُعاد بالشكل { "error": "…" } مع رمز حالة من فئة 4xx أو 5xx.
رموز الحالة
| الرمز | متى تحصل عليه |
|---|---|
200 | قراءة ناجحة. |
201 | تم الإنشاء بنجاح. المحتوى هو { "id": 42 } — اجلب السجل إذا احتجت إلى بقية بياناته. |
400 | حقل مطلوب مفقود، مثل { "error": "name is required" }، أو تعذّرت قراءة مؤشر الترقيم (pagination cursor). |
401 | لا يوجد مفتاح API، أو المفتاح غير صالح الصيغة، أو تم إلغاؤه. |
403 | تم استخدام مفتاح للقراءة فقط في عملية كتابة. أنشئ مفتاح قراءة/كتابة من Developer → API keys. |
404 | السجل غير موجود، أو يتبع منظمة أخرى — الحالتان متعمّد عدم التمييز بينهما. تُعاد هذه الرسالة أيضًا عند استخدام مسار أو طريقة غير معروفة. |
نطاق هذا الـ API
الـ API مخصص لـ القراءة والإنشاء فقط. لا توجد أي نقاط نهاية DELETE, PUT أو PATCH
— أي طلب يستخدم إحداها يُعيد 404 Unknown endpoint, تمامًا كما هو الحال مع أي مسار غير معروف. تتم عمليتا الحذف والتعديل داخل التطبيق، بحيث لا يمكن لأي تكامل خارجي إتلاف سجلات مقدّم الطعام. إذا كنت بحاجة إلى صلاحيات كتابة تتجاوز الإنشاء،
أخبرنا بما تعمل عليه.
التقسيم إلى صفحات
كل نقطة نهاية للقوائم مقسّمة إلى صفحات. مرّر limit (الافتراضي 100، الحد الأقصى 500) و
اتبع next_cursor حتى تصبح has_more القيمة false:
{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0"
}
أعد إرسال المؤشر كما هو للحصول على الصفحة التالية. تعامل معه كقيمة مبهمة — فقد يتغيّر ترميزه:
curl "https://savrsoft.com/api/v1/clients?limit=100&cursor=eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0" \ -H "Authorization: Bearer savr_live_your_key_here"
الترقيم عبر الصفحات مرتبط بآخر صف استلمته، وليس بإزاحة رقمية، لذا فإن الصفوف التي يتم إنشاؤها أو حذفها أثناء التنقل بين الصفحات لن تتسبب في تخطي سجل أو تكراره. يظل المؤشر (cursor) صالحًا إلى أجل غير مسمى.
| المعامل | السلوك |
|---|---|
limit | 1 إلى 500. في حال الغياب أو الصفر أو القيمة السالبة أو غير الرقمية، تُستخدم القيمة الافتراضية 100؛ وأي قيمة أعلى من 500 يتم تحديدها عند 500. |
cursor | next_cursor من الصفحة السابقة. احذفه للحصول على الصفحة الأولى. المؤشر الذي يتعذر قراءته — تالف، أو من نقطة نهاية مختلفة — يُرجع 400 Invalid cursor بدلاً من إعادة البدء من البداية بصمت. |
الترتيب: /events و /invoices الأحدث أولاً؛ /recipes و
/clients حسب الاسم، مع كسر التعادل بواسطة id للحفاظ على استقرار الترقيم عند تكرار الأسماء.
نقاط النهاية
/v1/meمؤسستك (id، الاسم، العملة).
/v1/eventsعرض قائمة الفعاليات، الأحدث أولاً. مقسّمة على صفحات — راجع الترقيم عبر الصفحات أعلاه.
/v1/events/{id}فعالية واحدة مع أطباقها.
/v1/events · يتطلب صلاحية القراءة/الكتابةإنشاء فعالية جديدة. المحتوى:
{ "name": "Acme holiday party", "event_date": "2026-12-18",
"guests": 120, "price_per_head": 55, "event_type": "corporate" }
/v1/recipes · GET/v1/recipes/{id}عرض قائمة الوصفات (مع مسببات الحساسية وعلامات النظام الغذائي)، أو وصفة واحدة مع مكوناتها. القائمة مقسّمة إلى صفحات ومرتبة حسب الاسم.
/v1/clients · POST/v1/clientsعرض قائمة العملاء (مقسّمة إلى صفحات، حسب الاسم) أو إنشاء عميل جديد. محتوى الإنشاء: { "name": "...", "email": "...", "phone": "...", "company": "..." }
/v1/invoices · GET/v1/invoices/{id}عرض قائمة الفواتير مع الإجماليات المحسوبة، الأحدث أولاً، أو فاتورة واحدة مع بنودها. القائمة مقسّمة إلى صفحات.
الويب هوكس
سجّل نقطة نهاية ضمن Developer → Webhooks. نقوم بإرسال POST حمولة JSON عند حدوث الفعاليات:
{
"id": "evt_abc123",
"type": "event.inquiry",
"created_at": "2026-07-17T18:20:00.000Z",
"data": { "id": 42, "name": "Corporate lunch — Dana Ruiz", ... }
}
أنواع الفعاليات
| النوع | يتم التفعيل عند |
|---|---|
event.created | يتم إنشاء حدث |
event.inquiry | يصل طلب تموين جديد عبر الإنترنت |
invoice.sent | يتم تحديد الفاتورة كمُرسلة |
invoice.paid | يتم تحديد الفاتورة كمدفوعة |
proposal.approved | يوافق العميل على عرض |
client.created | يتم إنشاء عميل |
التحقق من التوقيعات
يتضمن كل تسليم x-savrsoft-signature رأس: وهو تجزئة HMAC-SHA256 لجسم الطلب الخام، باستخدام مفتاح توقيع الويب هوك الخاص بك. احسب نفس القيمة وقارنها:
// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', SIGNING_SECRET)
.update(rawBody).digest('hex');
if (sig !== req.headers['x-savrsoft-signature']) reject();
