ما البنية التي ينبغي أن تستخدمها استجابة API
الخلاصة: الكائنات المجردة نظيفة حتى تحتاج إلى بيانات وصفية؛ الأغلفة الكاملة آمنة لكنها مطوّلة. لمعظم المشاريع استخدم حالة HTTP للنتائج وغلافًا ثابتًا للبيانات.

الخلاصة: عبّر عن النتائج برموز الحالة 4xx/5xx، واحمل الحمولة في { "data": ..., "meta": ... }، وانتقل إلى غلاف error عند الفشل؛ وهذا يكفي لواجهات API الداخلية، ولا تحتاج إلى JSON:API أو OpenAPI إلا المنصات العامة بكثير من المدمجين.
استبعد أسوأ خيار أولًا: إرجاع 200 دائمًا مع النتيجة في حقل code.
ثلاثة أشكال
أ. كائن مجرد
{ "id": 1, "name": "demo", "price": 99 }
نظيف، ودلالات HTTP تؤدي العمل (404 هي 404). لكن لحظة احتياجك إلى ترقيم أو تحذيرات أو معرّف تتبع، لا يوجد مكان لوضعها دون تغيير العقد.
ب. غلاف ثابت
{
"data": { "id": 1, "name": "demo" },
"meta": { "requestId": "abc", "took": 12 }
}
تفترق الحمولة والبيانات الوصفية، فلا تعيد بيانات وصفية جديدة تشكيل data. التكلفة مستوى تداخل واحد.
ج. كل شيء غلاف (تجنبه)
{ "code": 0, "message": "success", "data": {...} }
الشكل ليس الخطيئة؛ الممارسة هي. حالة 200 لكل نتيجة تعني أن شبكات CDN والبوابات وقواطع الدوائر وسياسات إعادة المحاولة ولوحات المعلومات كلها ترى نجاحًا. وعندها يحتاج كل تنبيه إلى تحليل مخصص.
التوصية
حالة HTTP للنتيجة، وغلاف للحمولة.
{
"data": { "id": 1, "name": "demo" },
"meta": { "requestId": "req_8f2a", "took": 12 }
}
{
"error": {
"code": "ORDER_NOT_FOUND",
"message": "Order does not exist or was deleted",
"details": [{ "field": "id", "issue": "not_found" }]
},
"meta": { "requestId": "req_8f2a" }
}
حالة 4xx أو 5xx؛ وcode ثابت وقابل للقراءة آليًا؛ وmessage للبشر؛ وdetails لأخطاء النموذج على مستوى الحقل.
قواعد صارمة
- نقاط نهاية القوائم يجب أن تحمل بيانات وصفية للترقيم. بلا
totalأو مؤشر لا يوجد ملقم صفحات. - القوائم الفارغة تعيد
[]، لاnullأبدًا.null.mapانقطاع متكرر. - الطوابع الزمنية بـISO 8601 مع إزاحة. انظر أي تنسيق للطوابع الزمنية.
- اصطلاح تسمية واحد.
snake_caseأوcamelCase، يُحوَّل مرة واحدة عند الحدود. - المال كوحدات صغرى صحيحة أو سلاسل.
99.99ليس دقيقًا في الفاصلة العائمة الثنائية. - لا تخلط
nullبالغياب. انظرnullأم حذف الحقل.
متى تتبنى مواصفة
- منصات عامة بكثير من المدمجين: JSON:API أو OpenAPI مع غلاف مشترك
- واجهات API داخلية لفريق واحد: الغلاف أعلاه كافٍ
- عقود قوية: Schema أولًا والبنى مولدة منه
المواصفات توفر النقاش وتكلفة التأهيل. أما لفريق من خمسة أشخاص، فـJSON:API عادةً عمل سلبي.
الأسئلة الشائعة
كيف أختار بين الكائن المجرد والغلاف؟
استخدم غلافًا عندما تحتاج إلى ترقيم أو تحذيرات أو requestId، ليتمكن meta من النمو دون إعادة تشكيل data. ولا ترجع الكائن المجرد إلا عندما لا تحتاج بيانات وصفية وتقبل أن إضافة حقول لاحقًا تغيّر العقد.
لماذا يجب ألا ترجع API حالة 200 لكل نتيجة؟
تقرأ شبكات CDN والبوابات وقواطع الدوائر وسياسات إعادة المحاولة ولوحات المعلومات حالة HTTP لتقرر هل تخزّن أو تعيد المحاولة أو تنبّه. ومع 200 في كل مكان تعامل الفشل كنجاح، ويحتاج كل تنبيه إلى تحليل مخصص لرمز الأعمال.
هل يجب أن تحمل نقاط نهاية القوائم بيانات وصفية للترقيم؟
نعم. بلا total أو مؤشر لا يوجد ملقم صفحات، والقوائم الفارغة يجب أن تعيد [] لا null، وإلا انكسر استدعاء .map في الواجهة.