إعلانات عقارية وبيانات سوق في السعودية، مجمّعة من أكثر من 13 مصدرًا، مع إزالة التكرار وتصفية الجودة. وهي البيانات نفسها التي يعتمد عليها darak.app.
البدء السريع
- احصل على مفتاح API (
dk_live_…) من حسابك في دارك. - نفّذ طلبًا:
curl "https://api.darak.app/v1/listings?city=riyadh&listing_type=rent&limit=5" \
-H "Authorization: Bearer $DARAK_API_KEY"
أو استخدم حزمة SDK رسمية تضيف الأنواع وتصفح الصفحات وإعادة المحاولة. تغطي الحزمتان كل نقاط النهاية هنا، وتُولّدان من هذه المواصفة.
// npm install @darak-app/sdk
import { Darak } from "@darak-app/sdk";
const darak = new Darak(); // reads DARAK_API_KEY
const page = await darak.listings.search({ city: "riyadh", listing_type: "rent", limit: 5 });
# pip install darak
from darak import Darak
darak = Darak() # reads DARAK_API_KEY
page = darak.listings.search(city="riyadh", listing_type="rent", limit=5)
- استخدم
GET /citiesوGET /cities/{city}/neighborhoodsلمعرفة أسماء المدن المختصرة ومعرّفات الأحياء المقبولة في المرشّحات، وGET /enumsلمعرفة القيم المسموح بها.
كل الاستجابات بصيغة JSON. تعود الكائنات المفردة بالشكل { "data": { … } }، والقوائم بالشكل { "data": [ … ], "pagination": { … } }.
أين تجد الموارد. وثيقة OpenAPI متاحة في /v1/openapi.json دون مفتاح. تُولّد منها الحزمتان، ويمكنك توليد عميلك الخاص أيضًا. تتوفر @darak-app/sdk على npm وdarak على PyPI. تُعلن التغييرات في سجل التغييرات، وله موجز RSS، وتظهر حالة الخدمة في صفحة الحالة. إذا حدث خطأ، ابحث عن الطلب باستخدام GET /organization/request-logs?request_id=… لمعرفة الحالة والخطأ والمعامل المسبب له، أو راسل [email protected] مع ذكر request_id.
المصادقة
أرسل مفتاحك في ترويسة Authorization مع كل طلب:
Authorization: Bearer dk_live_…
- المفاتيح سرية. استدعِ API من خوادمك فقط، لا من المتصفحات أو تطبيقات الجوال أو المستودعات العامة.
- يُرفض المفتاح المرسل في الرابط (
?api_key=) بالرمزapi_key_in_query. دوّر أي مفتاح سبق وضعه في رابط. - يمكن للحساب الاحتفاظ بعدة مفاتيح ضمن مشاريع. يمكن تقييد المفتاح ببعض واجهات API وتحديد تاريخ انتهاء له؛ تفشل الطلبات خارج صلاحياته بالرمز
scope_not_in_key، ويحصل المفتاح المنتهي علىexpired_api_key. - لتدوير مفتاح، استخدم تدوير في لوحة التحكم: تحصل على مفتاح جديد بالإعدادات نفسها، ويستمر القديم خلال مهلة السماح التي تختارها حتى تنشر التحديث دون توقف. يسري الإلغاء فورًا.
حفظ المفتاح. احفظه في متغير بيئة أو مدير أسرار، لا في نظام التحكم بالمصدر. تبدأ المفاتيح بالبادئة الثابتة dk_live_ أو dk_admin_ لتسهيل اكتشافها بأدوات فحص الأسرار. إذا وصل مفتاح إلى مستودع عام، دوّره فورًا وألغِ القديم بعد اكتمال النشر.
نوعان من المفاتيح. يقرأ مفتاح البيانات (dk_live_…) الإعلانات وبيانات السوق والتحليلات والمشاريع العقارية. ينشئ مالك المؤسسة مفتاح الإدارة (dk_admin_…) لإدارة المؤسسة نفسها: المفاتيح والمشاريع والأعضاء والاستخدام وأحداث التدقيق. وهو النوع الوحيد المقبول في نقاط نهاية /v1/organization. لا تتداخل صلاحيات النوعين: يحصل مفتاح البيانات في نقطة إدارة على admin_key_required، ومفتاح الإدارة في غيرها على admin_key_not_allowed. لا تُحتسب وحدات لطلبات الإدارة.
مفاتيح الاختبار. يقرأ مفتاح dk_test_… البيانات الحية نفسها، بحصة ثابتة قدرها 1,000 وحدة شهريًا و30 وحدة في الدقيقة و25 نتيجة في الصفحة وعمق 250 نتيجة. يُقاس استخدامه منفصلًا، فلا يستهلك مفتاح اختبار يعمل في CI حصة تكامل الإنتاج، ولا تنشأ عنه فاتورة؛ الاستخدام الإضافي معطّل مهما سمحت الخطة. يصل إلى واجهات API نفسها التي تشملها خطتك، فتختبر ما ستستخدمه في الإنتاج. أنشئه من صفحة مفاتيح API؛ يمكن للمؤسسة الاحتفاظ بثلاثة مفاتيح اختبار، منفصلة عن حد المفاتيح الحية.
OAuth لخادم MCP، لا للطلبات المباشرة. يربط المستخدمون مساعدي الذكاء الاصطناعي عبر Darak MCP بتسجيل الدخول باستخدام OAuth. يستبدل خادم MCP رمزهم ببيانات اعتماد API قصيرة الأجل مرتبطة بالمؤسسة المختارة عند الموافقة، فتُحتسب الطلبات على خطتها وتظهر في سجلاتها. لا يقبل API رموز عملاء MCP مباشرة؛ استخدم مفتاحًا للخادم أو النص البرمجي أو المهمة المجدولة.
ما هو الإعلان العقاري؟
- الأسعار.
price.yearly_sarهو الرقم القابل للمقارنة: تُحوّل الإيجارات المنشورة شهريًا أو أسبوعيًا أو يوميًا إلى مبلغ سنوي، أما البيع فسعره الإجمالي. يحتفظprice.as_postedبمبلغ المعلن الأصلي وفترته. - إعلان واحد لكل عقار. عندما يُنشر العقار نفسه في عدة مصادر، يحتفظ دارك بإعلان واحد ويسرد البقية في
also_listed_on. - تصفية الجودة. يستبعد البحث والعدّ الأسعار والمساحات غير المعقولة بالتصفية نفسها المستخدمة في darak.app. يتجاوز
GET /listings/{id}و/listings/batchهذه التصفية، فيعيدان إعلانات لا تظهر في البحث. - الصور شرط للإتاحة. لا يتاح إعلان حتى ينسخ دارك صوره إلى شبكة CDN الخاصة به. يظهر الإعلان الجديد متأخرًا قليلًا، ولا يظهر ما لا يحصل على صور. تُستثنى الأراضي لأن نشرها دون صور شائع. ينطبق ذلك أيضًا على التفاصيل والجلب الدفعي: تعيد الشقة بلا صور
404ويظهر معرّفها فيmissing_ids. - الحداثة.
first_seen_atهو وقت رصد دارك للإعلان أول مرة.updated_atآخر تحديث في المصدر، أو آخر رصد لدى دارك إذا لم ينشر المصدر وقت التحديث.last_seen_atآخر تأكيد بأن الإعلان لا يزال نشطًا. - أسعار العرض. أسعار الإعلانات هي المطلوبة، لا أسعار الصفقات. تأتي البيانات من مصادر خارجية وقد تكون ناقصة أو قديمة.
- نسب المصدر. عند عرض الإعلانات لمستخدميك، انسب البيانات إلى دارك واربط
urlوانسب الإعلان لمصدره بالاسم (source.name). في الخطط المدفوعة يكونsource.urlرابطًا في darak.app يحوّل إلى الإعلان الأصلي؛ في الخطة المجانية يكون هو وsource.listing_idبالقيمة null.
الحدود والحصص
يكلف كل طلب وحدات تظهر في X-Request-Units، وفي x-units لكل نقطة نهاية في المرجع:
- نقاط القوائم، كبحث الإعلانات وقوائم المشاريع: وحدة لكل 10 نتائج مطلوبة بـ
limit، حتى حجم صفحة خطتك. صفحة 100 نتيجة تكلف 10. - الجلب الدفعي للإعلانات: وحدة لكل 10 معرّفات.
- الموارد المفردة والبيانات المرجعية وبيانات السوق: وحدة واحدة.
- التحليلات: 10 لوضع السوق ونطاق السعر، أو 15 للمقارنات والعائد الإيجاري ومقارنة الأحياء والاتجاهات، أو وحدتان لكل 10 نتائج للفرص.
تحدد خطتك:
- حد المعدل: وحدات في الدقيقة. الترويسات:
RateLimit-LimitوRateLimit-RemainingوRateLimit-Resetبالثواني. - الحصة الشهرية: وحدات في الشهر التقويمي بتوقيت UTC. الترويسات:
X-Quota-LimitوX-Quota-RemainingوX-Quota-Reset. - حجم الصفحة: أكبر
limitيمكنك طلبه. - عمق التصفح: عدد النتائج الممكن تصفحها في استعلام واحد. بعده تحصل على
result_window_exceeded؛ ضيّق الاستعلام أو زامن بـupdated_since.
| الخطة | وحدات / دقيقة | وحدات / شهر | حجم الصفحة | عمق التصفح | المفاتيح النشطة |
|---|---|---|---|---|---|
| Free | 30 | 250 | 25 | 500 | 5 |
| Starter | 60 | 50,000 | 50 | 5,000 | 25 |
| Growth | 150 | 200,000 | 100 | 5,000 | 25 |
| Pro | 300 | 750,000 | 100 | 20,000 | 25 |
تحدد خطط Enterprise هذه الحدود حسب الاتفاق. تجد حدودك في صفحة الخطة بلوحة التحكم، ويعيدها GET /limits للمفتاح الذي يطلبها دون وحدات. اقرأها عند بدء التشغيل بدل تثبيت حجم صفحة في الكود، ليعمل الكود نفسه مع كل خطة.
الاستخدام الإضافي. في أي اشتراك مدفوع، Starter أو Growth أو Pro، تستمر الطلبات بعد الحصة الشهرية وتُفوتر لكل 1,000 وحدة في نهاية دورة الفوترة حتى سقف الإنفاق الشهري الذي يحدده المالك في صفحة الفوترة. عند السقف تحصل على 429 spend_cap_reached حتى تجدد الحصة. مع سقف 0 تصبح الحصة حدًا صارمًا (429 monthly_quota_exceeded).
عند تجاوز حد تحصل على 429 وترويسة Retry-After. انتظر عدد الثواني المحدد ثم أعد المحاولة. لا تُحتسب الطلبات الفاشلة، 4xx و5xx و429، على حصتك الشهرية.
تصفح الصفحات
تعيد نقاط القوائم صفحة ومعها:
"pagination": { "limit": 25, "next_cursor": "eyJvIjoy….pkFEfJUOpRbZ…", "has_more": true, "result_window_reached": false }
- للحصول على التالية، كرر الطلب بـ
cursor=<next_cursor>والمعاملات نفسها. يُرفض المؤشر مع مرشّحات أو ترتيب مختلف. - تعامل مع المؤشر كسلسلة غير قابلة للتفسير، وأعده كما استلمته. المؤشرات موقّعة؛ يُرفض المعدّل أو المصنوع يدويًا بالرمز
invalid_cursor، وقد يتغير محتواها مع آلية التصفح. - تعني
result_window_reached: trueوجود نتائج إضافية مع بلوغ عمق خطتك. ضيّق الاستعلام بالحي أو السعر أو نوع العقار بدل التصفح أعمق. - لا يعيد بحث الإعلانات الإجمالي. استخدم
GET /listings/countبالمرشّحات نفسها.
تحمل المؤشرات إزاحة؛ مع sort=newest أو ترتيب سعري قد ينقل إعلان أُضيف أو حُذف بين صفحتين صفوفًا عبر الحد، فتتكرر أو تُفقد. هذا من طبيعة تصفح جدول حي، ولذلك تستخدم المزامنة sort=updated_asc؛ راجع مزامنة نسخة محلية.
إعادة المحاولة بأمان
يمكن تكرار GET بحرية. مع POST أرسل ترويسة Idempotency-Key، بسلسلة فريدة حتى 255 حرفًا، ويفضل UUID، ولن تُنفّذ العملية أكثر من مرة مهما كررت الطلب:
Idempotency-Key: 8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa
- كرر بـالمفتاح نفسه والجسم نفسه لتحصل على استجابة الطلب الأول مع
Idempotent-Replay: true. لا يُنفّذ شيء مرتين. - يُرفض المفتاح نفسه مع جسم مختلف بالرمز
409 idempotency_key_reuse. ولّد مفتاحًا لكل عملية منطقية، لا لكل عملية تشغيل. - لا يحتفظ الطلب الفاشل بمفتاحه؛ تنفّذه المحاولة الجديدة مجددًا، وهو المطلوب بعد انتهاء المهلة أو
5xx. - تُحفظ المفاتيح 24 ساعة.
دون الترويسة يُنفّذ POST المكرر كاملًا مرة أخرى. مع POST /organization/keys يعني ذلك إنشاء مفتاح ثانٍ لا يُعرض سره إلا مرة واحدة، لذا أرسل الترويسة.
الأخطاء
كل خطأ بالشكل نفسه:
{
"error": {
"type": "invalid_request",
"code": "unknown_parameter",
"message": "Unknown parameter 'bed'.",
"param": "bed",
"request_id": "req_4f1c2d9a8b7e6f5a4b3c2d1e",
"doc_url": "https://platform.darak.app/docs/guides/errors#unknown-parameter"
}
}
اعتمد في التفرّع على code: لا تُعاد تسمية الرموز، لكن قد تُضاف رموز جديدة. message للبشر وقد تتغير. معاملات الاستعلام غير المعروفة أخطاء وليست متجاهلة، فتظهر الأخطاء الإملائية فورًا. اذكر request_id عند التواصل معنا.
-
400
invalid_request— الطلب غير صحيح. أصلحه؛ ستفشل إعادته دون تغيير بالطريقة نفسها.invalid_value— قيمة معامل غير مقبولة. يحددparamالمعامل.missing_parameter— لم يُرسل معامل مطلوب. يحددparamالمعامل.unknown_parameter— المعامل غير موجود. تُرفض المعاملات غير المعروفة ولا تُتجاهل لتظهر الأخطاء الإملائية.invalid_body— جسم JSON غير سليم أو لا يطابق المخطط.unknown_city— المدينة غير مغطاة. يسردGET /citiesأسماء المدن المقبولة.result_window_exceeded— تجاوزت عمق تصفح خطتك. ضيّق الاستعلام بدلًا من ذلك.limit_reached— بلغ أحد حدود الحساب أقصاه.invalid_cursor— المؤشر غير سليم أو يخص استعلامًا بمرشّحات أو ترتيب مختلف. ابدأ الاستعلام مجددًا.
-
401
authentication_error— المفتاح مفقود أو غير سليم أو لم يعد صالحًا. لا تُعد المحاولة.missing_api_key— ترويسةAuthorization: Bearerمفقودة.invalid_api_key— لا يوجد مفتاح مطابق. تحقق من أن المفتاح كامل ومن البيئة الصحيحة.revoked_api_key— أُلغي هذا المفتاح. أنشئ مفتاحًا جديدًا.expired_api_key— انتهت صلاحية هذا المفتاح. أنشئ مفتاحًا جديدًا.api_key_in_query— أُرسل المفتاح في الرابط حيث يتسرّب إلى السجلات. انقله للترويسة ودوّره.
-
403
permission_error— المفتاح صالح، لكنه غير مخوّل لهذا الطلب. لا تُعد المحاولة.scope_not_in_plan— لا تشمل خطتك هذه الواجهة. رقِّ الخطة للوصول إليها.scope_not_in_key— تشمل خطتك الواجهة لكن المفتاح غير مخوّل لها. عدّل المفتاح.admin_key_required— تتطلب نقطة النهاية مفتاح إدارة (dk_admin_…).admin_key_not_allowed— مفاتيح الإدارة تصل فقط إلى/v1/organization. استخدم مفتاح بيانات هنا.forbidden_action— لا يسمح دورك في المؤسسة بهذا الإجراء.cr_outside_allowlist— السجل التجاري غير مدرج في قائمة السماح لحسابك.ip_not_allowed— عنوان المتصل غير مدرج في قائمة عناوين IP المسموحة للمؤسسة.client_suspended— الحساب معلّق. تواصل معنا.client_expired— انتهت مدة الحساب. تواصل معنا.
-
404
not_found— المورد غير موجود. وقد يكون الإعلان لم يعد نشطًا.not_found— المورد غير موجود.city_not_found— المدينة غير موجودة. يسردGET /citiesالمدن.route_not_found— نقطة النهاية غير موجودة. المواصفة في/v1/openapi.json.listing_not_found— لا يوجد إعلان نشط بهذا المعرّف. قد يكون أُزيل.neighborhood_not_found— لا يوجد حي بهذا المعرّف في المدينة.project_not_found— المشروع على الخارطة غير موجود.period_not_found— لم ينشر المصدر بيانات للفترة. يسردdetails.available_periodsالفترات المتاحة.release_not_found— لا يوجد إصدار منشور مطابق من مؤشر دارك العقاري. يسردdetails.available_releasesالإصدارات.export_not_found— لا يوجد تصدير بهذا المعرّف للمؤسسة. تُحفظ سجلات التصدير 90 يومًا وملفاته 7 أيام.
-
405
method_not_allowed— المسار صحيح وطريقة HTTP غير صحيحة. تسردAllowالطرق المقبولة.method_not_allowed— المسار موجود، لكن ليس لهذه الطريقة.
-
409
conflict— لا يمكن تطبيق الطلب في الحالة الحالية. غيّره ثم أعد المحاولة.conflict— تمنع حالة المورد الحالية هذا الإجراء.idempotency_key_reuse— استُخدمIdempotency-Keyمع جسم مختلف. استخدم مفتاحًا جديدًا.key_limit— بلغت أقصى عدد مفاتيح لخطتك. ألغِ مفتاحًا أولًا.project_limit— بلغت أقصى عدد مشاريع لخطتك.name_taken— يوجد عنصر بهذا الاسم بالفعل.export_limit— هناك صادرات كثيرة قيد التنفيذ أو أُنشئت اليوم. انتظر اكتمال أحدها؛ يحددdetailsالحد.
-
429
rate_limit_error— خفّض المعدل. تحددRetry-Afterمدة الانتظار.rate_limited— تجاوزت معدل الوحدات في الدقيقة. انتظر عدد الثواني فيRetry-After.monthly_quota_exceeded— نفدت حصة وحدات الشهر. تتجدد في بداية الشهر التالي بتوقيت UTC، أو ارفع سقف الإنفاق.spend_cap_reached— بلغ الاستخدام الإضافي سقف الإنفاق الشهري الذي حدده المالك. ارفعه للمتابعة.project_cap_exceeded— بلغ مشروع المفتاح سقف وحداته الشهري.
-
500
api_error— الخطأ من جانبنا. أعد المحاولة مع تراجع أُسّي.internal_error— حدث خلل من جانبنا. أعد المحاولة مع تراجع؛ واذكرrequest_idإذا استمر.
يمكن إعادة محاولة أخطاء 5xx بأمان مع تراجع أُسّي.
الإصدارات
الإصدار في المسار (/v1). داخل الإصدار نجري تغييرات إضافية فقط: نقاط نهاية ومعاملات اختيارية وحقول استجابة وقيم تعداد جديدة. يجب أن يتجاهل كودك الحقول والقيم غير المعروفة له.
تأتي التغييرات الكاسرة بإصدار جديد. يبقى القديم عاملًا 12 شهرًا على الأقل بعد إطلاق الجديد. يُعلن أي إيقاف في سجل التغييرات، وله موجز RSS، وبالبريد. تحمل الاستجابات ترويسة Deprecation وفق RFC 9745، ثم Sunset وفق RFC 8594 عند تحديد التاريخ. راقبها في سجلاتك.
الشروط عمليًا
يخضع استخدام API لـشروط استخدام Darak API. تؤثر البنود التالية في التصميم، لذا تعرّف عليها قبل بناء المزامنة لا بعدها:
- حد التخزين 30 يومًا. يمكنك حفظ بيانات دارك لتشغيل تطبيقك حتى 30 يومًا من الجلب، ثم تحديثها عبر API أو حذفها. يمكن حفظ الإحصاءات المجمعة المشتقة للتقارير الداخلية مدة أطول إذا لم تُعِد إنتاج بيانات مستوى الإعلان. صُممت وصفة المزامنة لإبقاء النسخة حديثة بدل تراكمها.
- أوقف عرض الإعلانات المختفية خلال 7 أيام. عندما يتوقف إرجاع إعلان، لبيعه أو تأجيره أو سحبه أو دمجه، أوقف عرضه خلال 7 أيام. الإشارة هي تعذر جلبه بالمعرّف أو ظهوره في
missing_ids. - طلبات الإزالة خلال 3 أيام عمل. إذا أخبرناك بوجوب إزالة بيانات محددة، احذفها وأوقف عرضها خلال 3 أيام عمل. احتفظ بمعرّفات يمكن الوصول إليها لتنفّذ ذلك.
- نسب المصدر مطلوب عند العرض. أظهر عبارة «البيانات من دارك» مع رابط darak.app. عند عرض إعلان مفرد، اربط
urlوانسبه للمصدر بالاسم، مثل «منشور على عقار»، أو اربطsource.urlالذي يحوّل إلى الإعلان الأصلي. بذلك يُنسب الإعلان لناشره ويتمكن الناس من التحقق منه. - عرض البيانات لمستخدميك يتطلب خطة مدفوعة. الخطة المجانية للبناء والاختبار مع فريقك ومستخدمي الاختبار. لا تسمح خطة ذاتية الخدمة بإعادة توزيع بيانات دارك كمجموعة أو تغذية أو API. يمكن لـEnterprise ترخيص إعادة توزيع مجاميع مشتقة، كالوسطاء والمؤشرات والعوائد، لا يمكن عكسها إلى إعلانات.
- البيانات الحكومية المفتوحة مختلفة. تحمل استجابات الصفقات المسجلة تحت /transactions و/market/transactions، و/market/land-prices، كائن
attributionوتخدم بيانات سعودية مفتوحة وفق رخصة البيانات المفتوحة السعودية. لا تسري عليها القواعد السابقة: يمكنك تخزينها ونشرها وإعادة بيعها مع إبقاء إشعارattributionوروابط مجموعات البيانات معها، وفق القسم 3.4 من شروط API.
تستبعد نقاط النهاية القياسية أسماء المعلنين وأرقام هواتفهم وسجلاتهم التجارية. قد تحتوي نصوص الإعلانات وصورها بيانات شخصية اختار المعلن تضمينها. أنت جهة تحكم مستقلة فيما تخزّنه، ويسري عليك نظام حماية البيانات الشخصية السعودي مباشرة.