# Makhzan Connect API v1

واجهة تكامل للمشتركين للوصول إلى بيانات مؤسستهم فقط. لا تستخدم مفتاح Supabase ولا ترسل `organization_id`؛ المؤسسة تُشتق من مفتاح Makhzan نفسه.

## المصادقة

```http
Authorization: Bearer mkz_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
X-Request-Id: 7456d05d-00ee-4c56-a629-aab0a0604128
```

يمكن إرسال المفتاح في `X-Makhzan-Key` بدل Authorization. مفاتيح `mkz_test_` مخصصة للاختبار ومفاتيح `mkz_live_` للتشغيل.

## الموارد

- `GET/POST /v1/products`
- `GET/POST /v1/customers`
- `GET /v1/suppliers`
- `GET /v1/warehouses`
- `GET /v1/inventory`
- `GET/POST /v1/sales-invoices`
- `GET/POST /v1/purchase-orders`
- `GET/POST /v1/payments`
- `GET /v1/accounting/journal-entries`
- `GET /v1/reports/trial-balance`
- `GET /v1/commands/{id}`

القوائم تقبل `limit` من 1 إلى 100 و`offset`، وبعضها يقبل `updated_since` بصيغة ISO-8601.

## أوامر الكتابة المالية

فواتير البيع وأوامر الشراء والمدفوعات تعيد `202 Accepted` لأن النظام يمررها عبر التحقق والموافقة والترحيل بدل تعديل دفاتر الأستاذ مباشرة. يجب إرسال مفتاح منع تكرار:

```http
X-Idempotency-Key: order-shop-10482-v1
```

إعادة الطلب بالمفتاح نفسه تعيد الأمر السابق ولا تنشئ حركة ثانية. تابع النتيجة عبر `status_url`.

يبدأ الأمر بحالة `accepted`، ثم ينتقل إلى `processing` وأخيرًا إلى `completed` أو `rejected`. النتيجة المكتملة قد تحمل `pending_approval` لأمر شراء؛ وهذا يعني أن عرض الشراء دخل صندوق الموافقات ولم يُنشأ أمر شراء نهائي بعد.

### فاتورة مبيعات

```json
{
  "customer_key": "CUST-1001",
  "customer_name": "شركة العميل",
  "invoice_date": "2026-08-20",
  "currency": "JOD",
  "lines": [
    {"description":"صنف تجريبي","item_key":"SKU-1","quantity":2,"unit_price":10,"discount":0,"tax_rate":16}
  ]
}
```

تمر الفاتورة عبر حدود الائتمان، العملة الأساسية، الفترة المحاسبية، الحسابات النظامية، واتزان القيد.

### أمر شراء

```json
{
  "request_id": "00000000-0000-4000-8000-000000000001",
  "supplier_id": "00000000-0000-4000-8000-000000000002",
  "payment_type": "credit",
  "branch_id": "00000000-0000-4000-8000-000000000003",
  "cost_center_id": "00000000-0000-4000-8000-000000000004",
  "budget_account_id": "00000000-0000-4000-8000-000000000005",
  "lines": [{"item_key":"SKU-1","item_name":"صنف","quantity":5,"unit_cost":8,"tax_rate":0.16}]
}
```

يجب أن يشير `request_id` إلى طلب شراء معتمد، ثم تُطبق قواعد الموازنة والموافقات متعددة المراحل.

### دفعة عميل أو مورد

أرسل `payment_kind=customer_receipt` لسند قبض العميل، أو `payment_kind=supplier_payment` لسداد المورد. عند حذف `vendor_bill_id` من سداد المورد، يوزع النظام المبلغ FIFO على أقدم الفواتير المفتوحة.

## Rate limits

كل Client له حد في الدقيقة وحصة يومية. عند التجاوز يعاد `429` مع `Retry-After`. تعرض الاستجابة أيضًا:

- `X-RateLimit-Remaining-Minute`
- `X-RateLimit-Remaining-Day`

## Webhooks

يُرسل النظام:

```http
X-Makhzan-Event: product.upserted
X-Makhzan-Delivery: <event uuid>
X-Makhzan-Timestamp: <unix seconds>
X-Makhzan-Signature: v1=<hex hmac sha256>
```

احسب HMAC-SHA256 على النص `timestamp.raw_body` باستخدام `whsec_...` وقارن النتيجة مقارنة ثابتة الزمن. ارفض الطلب إذا تجاوز timestamp خمس دقائق، واحفظ Delivery ID لمنع معالجة الحدث مرتين.

تُعاد المحاولة بتأخير أُسّي حتى ست محاولات، ثم ينتقل التسليم إلى `dead_letter` ويمكن للمدير إعادة إرساله من البوابة.

## الأخطاء

```json
{
  "error": {
    "code": "API_SCOPE_REQUIRED",
    "details": { "required": "inventory:read" },
    "request_id": "7456d05d-00ee-4c56-a629-aab0a0604128"
  }
}
```

احتفظ بـ`request_id` عند التواصل مع الدعم. لا تسجل المفتاح أو محتوى Authorization في السجلات.

## الملفات

- مواصفة OpenAPI: `makhzan-connect-openapi.yaml`
- Postman: `Makhzan-Connect-API-v1.postman_collection.json`
