واجهة REST للمطورين على العنوان
https://books.basmtak.com/partner/v1. تقرأ جهات الاتصال والأصناف والحسابات والمستندات والتقارير، وتنشئ جهات الاتصال والفواتير والإشعارات والسندات وفواتير الموردين والقيود، بالقواعد نفسها التي تحكم الشاشة. والإشعارات (Webhooks) تخبر نظامك بما يحدث في الدفاتر. كل مفتاح يعمل على منشأة واحدة.قبل أن تبدأ
- مفاتيح الربط تتوفر حسب باقة اشتراكك، ويظهر تبويبها لمن يدير المنشأة.
- مطوّر يعرف HTTP وJSON.
- عنوان HTTPS لاستقبال الإشعارات، إن أردتها.
خطوات الربط
أنشئ مفتاحاً
افتح المنشآت والمستخدمون، ثم تبويب مفاتيح الربط، واضغط مفتاح جديد. اختر الشخص في يعمل بصلاحيات: لا يستطيع المفتاح تجاوز صلاحياته، وإيقافه يوقف المفتاح. فعّل ما يحتاجه نظامك فقط، ومرّر صف الصلاحيات جانبياً لترى بقيتها، ويمكنك تحديد تاريخ انتهاء، ثم اضغط أنشئ المفتاح.
المفتاح يظهر مرة واحدة ويُخزَّن عندنا مُجزّأً، فانسخه فوراً. ولا تضعه في كود يصل إلى المتصفح. الصلاحيات
webhooks وjournals وstock وsettlements لا تأتي مع خياري قراءة وكتابة العامين، بل تُمنح بالاسم.
جرّب الاتصال
أرسل المفتاح في ترويسة
Authorization. يعيد /ping المنشأة ووضع الاشتراك وصلاحيات المفتاح وحدّ الطلبات وساعة الخادم. ووصف الواجهة الكامل بصيغة OpenAPI في /partner/v1/openapi.json، بالمفتاح نفسه.bash
curl https://books.basmtak.com/partner/v1/ping \ -H "Authorization: Bearer bsk_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Accept: application/json"
اقرأ البيانات
كل قائمة صفحات، و
per_page حتى 200. استخدم updated_since لقراءة ما تغيّر فقط، وأرسل قيمتي المؤشر cursor في الطلب التالي. المسارات: /contacts و/items و/accounts و/invoices و/credit-notes و/receipts و/bills و/journals و/reports/trial-balance و/reports/vat.bash
# the first page of invoices changed since a moment
curl "https://books.basmtak.com/partner/v1/invoices?updated_since=2026-09-01T00:00:00%2B03:00&per_page=100" \
-H "Authorization: Bearer $BOOKS_KEY"
# every list answers: data, page, per_page, total, last_page
# with updated_since it adds: cursor { updated_since, since_id } and has_more
# pass both cursor values on the next call
اكتب بأمان
أرسل
external_id من نظامك مع كل مستند. إذا انقطع الرد وأعدت الطلب بالمعرّف نفسه يعود المستند نفسه دون تكرار، ويكون created بقيمة false. وبدون issue: true تبقى الفاتورة مسودة، وتصدرها لاحقاً بالمسار POST /invoices/{id}/issue. الإصدار يرقّم الفاتورة ويرحّل قيدها ويبدأ إرسالها إلى الهيئة.bash
curl -X POST https://books.basmtak.com/partner/v1/invoices \
-H "Authorization: Bearer $BOOKS_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "shop-order-10482",
"contact_id": 118,
"date": "2026-09-30",
"issue": true,
"lines": [
{ "item_id": 13, "quantity": 2 },
{ "description": "Delivery", "quantity": 1, "unit_price": 40 }
]
}'
# answers { "invoice": { ... }, "created": true }
# the same external_id again answers the same invoice with "created": false
اشترك في الإشعارات
يحتاج المفتاح الصلاحية
webhooks:write. الأحداث العاملة: invoice.created وinvoice.issued وcredit_note.created وreceipt.created وbill.created وcontact.created وjournal.posted.الحدث
invoice.cleared مسجّل لكنه لا يُرسل حالياً، فلا تبنِ عليه. وjournal.posted يخص القيود المرسلة عبر الواجهة فقط.bash
curl -X POST https://books.basmtak.com/partner/v1/webhooks \
-H "Authorization: Bearer $BOOKS_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/books",
"events": ["invoice.issued", "receipt.created"],
"description": "Online store"
}'
# the answer holds the signing secret (whsec_...) once: store it now
تحقق من التوقيع
كل رسالة تحمل الترويسة
X-Books-Signature بالصيغة t=<unix>,v1=<hex>، وهي HMAC-SHA256 لنص t.body بسرّ الاشتراك. وتحمل أيضاً X-Books-Event وX-Books-Delivery وX-Books-Attempt. جسم الرسالة فيه id وevent وevent_key وbusiness_id وcreated_at وattempt وdata.javascript
import crypto from 'node:crypto';
// rawBody: the request body exactly as received, before any JSON parsing
function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const signed = `${parts.t}.${rawBody}`;
const expected = crypto.createHmac('sha256', secret).update(signed).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < toleranceSeconds;
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
// header: req.headers['x-books-signature'], e.g. t=1790000000,v1=9f2c...
// answer any 2xx to confirm delivery
ما الذي ينتقل
- قراءة من الدفاتر:
contacts:readوitems:readوaccounts:readوinvoices:readوcredit_notes:readوreceipts:readوbills:readوreports:readوjournals:read. - كتابة إلى الدفاتر:
contacts:writeوinvoices:writeوcredit_notes:writeوreceipts:writeوbills:writeوjournals:write. - لا يمكن إنشاء الأصناف ولا الحسابات عبر الواجهة، فهي قراءة فقط.
- من الدفاتر إلى نظامك: أحداث موقّعة إلى العنوان الذي تختاره.
حل المشكلات
الرد 401
المفتاح مفقود أو خاطئ أو ملغى أو منتهٍ. تأكد من الترويسة
Authorization: Bearer ....الرد 403 مع ScopeRequired
المفتاح لا يملك الصلاحية المذكورة في
details.scope. أما FeatureNotInPlan فيعني أن باقة المنشأة لا تشمل الواجهة البرمجية.الرد 402
الدفاتر للقراءة فقط لأن الاشتراك انتهى. جدّد الاشتراك لتعود الكتابة.
الرد 429
تجاوزت الحد. الحد الافتراضي 120 طلباً في الدقيقة لكل مفتاح، وتوجد حدود على العنوان أيضاً. انتظر المدة في الترويسة
Retry-After.لم يصل إشعار
اقرأ سجل التسليم من
GET /webhooks/deliveries. عند الفشل تُعاد المحاولة بعد دقيقة، ثم 5 و15 دقيقة، ثم ساعة، ثم 6 ساعات، وبعدها تتوقف بحالة dead. أعد الإرسال بالمسار POST /webhooks/deliveries/{id}/replay.توقف اشتراك الإشعارات وحده
يتوقف الاشتراك بعد 10 إخفاقات متتالية. أصلح العنوان ثم أعد تشغيله بالمسار
POST /webhooks/{id}/active.