# مزامنة نظام ERP

> نسخ فواتير التاجر ومدفوعاته وإشعاراته الدائنة إلى نظامك بلا نقص ولا تكرار، والكتابة في كسور بأمان باستخدام معرّفاتك الخاصة.

هذه الصفحة للأنظمة التي تنسخ مستندات التاجر، مثل أنظمة ERP أو برامج المحاسبة، وقد تكتب في كسور أيضاً.

## اقرأ الجديد

كل قائمة ترجع أحدث السجلات أولاً، أياً كانت القناة التي أنشأتها: نقطة البيع، أو الكشك الذاتي، أو المتجر الإلكتروني، أو لوحة التحكم، أو الـ API. والسجل الذي يُنشأ أثناء تنقلك بين الصفحات يظهر في أول القائمة، فلا يغيّر الصفحات التي تقرؤها. التفاصيل في [تقسيم النتائج](https://docs.kosoor.com.sa/ar/pagination.md).

لجلب الجديد منذ آخر مرة:

1. احفظ الـ `id` لأحدث سجل خزّنته من كل قائمة.
2. اطلب الصفحة الأولى: `GET /v1/sales-invoices?limit=100`.
3. خزّن السجلات واحداً واحداً حتى تصل إلى الـ `id` الذي حفظته، ثم توقف.
4. إذا لم تصل إليه وكانت قيمة `hasMore` هي `true`، فاطلب الصفحة التالية مع `startingAfter` بقيمة آخر `id` في هذه الصفحة، وارجع إلى الخطوة 3.
5. احفظ الـ `id` لأول سجل في الصفحة الأولى للمرة القادمة.

```bash
curl "https://api.kosoor.com.sa/v1/sales-invoices?limit=100&startingAfter=c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f" \
  -H "Authorization: Bearer ksr_live_..."
```

```json
{
  "data": [
    {
      "id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
      "object": "salesInvoice",
      "number": "INV-1042",
      "issueDate": "2026-11-07",
      "supplyDate": null,
      "dueDate": null,
      "branchId": "9a0b1c2d-3e4f-4a5b-8c6d-7e8f9a0b1c2d",
      "customerId": "5a4db0c5-0000-4000-8000-000000000001",
      "currency": "SAR",
      "subtotal": 100,
      "discountTotal": 0,
      "vatTotal": 15,
      "total": 115,
      "amountPaid": 115,
      "amountDue": 0,
      "notes": null,
      "costCentreId": null,
      "referenceId": "order-20417",
      "metadata": {},
      "createdVia": "api",
      "zatca": {
        "kind": "simplified",
        "status": "reported",
        "uuid": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
        "counter": 17,
        "hash": "dZBGdHmJoIQ0SOi+mt6KcGC6mWlVmpjbPEJ4y/3tps4=",
        "qr": "ARBTYW5kYm94IE1lcmNoYW50Ag8zOTk5OTk5OTk5MDAwMDMDFDIwMjYtMTEtMDdUMDk6MzA6MTJaBAYxMTUuMDAFBTE1LjAw",
        "submittedAt": "2026-11-07T09:30:40.118Z",
        "clearedAt": null,
        "reportedAt": "2026-11-07T09:30:41.204Z",
        "errors": []
      }
    }
  ],
  "hasMore": false
}
```

القائمة لا ترجع بنود الفواتير (`lines`). أضف `expand=lines` لتحصل عليها، و `expand=customer` لتضمين بيانات العميل (ويحتاج `customers:read` أيضاً)، وكرّر الـ Parameter للاثنين معاً: `expand=lines&expand=customer`.

والخطوات نفسها تصلح لـ `GET /v1/payments` و `GET /v1/credit-notes`. وقائمة الإشعارات الدائنة تشمل الاسترجاع من نقطة البيع ومن لوحة التحكم.

ولتحميل البيانات السابقة مرة واحدة، استخدم فلاتر التاريخ: `issuedAfter` و `issuedBefore` لفواتير المبيعات والإشعارات الدائنة (لحظة زمنية بصيغة ISO 8601، مثل `2026-01-01T00:00:00Z`)، و `dateFrom` و `dateTo` للمدفوعات (أيام، مثل `2026-01-01`).

## التمييز بين القنوات

يوضح `createdVia` القناة التي أنشأت السجل: `api`، أو `dashboard`، أو `pos` (نقطة البيع)، أو `kiosk`، أو `storefront` (المتجر الإلكتروني للتاجر)، أو `unknown` للسجل المحفوظ قبل أن تبدأ كسور بتسجيل القناة. والقيمة `api` تشمل كل مفتاح أصدره التاجر، وليس مفتاحك وحده. ولتتعرف على سجلاتك أنت، أعطها `referenceId` خاصاً بك، أو مفتاحاً في `metadata`.

## السجلات التي تتغير بعد تخزينها

تعرض القائمة كل سجل مرة واحدة، عند إنشائه. لكن بعض الحقول تتغير لاحقاً:

| الحقل | يتغير عندما |
|---|---|
| `zatca.status` وبقية حقول `zatca` | ترد الهيئة: تتحول `pending` إلى `cleared` أو `reported` أو `rejected` |
| `amountPaid` و `amountDue` في الفاتورة | تُخصَّص لها دفعة، أو يخصم منها إشعار دائن |
| أي حقل في العميل | يعدّله التاجر أو أحد المفاتيح |

اقرأ السجل مرة أخرى بـ `GET` على الـ `id` الخاص به عندما تحتاج أحدث بياناته. والفلتر `zatcaStatus=pending` في `GET /v1/sales-invoices` و `GET /v1/credit-notes` يعرض المستندات التي ما زالت تنتظر هيئة الزكاة والضريبة والجمارك. ونتائج الهيئة التي تصل لاحقاً تُرسل إليك عن طريق Webhooks. التفاصيل في [Webhooks](https://docs.kosoor.com.sa/ar/webhooks.md).

## الكتابة بلا تكرار

شيئان يحميان طلب الكتابة، ويعملان معاً:

- **`Idempotency-Key`**: إرسال الطلب نفسه مرة أخرى بالمفتاح نفسه يرجع الرد الأول ولا يُنشئ شيئاً. وتحتفظ كسور بالمفتاح 30 يوماً. التفاصيل في [منع تكرار الطلبات](https://docs.kosoor.com.sa/ar/idempotency.md).
- **`referenceId`**: معرّفك الخاص للسجل، مثل رقم المستند في نظام ERP عندك. ولا يتكرر بين سجلين من النوع نفسه:

| المورد | `referenceId` لا يتكرر بين |
|---|---|
| العملاء | عملاء التاجر، ويُحدَّد مرة واحدة ولا يتغير |
| فواتير المبيعات | فواتير المبيعات والإشعارات الدائنة لدى التاجر معاً |
| المدفوعات | مدفوعات التاجر |
| الإشعارات الدائنة | فواتير المبيعات والإشعارات الدائنة لدى التاجر معاً |

فإذا توقف نظامك بعد إرسال فاتورة وضاع منه الـ `Idempotency-Key`، لن تُنشئ إعادة إرسالها بمفتاح جديد فاتورة ثانية، بل ترجع `409 reference_id_taken`. ويحمل `existingId` معرّف السجل الذي يستخدم المعرّف إذا كان من النوع نفسه ويملك مفتاحك صلاحية قراءته، وفي كل الأحوال تجده بـ `GET /v1/sales-invoices?referenceId=...`:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "reference_id_taken",
    "message": "قيمة referenceId مستخدمة لسجل آخر.",
    "param": "referenceId",
    "docUrl": "https://docs.kosoor.com.sa/ar/errors#reference_id_taken",
    "existingId": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f"
  }
}
```

ويمكنك أيضاً البحث عن المعرّف قبل الكتابة، فكل قائمة تقبل الفلتر `referenceId`.

## اربط الكتالوج مرة واحدة

تُربط فروع نظامك وأصنافه وطرق الدفع فيه بمعرّفات كسور من `GET /v1/branches` و `GET /v1/items` و `GET /v1/payment-methods`. وتحتفظ بيئة الاختبار بالمعرّفات الفعلية للكتالوج الذي نسخته، فالربط الذي تبنيه في بيئة الاختبار يصلح على البيانات الفعلية. ويُستثنى العملاء، فلبيئة الاختبار عملاؤها الخاصون، فاربطهم من جديد على البيانات الفعلية بـ `referenceId` أو رقم الجوال أو الرقم الضريبي.

المصدر: https://docs.kosoor.com.sa/ar/erp-sync
