رموز الأخطاء
رموز حالة HTTP في Listings API، ورموز الأخطاء SYxxxxx لكل من Listings وSocial، وأشكال استجابات الأخطاء الثلاثة التي تُرجعها واجهة API بالإصدار v4.
تستخدم Listings API رموز حالة HTTP المعتادة للإبلاغ عن نتيجة الطلب. تبدأ رموز الأخطاء بالبادئة SY وتُضمَّن في السلسلة النصية message للخطأ، بالتنسيق SYxxxxx: <human-readable reason>.
رموز حالة HTTP
HTTP status code summary
ثلاثة أشكال للاستجابة
تتضمن معظم حالات الفشل مصفوفة errors، إما في المستوى الأعلى أو متداخلة داخل نتيجة العملية، كما توضح الأقسام أدناه. تُرجع بعض حالات الفشل كائن error واحدًا بدلًا من ذلك: تقييد المعدل (429) وبعض حالات الفشل على مستوى الطلب (400/500 مع code مثل INTERNAL_SERVER_ERROR). تحقّق من الحالتين: errors مصفوفة، وerror كائن.
1. على مستوى الطلب: errors[] في المستوى الأعلى
توقف حالات فشل المصادقة والتفويض والطلبات غير السليمة المعالجة قبل تنفيذ العملية. وتُرجع حالة 4xx المطابقة (أعلاه) مع الخطأ في المستوى الأعلى من الاستجابة.
{ "data": { "createLocation": null }, "errors": [{ "message": "SY90005: Invalid Token" }]}2. التحقق من صحة عمليات الكتابة: data.<operation>.errors[] متداخل
يُرجع طلب الإنشاء أو التحديث أو النشر الحالة HTTP 200 ما دام سليم البنية. إذا خالفت المدخلات قاعدة عمل، يُبلَّغ عن الفشل بشكل متداخل ضمن الحمولة الخاصة بالعملية في data.<operation>.errors. عند النجاح، تكون هذه المصفوفة موجودة وفارغة ("errors": []).
{ "data": { "createLocation": { "errors": [ { "message": "SY10126: City is Mandatory" }, { "message": "SY10010: state_iso" } ], "location": null } }}3. على مستوى البوابة: كائن error واحد في المستوى الأعلى
يؤدي تقييد المعدل وأعطال البوابة غير المتوقعة إلى إيقاف المعالجة قبل الترجمة وإرجاع كائن error واحد يحتوي على code وmessage وcorrelation_id. راجع rate_limited أدناه للاطلاع على جسم استجابة 429.
اقرأ data.<operation>.errors دائمًا عند إجراء عملية كتابة، حتى مع الحالة 200 وكائن data.<operation> يحتوي على بيانات: فقد تفشل عملية الكتابة جزئيًا وتُبلّغ عن ذلك هنا.
لا تحتوي استجابة 402 Payment Required على غلاف error: تكون code وmessage وdoc_url في المستوى الأعلى، وكذلك pay_url عند وجود فاتورة مستحقة الدفع. راجع payment_required أدناه.
إعادة محاولة الكتابة ليست بلا تبعات
لا تدعم واجهة API بالإصدار v4 الترويسة Idempotency-Key: إذ يجري تجاهلها، ولا تكتشف أي نقطة نهاية عمليات الكتابة المتكررة. إذا انتهت مهلة استدعاء إنشاء أو تحديث أو نشر، أو أرجع الحالة 5xx، فقد يكون الخادم قد حفظ التغيير رغم ذلك، لذا قد تؤدي إعادة المحاولة دون تحقق إلى إنشاء موقع أو منشور أو رد على تقييم مكرر.
أعد محاولة عمليات القراءة بحرية مع زيادة مدة الانتظار بين المحاولات. أما لعملية الكتابة، فاقرأ البيانات للتحقق أولًا: ابحث عن السجل باستخدام مفتاح تتحكم فيه (storeId، أو رمز متجر، أو قائمة ردود التفاعل)، ولا تكرر الاستدعاء إلا إذا كان السجل غير موجود بالفعل.
الرموز الشائعة
Common SY error codes
تقابل رموز التحقق من الصحة ضمن النطاق SY10xxx حقلًا محددًا من حقول المدخلات؛ ويحدد message اسم الحقل أو القاعدة التي لم تُستوفَ. أما رموز المصادقة والتخويل ضمن النطاق SY90xxx فتخص الطلب بأكمله وتَرِد في المستوى الأعلى مع الحالة المطابقة.
رموز الحسابات المتصلة
تصدر الرموز ضمن النطاق SY810xx عن نقاط نهاية الحسابات المتصلة التي تستورد إدراج نشاط تجاري على منصة نشر أو تربطه. وتَرِد متداخلة في جسم الاستجابة عند إرجاع HTTP 200 (بنية الاستجابة 2 أعلاه)، لذا اقرأ data.<operation>.errors حتى عندما تشير الحالة إلى النجاح.
SY810xx connected-account and import codes
رموز Social
تأتي الرموز ضمن النطاق SY950xx من نقاط نهاية Social: العلامات التجارية والاتصالات ومنشورات التواصل الاجتماعي. وكما هو الحال مع رموز الحسابات المتصلة، تَرِد هذه الرموز متداخلة في جسم الاستجابة عند HTTP 200، لذا اقرأ data.<operation>.error (وdata.<operation>.errors في مسارات العمليات المجمّعة) حتى عندما تشير الحالة إلى النجاح.
SY950xx Social codes
يشير SY95042 وSY95044 إلى عدم استيفاء استحقاقات الخطة، وليس إلى أخطاء في المدخلات: ستفشل إعادة المحاولة بالطريقة نفسها إذا لم تُغيَّر الخطة. أما SY95045 وSY95046 وSY95049 وSY95052 فهي أخطاء في المدخلات يمكن تصحيحها في الطلب التالي.
رموز استحقاقات Listings
Listings plan codes
rate_limited
429 Too Many Requests: تجاوز الحساب حد معدل الطلبات المسموح به في خطته. جسم الاستجابة هو استجابة الخطأ القياسية، ويحمل تلميحًا في retry_after_seconds، وقيمة correlation_id لتضمينها في طلبات الدعم، وقيمة doc_url تربط بهذا القسم:
{ "error": { "code": "RATE_LIMITED", "message": "Too many requests. Slow down.", "retry_after_seconds": 30, "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#rate_limited" }}انتظر المدة المحددة في retry_after_seconds (أو في ترويسة Retry-After إن وُجدت)، ثم أعد المحاولة مع زيادة مدة الانتظار أُسّيًا بين المحاولات. راجع حدود معدل الطلبات للاطلاع على الحدود الخاصة بكل خطة وتنفيذ مرجعي لآلية زيادة مدة الانتظار بين المحاولات.
payment_required
402: لم تنجح الدفعة الأخيرة لهذا الحساب، لذا أُوقفت جميع نقاط نهاية /api/v4 مؤقتًا. يتضمن جسم الاستجابة pay_url، وهي صفحة Stripe الخاصة بالفاتورة غير المدفوعة، عند توفرها، وتحمل ترويسة الاستجابة X-Error-Code قيمة code نفسها. لا يزال بإمكانك فتح صفحة الفوترة في لوحة التحكم للدفع.
{ "code": "payment_required", "message": "This account has an unpaid invoice, so API access is paused. Pay the invoice to restore access.", "pay_url": "https://invoice.stripe.com/i/acct_123/test_abc", "doc_url": "https://listingsapi.com/docs/error-codes#payment_required"}تُستعاد إمكانية الوصول خلال دقيقة من سداد آخر فاتورة مفتوحة. إذا ظلت الفاتورة غير مدفوعة بعد 3 أيام من أول محاولة دفع فاشلة، يُلغى اشتراك Listings وتُؤرشف مواقع الحساب. إذا كان لدى الحساب أيضًا اشتراك Social نشط، فإنه يحتفظ بإمكانية الوصول إلى Social؛ وإلا يُغلق الحساب وتتوقف مفاتيح API الخاصة به عن العمل.
social_payment_required
402: لم تنجح الدفعة الأخيرة لاشتراك Social، لذا أُوقفت نقاط نهاية Social (/api/v4/social/*) مؤقتًا. تستمر نقاط نهاية Listings في العمل. يحتوي جسم الاستجابة على الحقول نفسها الموجودة في payment_required، مع "code": "social_payment_required". إذا ظلت الفاتورة غير مدفوعة بعد 3 أيام من أول محاولة دفع فاشلة، يُلغى اشتراك Social وتُؤرشف العلامات التجارية الخاصة بالحساب. يُغلق الحساب الذي ليس لديه اشتراك Listings، وتتوقف مفاتيح API الخاصة به عن العمل.
أخطاء مستوى التحكم في بوابة المطورين
تُرجع نقاط نهاية إدارة الحساب والمفاتيح في بوابة المطورين (مسارات API الخاصة بلوحة التحكم نفسها) استجابة خطأ واحدة ذات بنية محددة، تختلف عن صيغ errors[] الخاصة بـ REST أعلاه. يحمل كل code قيمة correlation_id وقيمة doc_url تربط بالقسم المقابل هنا.
{ "error": { "code": "AUTH_INVALID_KEY", "message": "Session is invalid or expired.", "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#auth_invalid_key" }}auth_missing_key
401: لم تُقدَّم بيانات اعتماد. سجِّل الدخول مجددًا، أو أرسل مفتاحك بصيغة Authorization: API <your-key>.
auth_invalid_key
401: الجلسة أو المفتاح غير صالح أو منتهي الصلاحية. أعِد المصادقة أو أعِد إصدار مفتاح من لوحة التحكم.
auth_insufficient_scope
403: بيانات الاعتماد صالحة لكنها لا تمنح الإذن بتنفيذ هذا الإجراء. لا يمكن لمفتاح ذي نطاق صلاحيات للقراءة استدعاء نقاط نهاية الكتابة؛ أصدِر مفتاحًا للكتابة إذا كنت بحاجة إليه.
not_found
404: المورد المطلوب، أو مورد يُشار إليه بواسطة ID، غير موجود.
conflict
409: يتعارض الطلب مع الحالة الحالية للمورد (مثل إبطال مفتاح أُبطل بالفعل).
validation_failed
422: لم يجتز جسم الطلب التحقق من الصحة. يحدد الحقلان field وdetails في الاستجابة المُدخل الذي تسبب في فشل التحقق.
internal_error
500: خطأ غير متوقع من جانب الخادم. أعِد محاولة القراءة مع زيادة مدة الانتظار أُسّيًا بين المحاولات؛ أما في حالة الكتابة، فاقرأ السجل مجددًا أولًا (راجع إعادة محاولة الكتابة ليست بلا تبعات). أدرج قيمة correlation_id إذا تواصلت مع الدعم.
dependency_unavailable
503: إحدى الخدمات التي تعتمد عليها API غير متاحة مؤقتًا. أعِد المحاولة مع زيادة مدة الانتظار بين المحاولات.
للاطلاع على معلومات حول 429، راجع rate_limited أعلاه.
معالجة الأخطاء في الشيفرة
تحقّق من حالة HTTP أولًا؛ ثم، في عمليات الكتابة، افحص جسم الاستجابة بحثًا عن مصفوفة errors متداخلة:
from listingsapi import APIError, ListingsAPI client = ListingsAPI(api_key=os.environ["LISTINGSAPI_KEY"]) try: location = client.locations.create(input=payload)except APIError as e: # Raised for a non-2xx status (AuthenticationError, ValidationError, and # so on) and for an error payload returned inside a 200 body. raise RuntimeError(f"Listings API error: {e}") from eعند استخدام واجهة HTTP API مباشرةً، يُجرى الفحصان نفساهما صراحةً: رمز الحالة أولًا ثم حمولة الاستجابة:
resp = requests.post( "https://listingsapi.com/api/v4/locations", headers={"Authorization": f"API {os.environ['LISTINGSAPI_KEY']}"}, json=payload, timeout=30,)resp.raise_for_status()body = resp.json() op = (body.get("data") or {}).get("createLocation") or {}if op.get("errors"): messages = [e["message"] for e in op["errors"]] raise RuntimeError(f"Listings API error: {messages}")تتولى حزمة Python SDK كلا الفحصين نيابةً عنك: فهي تربط كل حالة HTTP باستثناء ذي نوع محدد، وترفع استثناءً أيضًا عند إرجاع حمولات خطأ داخل جسم استجابة 200.