# أكواد الأخطاء

> كل أكواد الأخطاء التي يرجعها Merchant API، مع الـ HTTP Status ومعنى كل كود، وشكل الخطأ الموحّد.

جميع الأخطاء ترجع بالشكل نفسه. اعتمد على `code` في الكود عندك، أما `message` فهي نص موجّه للمستخدم وتتغيّر لغتها حسب الـ Header `Accept-Language`.

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "phone_taken",
    "message": "رقم الجوال مسجّل لعميل آخر.",
    "param": "phone",
    "docUrl": "https://docs.kosoor.com.sa/ar/errors#phone_taken",
    "existingId": "0f8fad5b-d9cb-469f-a165-70867728950e"
  }
}
```

| الحقل | الوصف |
|---|---|
| `type` | تصنيف الخطأ، وهو أحد العناوين في هذه الصفحة. |
| `code` | كود الخطأ، ولا يتغيّر بين الإصدارات. |
| `message` | وصف الخطأ بلغة الطلب. |
| `param` | الحقل أو الـ Query Parameter أو الـ Header الذي سبّب الخطأ، بمسار مثل `company.vatNumber`. قيمته `null` إذا لم يكن الخطأ متعلقاً بحقل معيّن. |
| `docUrl` | رابط شرح الكود في هذه الصفحة. |
| `errors` | في أخطاء 400: قائمة بكل مشاكل الطلب، بما فيها المشكلة الأولى. |
| `requiredPermission` | مع `missing_permission`: الصلاحية التي يحتاجها الطلب، مثل `customers:write`. |
| `existingId` | مع الأكواد التي تنتهي بـ `_taken`: الـ `id` للسجل الذي يستخدم القيمة نفسها، إذا كان من نوع المورد نفسه ويملك مفتاحك صلاحية قراءته. |
| `missing` | مع `customer_address_incomplete`: حقول العميل الناقصة لإصدار فاتورة ضريبية، مثل `address.street`. |
| `zatcaErrors` | مع `zatca_rejected`: رسائل الهيئة كما أرسلتها، ولكل رسالة `code` و `category` و `message`. |

## المصادقة

### `missing_api_key`

HTTP Status: **401**

لم يتم إرسال مفتاح API. أرسله في الـ Header بالشكل: Authorization: Bearer <key>.

### `invalid_api_key`

HTTP Status: **401**

مفتاح API غير صحيح.

### `revoked_api_key`

HTTP Status: **401**

تم إلغاء مفتاح API هذا.

### `expired_api_key`

HTTP Status: **401**

انتهت صلاحية مفتاح API هذا.

## الصلاحيات

### `tenant_suspended`

HTTP Status: **403**

حساب المنشأة موقوف.

### `missing_permission`

HTTP Status: **403**

مفتاح API لا يملك الصلاحية المطلوبة لهذا الطلب.

### `branch_not_allowed`

HTTP Status: **403**

مفتاح API غير مسموح له بالعمل على هذا الفرع.

## أخطاء في الطلب

### `invalid_json`

HTTP Status: **400**

الـ Body ليس JSON صحيحاً.

### `missing_parameter`

HTTP Status: **400**

أحد الحقول المطلوبة غير موجود.

### `invalid_parameter`

HTTP Status: **400**

قيمة أحد الحقول غير صحيحة.

### `unknown_parameter`

HTTP Status: **400**

الطلب يحتوي على حقل لا يقبله هذا الـ Endpoint.

### `too_many_errors`

HTTP Status: **400**

في الطلب أخطاء أخرى غير المذكورة هنا.

### `unsupported_media_type`

HTTP Status: **415**

أرسل الـ Body بصيغة application/json.

### `body_too_large`

HTTP Status: **413**

حجم الـ Body أكبر من الحد المسموح.

### `route_not_found`

HTTP Status: **404**

لا يوجد Endpoint بهذا الرابط.

### `method_not_allowed`

HTTP Status: **405**

هذا الـ Endpoint لا يقبل الـ HTTP Method المستخدم.

### `resource_not_found`

HTTP Status: **404**

السجل المطلوب في الرابط غير موجود.

### `reference_id_taken`

HTTP Status: **409**

قيمة referenceId مستخدمة لسجل آخر.

### `invoice_not_cleared`

HTTP Status: **409**

لم تقبل هيئة الزكاة والضريبة والجمارك هذه الفاتورة. راجع قيمة zatca.status.

### `invoice_busy`

HTTP Status: **409**

هناك طلب آخر يعدّل هذه الفاتورة الآن. أعد المحاولة بعد ثوانٍ.

### `invalid_vat_number`

HTTP Status: **400**

الرقم الضريبي يتكون من 15 رقماً، يبدأ بـ 3 وينتهي بـ 3.

### `vat_number_taken`

HTTP Status: **409**

الرقم الضريبي مسجّل لعميل آخر.

### `phone_taken`

HTTP Status: **409**

رقم الجوال مسجّل لعميل آخر.

## قواعد العمل

### `referenced_resource_not_found`

HTTP Status: **422**

الطلب يشير إلى سجل غير موجود.

### `invoice_not_issued`

HTTP Status: **422**

لم يتم إصدار الفاتورة.

### `on_account_not_allowed`

HTTP Status: **422**

العميل الفرد لا يشتري بالآجل.

### `credit_limit_exceeded`

HTTP Status: **422**

تجاوز الحد الائتماني.

### `customer_inactive`

HTTP Status: **422**

العميل غير نشط.

### `customer_address_incomplete`

HTTP Status: **422**

الفاتورة الضريبية تحتاج عنوان العميل (الشركة) كاملاً مع الرقم الضريبي أو رقم الهوية. الحقول الناقصة موضحة في missing.

### `item_not_sellable`

HTTP Status: **422**

لا يمكن بيع هذا المنتج في فاتورة مبيعات.

### `branch_not_onboarded`

HTTP Status: **422**

هذا الفرع غير مربوط بهيئة الزكاة والضريبة والجمارك، فلا يمكنه إصدار فاتورة ضريبية.

### `zatca_rejected`

HTTP Status: **422**

رفضت هيئة الزكاة والضريبة والجمارك الفاتورة، ولم يُحفظ أي شيء. رسائل الهيئة موضحة في zatcaErrors.

### `allocation_exceeds_due`

HTTP Status: **422**

المبلغ المخصص أكبر من المتبقي على هذه الفاتورة.

### `invoice_not_payable`

HTTP Status: **422**

لا يمكن سداد هذه الفاتورة، لأنها غير موجودة، أو لعميل آخر، أو في فرع لا يملك المفتاح صلاحية عليه، أو غير صادرة، أو ليست فاتورة مبيعات.

### `period_locked`

HTTP Status: **422**

هذا التاريخ في فترة محاسبية مقفلة.

### `payment_method_not_in_branch`

HTTP Status: **422**

خزينة طريقة الدفع هذه تخدم فرعاً آخر، فلا يمكن تسجيل الدفعة في الفرع المحدد.

### `payment_not_recorded`

HTTP Status: **422**

لم يتم تسجيل الدفعة.

### `webhook_endpoint_limit`

HTTP Status: **422**

وصل هذا المفتاح إلى الحد الأقصى لعدد الـ Webhook Endpoints، احذف واحداً لا تستخدمه أولاً.

### `credit_exceeds_invoice`

HTTP Status: **422**

مبلغ الإشعار أكبر من المتبقي القابل للإشعار على الفاتورة.

### `invoice_not_creditable`

HTTP Status: **422**

لا يمكن إصدار إشعار دائن لهذه الفاتورة، لأنها ليست فاتورة مبيعات صادرة، أو مستوردة، أو رفضتها الهيئة.

### `used_subscription_not_refundable`

HTTP Status: **422**

هذا الاشتراك استُخدمت منه زيارات، فلا يمكن إصدار إشعار دائن له عن طريق الـ API.

### `refund_exceeds_collected`

HTTP Status: **422**

مبلغ الاسترجاع أكبر مما حُصّل على الفاتورة.

### `refund_method_not_supported`

HTTP Status: **422**

دُفعت هذه الفاتورة ببطاقة عبر المتجر الإلكتروني، ولا يمكن بدء استرجاع إلى البطاقة عن طريق الـ API.

### `loyalty_refund_blocked`

HTTP Status: **422**

تعذّر إصدار هذا الإشعار بسبب منصة الولاء: إما أن النقاط أو الأختام المكتسبة من هذه الفاتورة استُخدمت، أو تعذّر الوصول إلى المنصة، أو لم تصلها الفاتورة بعد.

### `credit_note_not_issued`

HTTP Status: **422**

لم يتم إصدار الإشعار الدائن.

## منع تكرار الطلبات

### `missing_idempotency_key`

HTTP Status: **400**

أرسل الـ Header Idempotency-Key مع هذا الطلب.

### `invalid_idempotency_key`

HTTP Status: **400**

قيمة الـ Header Idempotency-Key غير صحيحة.

### `idempotency_key_reused`

HTTP Status: **422**

قيمة Idempotency-Key هذه استُخدمت من قبل مع طلب مختلف.

### `idempotency_in_progress`

HTTP Status: **409**

يوجد طلب بنفس قيمة Idempotency-Key لم ينتهِ تنفيذه بعد.

## تجاوز حد الطلبات

### `rate_limited`

HTTP Status: **429**

تجاوزت الحد المسموح من الطلبات. أعد المحاولة بعد المدة الموضحة في Retry-After.

## أخطاء السيرفر

### `internal_error`

HTTP Status: **500**

حدث خطأ من جهتنا. أعد المحاولة، وإذا تكرر الخطأ أرسل لنا قيمة Request-Id.

### `sandbox_unavailable`

HTTP Status: **503**

بيئة الاختبار قيد التجهيز. أعد المحاولة بعد قليل.

### `sandbox_failed`

HTTP Status: **503**

تعذّر تجهيز بيئة الاختبار، ولن تنجح إعادة المحاولة حتى يُعيد التاجر تعيينها من صفحة المطوّرين في لوحة التحكم.

المصدر: https://docs.kosoor.com.sa/ar/errors
