أدِر سلسلة الطلب كاملة
أنشئ الطلب، واشحن إشعار التسليم، وأصدر الفاتورة واعتمدها، وسوِّ التحصيل في الاستدعاء نفسه. الشحن والفوترة الجزئية مدعومان.
Developer API · بيتا
يربط Kumpara Developer API المتاجر الإلكترونية وأنظمة ERP وبرامج المحاسبة ووسطاء المتاجر بـ Kumpara. تستدعي واجهة /v1 النواة نفسها التي يستدعيها التطبيق: الضوابط نفسها والقيود نفسها والحساب الضريبي نفسه.
واجهة Developer API في بيتا مغلقة حاليًا؛ لم يُفتح الوصول العام بعد ولا نَعِد بتاريخ. يحصل المشاركون على عنوانهم ومفاتيحهم منّا.
كل ما يلي يُبنى بنهايات تعمل اليوم — وليست وعودًا مستقبلية.
أنشئ الطلب، واشحن إشعار التسليم، وأصدر الفاتورة واعتمدها، وسوِّ التحصيل في الاستدعاء نفسه. الشحن والفوترة الجزئية مدعومان.
يعطيك تدفق GET /v1/changes نوع السجل المتغيّر ومعرّفه، وتقرأ التفاصيل من نهايته. ولا يفرّق التدفق بين التطبيق والجوال والـ API.
يكتب POST /v1/stock-levels/actions/set نتيجة الجرد مباشرة، ويتحوّل الفرق إلى حركة تسوية.
استدعاء واحد يحوّل الفاتورة المعتمدة إلى مستند إلكتروني، ويُختار السيناريو على الخادم. وتزامن صندوق الوارد وتنزّل XML/PDF.
الرصيد وحده لا يكفي: قيود الدفتر والبنود المفتوحة وتقادم الذمم نهايات منفصلة. وتسوّي التحصيلات على الفواتير المفتوحة.
للأرصدة الافتتاحية للعملاء وللمخزون نهايات خاصة، ولكل منها نظير عكسي؛ فالدفاتر بالإضافة فقط.
كل عملية كتابة تحمل ثلاثة ترويسات: Authorization وIdempotency-Key وContent-Type.
في التطبيق: الإعدادات ← مفاتيح API. اختر اسمًا وشركة وصلاحيات. يُعرض المفتاح مرة واحدة.
يعيد GET /v1/me المنشأة والشركة والبيئة والصلاحيات المرتبطة بالمفتاح.
طابِق بالرقم الضريبي أو رمز الحساب: يُحدَّث الموجود ويُنشأ المفقود.
بـ approve: true يتمّ الإنشاء والاعتماد في معاملة واحدة: الرقم والمديونية وخروج المخزون معًا.
تمرّر الفاتورة عند إنشاء الدفعة: يُكتب دفتر النقد ودفتر العميل والتسوية في معاملة واحدة.
كل طلب يحمل ترويسة Authorization: Bearer. أول استدعاء يخبرك بالمنشأة والشركة المرتبطتين بالمفتاح
وبالصلاحيات التي يحملها:
curl -s "https://api.kumpara.net/v1/me" \
-H "Authorization: Bearer kp_live_a1b2c3d4_…"
ثم يخبرك GET /v1/capabilities هل المستندات الإلكترونية موصولة لهذه الشركة، وكم بقي من الرصيد، وما
العملة الأساسية.
curl -s -X POST "https://api.kumpara.net/v1/contacts/actions/upsert?matchBy=taxNumber" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: contact-4711-2026-09-23" \
-H "Content-Type: application/json" \
-d '{ "name": "Örnek Gıda Ltd. Şti.", "type": "customer", "taxNumber": "1234567890" }'
يخبرك الحقل created في الاستجابة هل أُنشئ سجل جديد أم حُدّث سجل قائم. ويقبل matchBy القيمتين
taxNumber أو code فقط.
لا يوجد حقل مبلغ في بند الفاتورة. أنت ترسل الكمية والسعر والخصم ونسبة الضريبة، ويحسب الخادم الباقي.
curl -s -X POST "https://api.kumpara.net/v1/sales-invoices" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: order-88213-invoice" \
-H "Content-Type: application/json" \
-d '{ "contactId": "6f1c…", "currency": "TRY", "approve": true,
"lines": [ { "productId": "9a3e…", "quantity": 10, "unitPrice": 250, "vatRate": 20 } ] }'
تنفّذ approve: true الإنشاء والاعتماد في معاملة واحدة. وهذه حركة مالية، لذا يحتاج المفتاح إلى
sales:approve إلى جانب sales:write.
curl -s -X POST "https://api.kumpara.net/v1/payments" \
-H "Authorization: Bearer kp_live_…" \
-H "Idempotency-Key: payment-88213" \
-H "Content-Type: application/json" \
-d '{ "contactId": "6f1c…", "cashAccountId": "2b77…", "direction": "incoming",
"amount": 3060, "invoiceType": "sales_invoice", "invoiceId": "c41b…" }'
curl -s "https://api.kumpara.net/v1/changes?since=2026-09-23T06:00:00Z&types=sales_invoice,payment" \
-H "Authorization: Bearer kp_live_…"
في الاستدعاء التالي مرّر meta.checkpoint كـ since؛ الحدّ حصري فلا يعود السجل نفسه مرتين. ونوصي
بتداخل خمس دقائق، فالقراءة عملية متكرّرة الأثر والتكرار غير ضار.
يُرسل المفتاح في Authorization: Bearer kp_live_… (أو X-Api-Key). ولا تُخزَّن قيمته الصريحة؛ يحتفظ
Kumpara ببصمة SHA-256 والبادئة فقط. كل مفتاح مقيَّد بشركة واحدة، ولا يمكن معماريًا أن تعود بيانات
شركة أخرى. ولا يمكن لصلاحيات المفتاح أن تتجاوز دور المستخدم الذي أنشأه.
الصلاحيات على شكل {مورد}:{إجراء} وعددها ثمانٍ وعشرون: read للعرض، وwrite للإنشاء والتعديل،
وapprove للاعتماد والإلغاء والعكس، وissue/cancel/incoming للمستندات الإلكترونية. وتعيد النهاية
غير المصرّح بها 403 insufficient_scope مع اسم الصلاحية الناقصة.
كل عملية كتابة تتطلب Idempotency-Key. يُخزَّن المفتاح داخل المعاملة نفسها التي تكتب السجل. والطلب
الثاني بالمفتاح ذاته لا يكرّر العمل. وتأتي الاستجابة بإحدى صورتين: 409 idempotency_replayed (تقرأ
السجل المُنشأ بـ GET)، أو 200 مع جسم الاستجابة الأولى وراية replayed: true. وكلتاهما تعني «نُفِّذت
العملية سابقًا»، وعلى عميلك أن يعدّ كلتيهما نجاحًا.
تُخزَّن المبالغ بنوع numeric(19,4) وتعود في JSON كسلسلة نصية، فلا يحدث تقريب عائم. ولا يُفصل المبلغ
عن عملته أبدًا.
يحمل كل بند مالي لقطة سعر الصرف الخاصة به: originalAmount وoriginalCurrency وexchangeRate
وbaseAmount وbaseCurrency. وحتى لو تغيّرت الأسعار لاحقًا لا يتغيّر المستند السابق. ويمكنك تمرير السعر
في exchangeRate؛ وإن لم تمرّره استُخدم 1.
تُرقَّم القوائم بـ cursor بلا offset، وتحمل الاستجابة meta.nextCursor وmeta.hasMore. وحجم الصفحة
pageSize افتراضيًا 50 وحدّه 200. وللفروق استخدم معامل الاستعلام updatedAfter أو تدفق /v1/changes.
الأخطاء بصيغة RFC 9457 application/problem+json وتحمل حقل code ثابتًا: 400 تعذّرت قراءة الطلب،
401 مفتاح غير صالح (unauthorized)، 403 صلاحية ناقصة، 404 سجل غير موجود،
409 تعارض، 422 مخالفة قاعدة عمل، 429 تجاوز الحد.
القراءة والكتابة في سلّتين منفصلتين: افتراضيًا 600 قراءة و120 كتابة في الدقيقة لكل مفتاح، مع
ترويسات RateLimit-* في كل استجابة. وتحمل كل استجابة X-Request-Id. والعقد كاملًا منشور بصيغة
OpenAPI 3: https://api.kumpara.net/v1/openapi.json.
الجدول أدناه هو كامل الواجهة العاملة اليوم. أما المعاملات الكاملة والأجسام ومخططات الاستجابة فموجودة في
OpenAPI: https://api.kumpara.net/v1/docs.
| المجال | النهايات الرئيسية | الصلاحيات |
|---|---|---|
| السياق | GET /v1/me, GET /v1/capabilities |
me:read |
| بطاقة جهة التعامل | GET · POST /v1/contacts, POST /v1/contacts/actions/upsert |
contacts:read · contacts:write |
| وضع جهة التعامل | GET /v1/contacts/{id}/balance, …/ledger-entries, …/open-items, GET /v1/aging |
contacts:read |
| المنتجات والمتغيرات | GET · POST /v1/products, POST /v1/products/{id}/variants |
products:read · products:write |
| المخزون | GET /v1/stock-levels, POST /v1/stock-levels/actions/set, GET /v1/stock-movements |
stock:read · stock:write |
| الطلبات | GET · POST /v1/orders, POST /v1/orders/{id}/actions/cancel |
sales:read · sales:write |
| إشعارات التسليم | GET · POST /v1/delivery-notes, …/actions/ship |
sales:read · sales:write |
| فواتير المبيعات | GET · POST /v1/sales-invoices, …/{id}/actions/approve, …/{id}/actions/cancel |
sales:read · sales:write · sales:approve |
| فواتير المشتريات | GET · POST /v1/purchase-invoices, …/{id}/actions/approve |
purchase:* |
| التحصيلات والدفعات | GET · POST /v1/payments, POST /v1/payments/{id}/actions/allocate |
payments:read · payments:write |
| الصندوق والبنك | GET /v1/cash-accounts, …/{id}/ledger-entries |
cash:read |
| الشيكات والسندات | GET /v1/cheques |
cheques:read |
| المستندات الإلكترونية | POST /v1/sales-invoices/{id}/actions/issue-e-document, GET /v1/e-documents, GET /v1/incoming-e-documents |
edocuments:* |
| الفهارس المرجعية | GET /v1/warehouses, GET /v1/categories, GET /v1/reference/{type} |
catalog:read |
| تدفق التغييرات | GET /v1/changes |
changes:read |
كيف تترابط سلسلة المستندات. يقبل جسم إشعار التسليم orderId، ويقبل جسم الفاتورة orderId و
deliveryNoteIds[]، وتتطابق البنود عبر orderLineId وdeliveryNoteLineId. والكمية المتبقية ليست عدّادًا
مخزَّنًا بل تُشتقّ من الفواتير غير الملغاة.
خروج المخزون يحدث في مكان واحد. لا يخصم الشحن واعتماد الفاتورة البضاعة مرتين: إجمالي الخروج هو
max(Σ الشحنات, Σ الفواتير المعتمدة)، ويكتب كل مستند فرقه فقط.
نذكر ما هو غير متاح أيضًا كي لا تبني على افتراض خاطئ.
الطريق العملي اليوم هو استطلاع GET /v1/changes؛ الصلاحية موجودة في الفهرس لكن النهاية غير منشورة.
بادئة kp_test_ مجرد تسمية اليوم وتكتب في بياناتك الحقيقية. أنشئ شركة منفصلة للتجريب.
لا يُضاف التحكّم بالتزامن ناقصًا دون عمود الإصدار الذي يعتمد عليه؛ فانطباع الحماية أسوأ من غيابها.
خلال البيتا ينشئ عميلك مفتاحًا ضيّق الصلاحيات من لوحته؛ وتدفّق شاشة الموافقة ضمن الخطة.
تعمل قراءة صندوق الوارد والردّ عليه وتجاهله؛ أما مطابقة البنود بالمنتجات فتتم في التطبيق حاليًا.
يعمل تقادم الذمم (GET /v1/aging)؛ أما الأرباح والضريبة والتصدير غير المتزامن فغير متاحة بعد.
العزل يتم على مستوى قاعدة البيانات. ما يفصل منشأة عن أخرى ليس مرشّحًا في التطبيق بل طبقة أمان الصفوف في PostgreSQL نفسها. يتصل طلب الـ API بدور أقلّ امتيازًا، ويُكتب السياق في قاعدة البيانات عند فتح الاتصال، فلا يمكن لاستعلام خاطئ أن يعيد صفّ منشأة أخرى. ويأتي فصل الشركات فوق ذلك: المفتاح مقيَّد بشركة واحدة.
المفتاح لا يُخزَّن. تُحفظ بصمة SHA-256 والبادئة (kp_live_a1b2c3d4) فقط. وتظهر القيمة الصريحة مرة واحدة
عند الإنشاء؛ وإن فقدتها فلا يمكن استرجاعها بل تُصدر مفتاحًا جديدًا. ولا تُكتب المفاتيح في السجلات، والإلغاء
يسري فورًا.
لا تصعيد للصلاحيات. لا تتجاوز صلاحيات المفتاح دور من أنشأه. وإنشاء فاتورة بـ approve: true يحتاج
sales:approve إلى جانب sales:write، وإلا رُفض الطلب بدل حفظه مسوّدة بصمت.
كل إجراء يترك أثرًا. تُسجَّل كل كتابة عبر الـ API في سجل التدقيق ببادئة المفتاح كفاعل
(api:kp_live_a1b2c3d4)، ويكتب التطبيق والجوال والـ API في السجل نفسه.
البيانات الشخصية بصلاحية ضيّقة. تعود حقول مثل رقم الهوية والـ IBAN والاسم والعنوان مُقنَّعة إلى
المفاتيح التي لا تملك صلاحية pii:read — تبقى الأحرف الأربعة الأخيرة ظاهرة وتستمر النهاية في العمل.
فإن لم يحتجها تكاملك فلا تمنحها؛ فأفضل حماية ألّا تغادر البيانات أصلًا.
كيف تحفظ المفتاح. على الخادم، في متغيّر بيئة أو مدير أسرار؛ ولا تضعه في الشيفرة أو المتصفح أو تطبيق
الجوال. وأصدر مفتاحًا لكل تكامل. وعند فتح طلب دعم شارك requestId وIdempotency-Key، ولا تشارك مفتاحك
أبدًا.
الوصول غير مقيّد بالباقة. تختلف الباقات في حدود الطلبات والحصص وهي قابلة للضبط. خلال البيتا يُمنح الوصول بطلب.
لا؛ الخادم هو المرجع الوحيد. أنت ترسل الكمية والسعر ونسبة الخصم ونسبة الضريبة ورمز الاستقطاع والعملة، ويحسب الخادم إجماليات البند والضريبة المستقطعة والمبلغ الأساسي ورقم المستند.
لا. كل عملية كتابة تتطلب Idempotency-Key، ويُخزَّن المفتاح داخل المعاملة نفسها التي تكتب السجل. والطلب الثاني بالمفتاح ذاته لا يكرّر العمل: إمّا تتلقّى 409 idempotency_replayed فتقرأ السجل بـ GET، وإمّا 200 مع جسم الاستجابة الأولى وراية replayed: true. وكلتاهما تُعدّ نجاحًا.
لا، المستند المعتمد غير قابل للتعديل. طريق التصحيح هو الإلغاء ثم مستند جديد؛ والإلغاء يكتب قيودًا عكسية. لا يوجد UPDATE/DELETE في الدفاتر.
نعم. لا يفرّق تدفق GET /v1/changes بين مصدر التغيير: التطبيق والجوال والـ API تصل إلى التدفق نفسه، وهو يعطي نوع السجل ومعرّفه فقط.
ليس بعد، ونقولها صراحة. مفتاح kp_test_ اليوم مجرد تسمية ويكتب في بياناتك الحقيقية. للتجريب أنشئ شركة منفصلة؛ والبيئة المعزولة ضمن خارطة الطريق.
ليس بعد. الطريق العملي اليوم هو استطلاع GET /v1/changes: مرّر آخر meta.checkpoint تلقيته كـ since في الطلب التالي. الـ Webhooks ضمن خارطة الطريق.
كل مفتاح مقيّد بشركة واحدة ولا يرى سوى بياناتها. في التكامل متعدد الشركات تُنشئ مفتاحًا لكل شركة.
لا. يُستهلك الرصيد في حركة المستندات الإلكترونية فقط: كل مستند صادر أو وارد يساوي رصيدًا واحدًا. أما ما تنشئه داخل النظام فلا يستهلك شيئًا.
لا يمكن استرجاعه. يخزّن Kumpara بصمة SHA-256 والبادئة فقط، ويُعرض المفتاح مرة واحدة عند الإنشاء. إن فقدته فألغِ القديم وأنشئ مفتاحًا جديدًا؛ والإلغاء يسري فورًا.
نقبل منصّات المتاجر وأنظمة ERP وبرامج المحاسبة ومكاتب المحاسبة ووسطاء المتاجر. يحصل المشاركون على الوصول وإشعار مسبق بتغيّرات العقد وقناة تواصل مباشرة.