{"openapi":"3.1.0","info":{"title":"Darak API","version":"1.0.0","description":"Saudi real-estate listings and market data, aggregated from 13+ sources, deduplicated and quality-filtered. The same inventory powers [darak.app](https://darak.app).\n\n## Quickstart\n\n1. Get an API key (`dk_live_…`) from your Darak account.\n2. Make a request:\n\n```bash\ncurl \"https://api.darak.app/v1/listings?city=riyadh&listing_type=rent&limit=5\" \\\n  -H \"Authorization: Bearer $DARAK_API_KEY\"\n```\n\n   Or with an official SDK, which adds types, paging and retries. Both cover every endpoint here and are generated from this spec.\n\n```ts\n// npm install @darak-app/sdk\nimport { Darak } from \"@darak-app/sdk\";\n\nconst darak = new Darak(); // reads DARAK_API_KEY\nconst page = await darak.listings.search({ city: \"riyadh\", listing_type: \"rent\", limit: 5 });\n```\n\n```python\n# pip install darak\nfrom darak import Darak\n\ndarak = Darak()  # reads DARAK_API_KEY\npage = darak.listings.search(city=\"riyadh\", listing_type=\"rent\", limit=5)\n```\n\n3. Use `GET /cities` and `GET /cities/{city}/neighborhoods` to find the city slugs and neighborhood ids that filters accept, and `GET /enums` for allowed values.\n\nAll responses are JSON. Single objects come back as `{ \"data\": { … } }`, lists as `{ \"data\": [ … ], \"pagination\": { … } }`.\n\n**Where things are.** The OpenAPI document is at [`/v1/openapi.json`](https://api.darak.app/v1/openapi.json) — no key needed — and generates both SDKs, so you can generate your own client from it too. [`@darak-app/sdk`](https://www.npmjs.com/package/@darak-app/sdk) is on npm and [`darak`](https://pypi.org/project/darak/) on PyPI. Changes are announced in the [changelog](https://platform.darak.app/changelog), which has an RSS feed, and availability is on the [status page](https://platform.darak.app/status). If something is wrong, look the call up yourself with `GET /organization/request-logs?request_id=…` — it carries the status, the error and the parameter at fault — or email [hello@darak.app](mailto:hello@darak.app) quoting the `request_id`.\n\n## Authentication\n\nSend your key in the `Authorization` header on every request:\n\n```\nAuthorization: Bearer dk_live_…\n```\n\n- Keys are secret. Call the API from your servers only: never from browsers, mobile apps or public repositories.\n- A key passed in the URL (`?api_key=`) is rejected with `api_key_in_query`. Rotate any key that was ever put in a URL.\n- Accounts can hold several keys, grouped into projects. A key can be limited to some APIs and given an expiry date; calls outside its APIs fail with `scope_not_in_key`, and an expired key gets `expired_api_key`.\n- To rotate a key, use **Rotate** in the dashboard: you get a new key with the same settings, and the old one keeps working for the grace period you choose, so you can deploy without downtime. Revocation takes effect immediately.\n\n**Storing a key.** Keep it in an environment variable or a secret manager, never in source control. Keys carry a fixed `dk_live_` or `dk_admin_` prefix so secret scanners can spot one easily — if a key does reach a public repository, rotate it straight away and revoke the old one once your deploy is through.\n\n**Two kinds of key.** A data key (`dk_live_…`) reads listings, market data, analytics and projects. An admin key (`dk_admin_…`), created by an organization owner, manages the organization itself — keys, projects, members, usage and audit events — and is the only thing the `/v1/organization` endpoints accept. The two never overlap: a data key on an admin endpoint gets `admin_key_required`, an admin key anywhere else gets `admin_key_not_allowed`. Admin calls aren't metered.\n\n**Test keys.** A `dk_test_…` key reads the same live data as a live key, under a fixed allowance of 1,000 units a month at 30 units a minute, 25 results a page and 250 deep. It counts against its own buckets, so a test key left running in CI can't eat the quota your production integration depends on, and it can never generate a bill — overage is off whatever the plan allows. It reaches the same APIs your plan does, so what you build against is what you ship against. Create one on the API keys page; an organization can hold three, separate from the plan's limit on live keys.\n\n**OAuth is for the MCP server, not direct calls.** People connect AI assistants through [Darak MCP](/docs/guides/mcp) by signing in with OAuth. The MCP server exchanges their token for a short-lived API credential bound to the organization they chose at consent, so those calls count against that organization's plan and appear in its logs. Tokens issued to MCP clients are not accepted by the API directly: a server, script or scheduled job should hold a key.\n\n## What a listing is\n\n- **Prices.** `price.yearly_sar` is the comparable number: rentals posted monthly, weekly or daily are converted to a yearly amount, and sales are the total price. `price.as_posted` keeps the advertiser's original amount and period.\n- **One listing per property.** When the same property is posted on several sources, Darak keeps one listing and lists the others in `also_listed_on`.\n- **Quality filtering.** Search and counts exclude listings with implausible prices or sizes, the same filter darak.app uses. `GET /listings/{id}` and `/listings/batch` skip that filter, so they return listings search won't.\n- **Photos are a condition of being served.** A listing is only available once Darak has copied its photos to its own CDN — a newly scraped listing appears a little later, and one that never gets photos never appears at all. Land is exempt, since land is routinely advertised without any. This applies to detail and batch lookups too: a photo-less apartment is a `404`, and comes back in `missing_ids`.\n- **Freshness.** `first_seen_at` is when Darak first saw a listing. `updated_at` is its last update at the source, or the last time Darak saw it if the source doesn't publish update times. `last_seen_at` is when Darak last confirmed it is live.\n- **Asking prices.** Listings are asking prices, not transaction prices. Data comes from third-party sources and may be incomplete or out of date.\n- **Attribution.** Where you show listings to your users, credit Darak and link to the original ad (`source.url`).\n\n## Limits and quotas\n\nEvery request costs **units** (shown in `X-Request-Units`, and as `x-units` on each endpoint in this reference):\n\n- List endpoints (listing search, project lists): 1 unit per 25 results asked for with `limit`, counted up to your plan's page size. A page of 100 costs 4.\n- Listing batch: 1 unit per 25 ids.\n- Single resources, reference data and market data: 1 unit.\n- Analytics: 2 (market position), 3 (comparables, rental yield, neighborhood compare), 5 (trends), or 2 per 25 results (deals).\n\nYour plan sets:\n\n- **Rate limit:** units per minute. Headers: `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` (seconds).\n- **Monthly quota:** units per calendar month (UTC). Headers: `X-Quota-Limit`, `X-Quota-Remaining`, `X-Quota-Reset`.\n- **Page size:** the largest `limit` you can request.\n- **Paging depth:** how many results of a single query you can page through. Past it you get `result_window_exceeded`; narrow the query, or sync with `updated_since`.\n\n| Plan | Units / minute | Units / month | Page size | Paging depth | Active keys |\n| --- | --- | --- | --- | --- | --- |\n| Free | 30 | 2,500 | 25 | 500 | 5 |\n| Starter | 60 | 50,000 | 50 | 5,000 | 25 |\n| Growth | 150 | 200,000 | 100 | 5,000 | 25 |\n| Pro | 300 | 750,000 | 100 | 20,000 | 25 |\n\nEnterprise plans set these individually. Your own are on the Plan page in the dashboard, and `GET /limits` returns them to the key making the call — it costs no units, so read it at start-up rather than hard-coding a page size, and the same code works on every plan.\n\n**Extra usage.** On any paid subscription (Starter, Growth or Pro), requests past the monthly quota keep working and are billed per 1,000 units at the end of the billing period, up to the monthly spend cap an owner sets on the Billing page. At the cap you get `429 spend_cap_reached` until the quota resets. With a cap of 0, the quota is a hard limit (`429 monthly_quota_exceeded`).\n\nOver a limit you get `429` with a `Retry-After` header. Wait that many seconds, then retry. Requests that fail (4xx, 5xx, and 429s) don't count toward your monthly quota.\n\n## Pagination\n\nList endpoints return a page plus:\n\n```json\n\"pagination\": { \"limit\": 25, \"next_cursor\": \"eyJvIjoy….pkFEfJUOpRbZ…\", \"has_more\": true, \"result_window_reached\": false }\n```\n\n- To get the next page, repeat the request with `cursor=<next_cursor>` and **the same parameters**. A cursor used with different filters or sort is rejected.\n- Treat a cursor as an opaque string: pass back exactly what you were given. Cursors are signed, so an edited or hand-built one is rejected with `invalid_cursor`, and their contents will change when the underlying pagination does.\n- `result_window_reached: true` means more results exist but your plan's paging depth is reached. Narrow the query (neighborhood, price, property type) instead of paging deeper.\n- Listing search doesn't return a total. Use `GET /listings/count` with the same filters.\n\nCursors carry an offset, so under `sort=newest` or a price sort a listing added or removed between two pages can shift rows across the boundary and be served twice or skipped. That is inherent to paging a live table, and it is why a sync uses `sort=updated_asc` — see [Keeping a copy in sync](https://platform.darak.app/docs/guides/sync).\n\n## Retrying safely\n\nA `GET` can be repeated freely. For a `POST`, send an `Idempotency-Key` header — any unique string of up to 255 characters, a UUID is ideal — and the call will happen at most once however many times you send it:\n\n```\nIdempotency-Key: 8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa\n```\n\n- Retry with the **same key and the same body** and you get the first call's response back, with `Idempotent-Replay: true`. Nothing runs twice.\n- The same key with a **different body** is rejected with `409 idempotency_key_reuse`. Generate a key per logical operation, not per process.\n- A call that failed doesn't hold its key: retrying it runs again, which is what you want after a timeout or a `5xx`.\n- Keys are remembered for 24 hours.\n\nWithout the header a retried `POST` runs again in full. On `POST /organization/keys` that means a second key you were only ever shown the secret for once, so send the header.\n\n## Errors\n\nEvery error has the same shape:\n\n```json\n{\n  \"error\": {\n    \"type\": \"invalid_request\",\n    \"code\": \"unknown_parameter\",\n    \"message\": \"Unknown parameter 'bed'.\",\n    \"param\": \"bed\",\n    \"request_id\": \"req_4f1c2d9a8b7e6f5a4b3c2d1e\",\n    \"doc_url\": \"https://platform.darak.app/docs/guides/errors#unknown-parameter\"\n  }\n}\n```\n\nBranch on `code`: codes are never renamed, though new ones may be added. `message` is for humans and may change. Unknown query parameters are errors, not ignored, so typos surface immediately. Quote `request_id` when you contact us.\n\n- **400 `invalid_request`** — The request is wrong. Fix it; sending it again unchanged fails the same way.\n  - `invalid_value` — A parameter's value isn't accepted. `param` names it.\n  - `missing_parameter` — A required parameter was omitted. `param` names it.\n  - `unknown_parameter` — No such parameter. Unknown ones are rejected, not ignored, so typos surface.\n  - `invalid_body` — The JSON body was malformed or didn't match the schema.\n  - `unknown_city` — That city isn't covered. `GET /cities` lists the slugs that are.\n  - `result_window_exceeded` — Paging past your plan's depth. Narrow the query instead.\n  - `limit_reached` — An account limit is already at its maximum.\n  - `invalid_cursor` — The cursor is malformed, or belongs to a query with different filters or sort. Start the query again.\n\n- **401 `authentication_error`** — The key was missing, malformed or is no longer usable. Don't retry.\n  - `missing_api_key` — No `Authorization: Bearer` header.\n  - `invalid_api_key` — No key matches. Check for a truncated or wrong-environment key.\n  - `revoked_api_key` — This key was revoked. Create a new one.\n  - `expired_api_key` — This key passed its expiry date. Create a new one.\n  - `api_key_in_query` — A key was passed in the URL, where it leaks into logs. Move it to the header and rotate it.\n\n- **403 `permission_error`** — The key is valid but isn't allowed this call. Don't retry.\n  - `scope_not_in_plan` — Your plan doesn't include this API. Upgrade to reach it.\n  - `scope_not_in_key` — Your plan includes this API but this key isn't allowed it. Edit the key.\n  - `admin_key_required` — This endpoint needs an admin key (`dk_admin_…`).\n  - `admin_key_not_allowed` — Admin keys only reach `/v1/organization`. Use a data key here.\n  - `forbidden_action` — Your role in the organization doesn't allow this.\n  - `cr_outside_allowlist` — That commercial registration isn't on your account's allowlist.\n  - `ip_not_allowed` — Your organization's IP allowlist doesn't include this caller's address.\n  - `client_suspended` — The account is suspended. Contact us.\n  - `client_expired` — The account's term has ended. Contact us.\n\n- **404 `not_found`** — No such resource. For a listing, it may simply no longer be live.\n  - `not_found` — No such resource.\n  - `city_not_found` — No such city. `GET /cities` lists them.\n  - `route_not_found` — No such endpoint. The spec is at `/v1/openapi.json`.\n  - `listing_not_found` — No live listing with that id. It may have been delisted.\n  - `neighborhood_not_found` — No such neighborhood in that city.\n  - `project_not_found` — No such off-plan project.\n\n- **405 `method_not_allowed`** — Right path, wrong HTTP method. `Allow` lists the ones it takes.\n  - `method_not_allowed` — That path exists, but not for this method.\n\n- **409 `conflict`** — The request can't be applied as things stand. Change it, then retry.\n  - `conflict` — The resource's current state rules this out.\n  - `idempotency_key_reuse` — This `Idempotency-Key` was already used with a different body. Use a new key.\n  - `key_limit` — You already hold the most keys your plan allows. Revoke one first.\n  - `project_limit` — You already hold the most projects your plan allows.\n  - `name_taken` — Something with that name already exists.\n\n- **429 `rate_limit_error`** — Slow down. `Retry-After` says how long to wait.\n  - `rate_limited` — Over your per-minute unit rate. Wait `Retry-After` seconds.\n  - `monthly_quota_exceeded` — This month's unit quota is spent. It resets at the start of the next UTC month, or raise the spend cap.\n  - `spend_cap_reached` — Extra usage hit the monthly spend cap an owner set. Raise it to continue.\n  - `project_cap_exceeded` — This key's project hit its own monthly unit cap.\n\n- **500 `api_error`** — Our fault. Retry with exponential backoff.\n  - `internal_error` — Something broke on our side. Retry with backoff; quote `request_id` if it lasts.\n\n`5xx` errors are safe to retry with exponential backoff.\n\n## Versioning\n\nThe version is in the path (`/v1`). Within a version we only make additive changes: new endpoints, optional parameters, response fields and enum values. Your code must ignore fields and values it doesn't recognize.\n\nBreaking changes ship as a new version. The old version keeps working for at least 12 months after the new one launches. Anything deprecated is announced in the [changelog](https://platform.darak.app/changelog) (with an RSS feed) and by email, and its responses carry a `Deprecation` header (RFC 9745) and, once the date is set, a `Sunset` header (RFC 8594). Watch for those headers in your logs.\n\n## Terms in practice\n\nUse of the API is subject to the [Darak API terms of use](https://platform.darak.app/legal/terms). Four clauses shape how you build, so they are worth knowing before you design a sync rather than after:\n\n- **Storage is capped at 30 days.** You may keep Darak data to run your application for up to 30 days from when you retrieved it; after that, refresh it through the API or delete it. Aggregated statistics you derive for internal reporting may be kept longer, as long as they can't be reversed into listing-level data. The sync recipe above is built for exactly this: it keeps a copy current rather than accumulating one.\n- **Delisted listings come down within 7 days.** Once a listing stops being returned — sold, rented, withdrawn, merged as a duplicate — stop showing it within 7 days. A listing you can no longer fetch by id, or that comes back in `missing_ids`, is your signal.\n- **Takedowns are 3 business days.** If we tell you specific data must be removed, delete it and stop showing it within 3 business days. Keep the listing ids you have stored addressable so you can act on that.\n- **Attribution is required where you display data.** Show \"Data by Darak\" near it with a link to [darak.app](https://darak.app), and where you show an individual listing, link `source.url` or credit the source by name (\"Listed on Aqar\"). That credits the original publisher and lets people verify the ad.\n\nStandard endpoints are built to exclude advertiser names, phone numbers and commercial registration numbers. Listing text and images may still contain personal data an advertiser chose to include, and you are an independent controller of whatever you store — the Saudi Personal Data Protection Law applies to you directly.\n","contact":{"name":"Darak","url":"https://platform.darak.app/docs"},"termsOfService":"https://platform.darak.app/legal/terms"},"servers":[{"url":"https://api.darak.app/v1"}],"externalDocs":{"description":"Guides, changelog and status","url":"https://platform.darak.app"},"security":[{"apiKey":[]}],"tags":[{"name":"Reference data","description":"The cities, neighborhoods, directions and enumerated values that every other filter is expressed in. Start here to learn the slugs and ids the API accepts. Included in every plan."},{"name":"Listings","description":"Every live rental and sale listing in Saudi Arabia, deduplicated across 13+ sources into one listing per property, with photos, full detail and price history. Search them, count them, fetch them by id, and follow a listing's price over time. Included in every plan."},{"name":"Market data","description":"Aggregates over those listings: median asking rents and prices, price and area distributions, supply, and a vacancy indicator, for a city or a single neighborhood. Built for reports and market pages. Starter and up."},{"name":"Analytics","description":"Valuation and investment questions answered against the same inventory: comparables for a listing, where its price sits in its market, gross rental yields, price trends, and listings asking noticeably less than their peers. Growth and up."},{"name":"Off-plan projects","description":"New developments with their units, price ranges, developers and linked listings, for buyers and lenders tracking new supply. Pro and up."},{"name":"Administration","description":"Manage your own organization — keys, projects, members, usage and audit events — with an admin key (`dk_admin_…`). These endpoints are unmetered, and a data key is refused here."}],"paths":{"/cities":{"get":{"operationId":"reference.cities","summary":"List cities","description":"Cities Darak covers. Use `slug` wherever a `city` parameter is accepted. Free on every plan: it costs no units.","tags":["Reference data"],"x-scope":"reference","x-units":0,"security":[{"apiKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","description":"Identifier used by every `city` parameter.","example":"riyadh"},"name_en":{"type":"string","example":"Riyadh"},"name_ar":{"type":"string","example":"الرياض"}},"required":["slug","name_en","name_ar"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"slug":"riyadh","name_en":"Riyadh","name_ar":"الرياض"}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/cities/{city}/neighborhoods":{"get":{"operationId":"reference.neighborhoods","summary":"List neighborhoods","description":"Active neighborhoods in a city. Neighborhood `id`s are stable and are how listings and market endpoints refer to neighborhoods. Free on every plan: it costs no units.","tags":["Reference data"],"x-scope":"reference","x-units":0,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"path","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Stable id. Pass as `neighborhood_id` to filter listings and market data.","example":1287},"slug":{"type":"string","example":"al-malqa"},"name_ar":{"type":"string","example":"الملقا"},"name_en":{"type":"string","example":"Al Malqa"},"direction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The city direction (north, east, …) it belongs to, if mapped."},"center":{"anyOf":[{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"],"additionalProperties":false},{"type":"null"}],"description":"Approximate centroid."}},"required":["id","slug","name_ar","name_en","direction_id","center"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":1287,"slug":"al-malqa","name_ar":"الملقا","name_en":"Al Malqa","direction_id":null,"center":{"lat":0,"lng":0}}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/cities/{city}/directions":{"get":{"operationId":"reference.directions","summary":"List city directions","description":"Groupings of neighborhoods by part of the city (north, east, …). Empty for cities that aren't mapped yet. Free on every plan: it costs no units.","tags":["Reference data"],"x-scope":"reference","x-units":0,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"path","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name_en":{"type":"string","example":"North Riyadh"},"name_ar":{"type":"string","example":"شمال الرياض"},"neighborhood_ids":{"type":"array","items":{"type":"integer"}}},"required":["id","name_en","name_ar","neighborhood_ids"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":0,"name_en":"North Riyadh","name_ar":"شمال الرياض","neighborhood_ids":[0]}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/enums":{"get":{"operationId":"reference.enums","summary":"List enumerated values","description":"Allowed values for enumerated fields and filters. New values may be added at any time; clients must tolerate values they don't recognize. Free on every plan: it costs no units.","tags":["Reference data"],"x-scope":"reference","x-units":0,"security":[{"apiKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"listing_types":{"type":"array","items":{"type":"string"}},"listing_categories":{"type":"array","items":{"type":"string"}},"property_types":{"type":"object","properties":{"residential":{"type":"array","items":{"type":"string"}},"commercial":{"type":"array","items":{"type":"string"}}},"required":["residential","commercial"],"additionalProperties":false},"rent_frequencies":{"type":"array","items":{"type":"string"}},"advertiser_types":{"type":"array","items":{"type":"string"}},"amenities":{"type":"array","items":{"type":"string"}},"project_features":{"type":"array","items":{"type":"string"}},"project_banks":{"type":"array","items":{"type":"string"}},"sources":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["listing_types","listing_categories","property_types","rent_frequencies","advertiser_types","amenities","project_features","project_banks","sources"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"listing_types":["<listing_types>"],"listing_categories":["<listing_categories>"],"property_types":{"residential":["<residential>"],"commercial":["<commercial>"]},"rent_frequencies":["<rent_frequencies>"],"advertiser_types":["<advertiser_types>"],"amenities":["<amenities>"],"project_features":["<project_features>"],"project_banks":["<project_banks>"],"sources":[{"id":"<id>","name":"<name>"}]}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/limits":{"get":{"operationId":"reference.limits","summary":"Get this key's limits","description":"The plan, rate limit, monthly quota, page size and paging depth that apply to the key making the request, and the APIs it can reach. Free on every plan: it costs no units. Read it at start-up rather than hard-coding a page size, and the same code works on every plan.","tags":["Reference data"],"x-scope":"reference","x-units":0,"security":[{"apiKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"plan":{"type":"string","description":"Plan id.","example":"growth"},"scopes":{"type":"array","items":{"type":"string"},"description":"APIs this key can reach.","example":["reference","listings"]},"rate_limit_per_minute":{"type":"integer","example":150},"monthly_quota_units":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Null on plans with no monthly quota.","example":200000},"max_page_size":{"type":"integer","description":"The largest `limit` a request may ask for.","example":100},"max_result_depth":{"type":"integer","description":"How many results of one query can be paged through before `result_window_reached`.","example":5000}},"required":["plan","scopes","rate_limit_per_minute","monthly_quota_units","max_page_size","max_result_depth"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"plan":"growth","scopes":["reference","listings"],"rate_limit_per_minute":150,"monthly_quota_units":200000,"max_page_size":100,"max_result_depth":5000}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings":{"get":{"operationId":"listings.search","summary":"Search listings","description":"Active, deduplicated listings in one city, quality-filtered like darak.app. Paginate with `cursor`. Paging depth per query is limited by plan; to mirror inventory, sort by `updated_asc` and advance `updated_since`.","tags":["Listings"],"x-scope":"listings","x-units":"1 per 25 results asked for with `limit` (default 25), up to your plan's page size","security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Omit for both.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One or more, comma-separated.","example":["apartment","villa"],"schema":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},"style":"form","explode":false},{"name":"neighborhood_id","in":"query","required":false,"description":"Neighborhood ids from GET /cities/{city}/neighborhoods.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms. Exact at every value, including 5 — darak.app's own filter treats 5 as five-or-more, so the same number returns different sets here. Use `beds_min` for a range.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"beds_min","in":"query","required":false,"description":"Minimum number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"beds_max","in":"query","required":false,"description":"Maximum number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_min","in":"query","required":false,"description":"Minimum number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"price_min","in":"query","required":false,"description":"SAR. Yearly for rentals (see `price.yearly_sar`).","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"price_max","in":"query","required":false,"description":"SAR. Yearly for rentals (see `price.yearly_sar`).","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"area_min","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"area_max","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"furnished","in":"query","required":false,"description":"Whether the listing is furnished. Omit to include listings that don't say.","schema":{"type":"string","enum":["true","false"]}},{"name":"source","in":"query","required":false,"description":"Source platforms, see GET /enums. Values aren't checked against the list, so a misspelled source narrows to nothing rather than erroring.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"bbox","in":"query","required":false,"description":"Bounding box `west,south,east,north` in degrees (GeoJSON order).","example":"46.60,24.70,46.75,24.85","schema":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?(,-?\\d+(\\.\\d+)?){3}$"}},{"name":"updated_since","in":"query","required":false,"description":"Only listings whose `updated_at` is at or after this ISO 8601 time. Combine with `sort=updated_asc` to sync.","example":"2026-09-01T00:00:00Z","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"bathrooms","in":"query","required":false,"description":"Exact number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_max","in":"query","required":false,"description":"Maximum number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"livings_min","in":"query","required":false,"description":"Minimum number of living rooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id_exclude","in":"query","required":false,"description":"Exclude these neighborhoods. Ids from GET /cities/{city}/neighborhoods. Listings Darak could not place in a neighborhood are kept — unlike `neighborhood_id`, which drops them.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"q","in":"query","required":false,"description":"Free-text match on the advertiser's title and description, as posted — not on `headline`, which Darak builds for the response. Several words must all appear; `\"quote a phrase\"` to match it whole, and `|` between words for either. Sources that post no title (Aqar among them) are matched on description alone.","example":"مسبح","schema":{"type":"string","minLength":2,"maxLength":120}},{"name":"amenities","in":"query","required":false,"description":"Only listings that have all of these. See GET /enums.","example":["parking","lift"],"schema":{"minItems":1,"maxItems":11,"type":"array","items":{"type":"string","enum":["ac","kitchen","maid_room","parking","private_roof","lift","pool","gym","balcony","garden","laundry_room"]}},"style":"form","explode":false},{"name":"amenities_exclude","in":"query","required":false,"description":"Exclude listings that have any of these.","schema":{"minItems":1,"maxItems":11,"type":"array","items":{"type":"string","enum":["ac","kitchen","maid_room","parking","private_roof","lift","pool","gym","balcony","garden","laundry_room"]}},"style":"form","explode":false},{"name":"floor","in":"query","required":false,"description":"`ground` for ground-floor listings, `upper` for any stated floor above it. The two do not partition the results: a listing whose floor the source didn't state is in neither.","schema":{"type":"string","enum":["ground","upper"]}},{"name":"source_exclude","in":"query","required":false,"description":"Exclude these source platforms, see GET /enums.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"max_age","in":"query","required":false,"description":"Maximum property age in years.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"verified","in":"query","required":false,"description":"`true` for listings the source marks as verified. `false` means everything else — both listings it marked unverified and listings it said nothing about.","schema":{"type":"string","enum":["true","false"]}},{"name":"advertiser_type","in":"query","required":false,"description":"Who posted the ad. The underlying column holds eight source-specific values; these two group them. Ads by an intermediary who does not say whether they are a firm or a person match neither.","schema":{"type":"string","enum":["company","individual"]}},{"name":"compound","in":"query","required":false,"description":"Compound name, partial match.","schema":{"type":"string","minLength":2,"maxLength":120}},{"name":"in_compound","in":"query","required":false,"description":"Only listings that belong to a compound, whichever one.","schema":{"type":"string","enum":["true","false"]}},{"name":"rent_frequency","in":"query","required":false,"description":"How the rent is advertised. `price.yearly_sar` stays yearly either way; see `price.as_posted`.","schema":{"type":"string","enum":["monthly","yearly"]}},{"name":"days_on_market_min","in":"query","required":false,"description":"Days since Darak first saw the listing.","schema":{"type":"integer","minimum":0,"maximum":3650}},{"name":"days_on_market_max","in":"query","required":false,"description":"Days since Darak first saw the listing.","schema":{"type":"integer","minimum":0,"maximum":3650}},{"name":"sort","in":"query","required":false,"description":"`newest` (first seen by Darak), `updated_desc`/`updated_asc` (by `updated_at`; use `updated_asc` to sync), `price_asc`/`price_desc`, `price_drop` (only listings whose price dropped, biggest drop first; drops over 50% are excluded as likely corrections), `days_on_market_desc`, and `recommended` — Darak's own ranking, blending asking price against comparable listings, how long the ad has been up, how complete it is, and how sought-after the neighborhood is, with no single source allowed to fill the top. It is a ranking rather than an ordering, so it is retuned from time to time and the same query can reorder between releases; page through it freely, but sync with `updated_asc`.","schema":{"default":"newest","type":"string","enum":["newest","updated_desc","updated_asc","price_asc","price_desc","price_drop","days_on_market_desc","recommended"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Listing"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"id":128647,"url":"https://darak.app/en/listing/128647","title":"<title>","headline":"3-bedroom apartment for rent in Al Malqa, Riyadh","description":"<description>","description_en":"<description_en>","listing_type":"rent","listing_category":"residential","property_type":"apartment","price":{"yearly_sar":60000,"as_posted":{"amount":5000,"frequency":"monthly"},"previous_yearly_sar":66000,"changed_at":"2026-09-21T10:00:00.000Z"},"financing":{"rent_now_pay_later_monthly_sar":null,"accepts_bank_financing":true,"landlord_payment_plans":{"monthly":true,"quarterly":true,"semiannually":true}},"bedrooms":3,"bathrooms":2,"livings":1,"area_sqm":140,"floor":"2","age_years":4,"furnished":false,"amenities":["ac","kitchen","parking"],"location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":12,"neighborhood_name_ar":"الملقا","neighborhood_name_en":"Al Malqa","lat":24.7869,"lng":46.6215,"street_width_m":20},"compound_name":"Sedra","project_id":null,"images":["https://images.darak.app/listings/128647/1.webp"],"image_count":8,"advertiser":{"type":"agency"},"verified_by_source":true,"source":{"name":"aqar","listing_id":"7788123","url":"https://sa.aqar.fm/7788123"},"also_listed_on":["bayut"],"first_seen_at":"2026-09-21T10:00:00.000Z","updated_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z","days_on_market":null}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/count":{"get":{"operationId":"listings.count","summary":"Count listings","description":"How many listings match the same filters as search.","tags":["Listings"],"x-scope":"listings","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Omit for both.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One or more, comma-separated.","example":["apartment","villa"],"schema":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},"style":"form","explode":false},{"name":"neighborhood_id","in":"query","required":false,"description":"Neighborhood ids from GET /cities/{city}/neighborhoods.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms. Exact at every value, including 5 — darak.app's own filter treats 5 as five-or-more, so the same number returns different sets here. Use `beds_min` for a range.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"beds_min","in":"query","required":false,"description":"Minimum number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"beds_max","in":"query","required":false,"description":"Maximum number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_min","in":"query","required":false,"description":"Minimum number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"price_min","in":"query","required":false,"description":"SAR. Yearly for rentals (see `price.yearly_sar`).","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"price_max","in":"query","required":false,"description":"SAR. Yearly for rentals (see `price.yearly_sar`).","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"area_min","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"area_max","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"furnished","in":"query","required":false,"description":"Whether the listing is furnished. Omit to include listings that don't say.","schema":{"type":"string","enum":["true","false"]}},{"name":"source","in":"query","required":false,"description":"Source platforms, see GET /enums. Values aren't checked against the list, so a misspelled source narrows to nothing rather than erroring.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"bbox","in":"query","required":false,"description":"Bounding box `west,south,east,north` in degrees (GeoJSON order).","example":"46.60,24.70,46.75,24.85","schema":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?(,-?\\d+(\\.\\d+)?){3}$"}},{"name":"updated_since","in":"query","required":false,"description":"Only listings whose `updated_at` is at or after this ISO 8601 time. Combine with `sort=updated_asc` to sync.","example":"2026-09-01T00:00:00Z","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"bathrooms","in":"query","required":false,"description":"Exact number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_max","in":"query","required":false,"description":"Maximum number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"livings_min","in":"query","required":false,"description":"Minimum number of living rooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id_exclude","in":"query","required":false,"description":"Exclude these neighborhoods. Ids from GET /cities/{city}/neighborhoods. Listings Darak could not place in a neighborhood are kept — unlike `neighborhood_id`, which drops them.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"q","in":"query","required":false,"description":"Free-text match on the advertiser's title and description, as posted — not on `headline`, which Darak builds for the response. Several words must all appear; `\"quote a phrase\"` to match it whole, and `|` between words for either. Sources that post no title (Aqar among them) are matched on description alone.","example":"مسبح","schema":{"type":"string","minLength":2,"maxLength":120}},{"name":"amenities","in":"query","required":false,"description":"Only listings that have all of these. See GET /enums.","example":["parking","lift"],"schema":{"minItems":1,"maxItems":11,"type":"array","items":{"type":"string","enum":["ac","kitchen","maid_room","parking","private_roof","lift","pool","gym","balcony","garden","laundry_room"]}},"style":"form","explode":false},{"name":"amenities_exclude","in":"query","required":false,"description":"Exclude listings that have any of these.","schema":{"minItems":1,"maxItems":11,"type":"array","items":{"type":"string","enum":["ac","kitchen","maid_room","parking","private_roof","lift","pool","gym","balcony","garden","laundry_room"]}},"style":"form","explode":false},{"name":"floor","in":"query","required":false,"description":"`ground` for ground-floor listings, `upper` for any stated floor above it. The two do not partition the results: a listing whose floor the source didn't state is in neither.","schema":{"type":"string","enum":["ground","upper"]}},{"name":"source_exclude","in":"query","required":false,"description":"Exclude these source platforms, see GET /enums.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"max_age","in":"query","required":false,"description":"Maximum property age in years.","schema":{"type":"integer","minimum":0,"maximum":100}},{"name":"verified","in":"query","required":false,"description":"`true` for listings the source marks as verified. `false` means everything else — both listings it marked unverified and listings it said nothing about.","schema":{"type":"string","enum":["true","false"]}},{"name":"advertiser_type","in":"query","required":false,"description":"Who posted the ad. The underlying column holds eight source-specific values; these two group them. Ads by an intermediary who does not say whether they are a firm or a person match neither.","schema":{"type":"string","enum":["company","individual"]}},{"name":"compound","in":"query","required":false,"description":"Compound name, partial match.","schema":{"type":"string","minLength":2,"maxLength":120}},{"name":"in_compound","in":"query","required":false,"description":"Only listings that belong to a compound, whichever one.","schema":{"type":"string","enum":["true","false"]}},{"name":"rent_frequency","in":"query","required":false,"description":"How the rent is advertised. `price.yearly_sar` stays yearly either way; see `price.as_posted`.","schema":{"type":"string","enum":["monthly","yearly"]}},{"name":"days_on_market_min","in":"query","required":false,"description":"Days since Darak first saw the listing.","schema":{"type":"integer","minimum":0,"maximum":3650}},{"name":"days_on_market_max","in":"query","required":false,"description":"Days since Darak first saw the listing.","schema":{"type":"integer","minimum":0,"maximum":3650}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"total":{"type":"integer"}},"required":["total"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"total":0}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/batch":{"get":{"operationId":"listings.batch","summary":"Get listings by id","description":"Up to 100 listings in one call, in the order requested. Ids that are no longer active (sold, rented, removed, or merged as a duplicate) come back in `missing_ids`.","tags":["Listings"],"x-scope":"listings","x-units":"1 per 25 ids","security":[{"apiKey":[]}],"parameters":[{"name":"ids","in":"query","required":true,"description":"Comma-separated listing ids.","example":[128647,128650],"schema":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Listing"}},"missing_ids":{"type":"array","items":{"type":"integer"}}},"required":["data","missing_ids"],"additionalProperties":false},"example":{"data":[{"id":128647,"url":"https://darak.app/en/listing/128647","title":"<title>","headline":"3-bedroom apartment for rent in Al Malqa, Riyadh","description":"<description>","description_en":"<description_en>","listing_type":"rent","listing_category":"residential","property_type":"apartment","price":{"yearly_sar":60000,"as_posted":{"amount":5000,"frequency":"monthly"},"previous_yearly_sar":66000,"changed_at":"2026-09-21T10:00:00.000Z"},"financing":{"rent_now_pay_later_monthly_sar":null,"accepts_bank_financing":true,"landlord_payment_plans":{"monthly":true,"quarterly":true,"semiannually":true}},"bedrooms":3,"bathrooms":2,"livings":1,"area_sqm":140,"floor":"2","age_years":4,"furnished":false,"amenities":["ac","kitchen","parking"],"location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":12,"neighborhood_name_ar":"الملقا","neighborhood_name_en":"Al Malqa","lat":24.7869,"lng":46.6215,"street_width_m":20},"compound_name":"Sedra","project_id":null,"images":["https://images.darak.app/listings/128647/1.webp"],"image_count":8,"advertiser":{"type":"agency"},"verified_by_source":true,"source":{"name":"aqar","listing_id":"7788123","url":"https://sa.aqar.fm/7788123"},"also_listed_on":["bayut"],"first_seen_at":"2026-09-21T10:00:00.000Z","updated_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z","days_on_market":null}],"missing_ids":[0]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/{id}":{"get":{"operationId":"listings.get","summary":"Get a listing","description":"One active listing. Returns 404 once it's sold, rented or removed, or if it was merged into another listing as a duplicate.","tags":["Listings"],"x-scope":"listings","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Listing id.","example":128647,"schema":{"type":"integer","minimum":1,"maximum":2147483647}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Listing"}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":128647,"url":"https://darak.app/en/listing/128647","title":"<title>","headline":"3-bedroom apartment for rent in Al Malqa, Riyadh","description":"<description>","description_en":"<description_en>","listing_type":"rent","listing_category":"residential","property_type":"apartment","price":{"yearly_sar":60000,"as_posted":{"amount":5000,"frequency":"monthly"},"previous_yearly_sar":66000,"changed_at":"2026-09-21T10:00:00.000Z"},"financing":{"rent_now_pay_later_monthly_sar":null,"accepts_bank_financing":true,"landlord_payment_plans":{"monthly":true,"quarterly":true,"semiannually":true}},"bedrooms":3,"bathrooms":2,"livings":1,"area_sqm":140,"floor":"2","age_years":4,"furnished":false,"amenities":["ac","kitchen","parking"],"location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":12,"neighborhood_name_ar":"الملقا","neighborhood_name_en":"Al Malqa","lat":24.7869,"lng":46.6215,"street_width_m":20},"compound_name":"Sedra","project_id":null,"images":["https://images.darak.app/listings/128647/1.webp"],"image_count":8,"advertiser":{"type":"agency"},"verified_by_source":true,"source":{"name":"aqar","listing_id":"7788123","url":"https://sa.aqar.fm/7788123"},"also_listed_on":["bayut"],"first_seen_at":"2026-09-21T10:00:00.000Z","updated_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z","days_on_market":null}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/{id}/price-history":{"get":{"operationId":"listings.price_history","summary":"Get a listing's price history","description":"Every price change Darak recorded for an active listing, oldest first. The Free plan sees the last 90 days; paid plans see the full history.","tags":["Listings"],"x-scope":"listings","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Listing id.","example":128647,"schema":{"type":"integer","minimum":1,"maximum":2147483647}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"listing_id":{"type":"integer"},"current_price_yearly_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]},"history_window_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Days of history included: 90 on the Free plan, null (all of it) on paid plans."},"changes":{"type":"array","items":{"type":"object","properties":{"changed_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},"from_yearly_sar":{"type":"integer"},"to_yearly_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["changed_at","from_yearly_sar","to_yearly_sar"],"additionalProperties":false}}},"required":["listing_id","current_price_yearly_sar","first_seen_at","history_window_days","changes"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"listing_id":0,"current_price_yearly_sar":null,"first_seen_at":"2026-09-21T10:00:00.000Z","history_window_days":null,"changes":[{"changed_at":"2026-09-21T10:00:00.000Z","from_yearly_sar":0,"to_yearly_sar":null}]}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/summary":{"get":{"operationId":"market.summary","summary":"Market summary","description":"Headline numbers for a city (or neighborhoods): listing count, median and quartile price, median area and price per m², how recently listings were updated, and breakdowns by property type, top neighborhoods by volume, and source.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"sample_size":{"type":"integer","description":"Listings in the sample.","example":18234},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price.","example":60000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile price."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile price."},"median_area_sqm":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median area in m², over listings that state an area."},"median_price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median of each listing's price divided by its area."},"area_sample_size":{"type":"integer","description":"Listings that state an area (the base of the area medians)."},"updated_last_3_days":{"type":"integer"},"updated_last_7_days":{"type":"integer"},"by_property_type":{"type":"array","items":{"type":"object","properties":{"property_type":{"type":"string"},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["property_type","sample_size","median_price_sar"],"additionalProperties":false}},"top_neighborhoods":{"type":"array","items":{"type":"object","properties":{"neighborhood_id":{"type":"integer"},"name_ar":{"type":"string"},"name_en":{"type":"string"},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["neighborhood_id","name_ar","name_en","sample_size","median_price_sar"],"additionalProperties":false},"description":"Up to 10 neighborhoods with the most listings in the sample."},"sources":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"count":{"type":"integer"}},"required":["source","count"],"additionalProperties":false},"description":"Listings in the sample per source (after deduplication)."},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","price_basis","sample_size","median_price_sar","p25_price_sar","p75_price_sar","median_area_sqm","median_price_per_sqm_sar","area_sample_size","updated_last_3_days","updated_last_7_days","by_property_type","top_neighborhoods","sources","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"price_basis":"yearly_rent","sample_size":18234,"median_price_sar":60000,"p25_price_sar":null,"p75_price_sar":null,"median_area_sqm":null,"median_price_per_sqm_sar":null,"area_sample_size":0,"updated_last_3_days":0,"updated_last_7_days":0,"by_property_type":[{"property_type":"<property_type>","sample_size":214,"median_price_sar":null}],"top_neighborhoods":[{"neighborhood_id":0,"name_ar":"<name_ar>","name_en":"<name_en>","sample_size":214,"median_price_sar":null}],"sources":[{"source":"<source>","count":0}],"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/price-distribution":{"get":{"operationId":"market.price_distribution","summary":"Price distribution","description":"Histogram and percentiles of price. Buckets are equal-width between `range_sar.min` (the lowest outlier fence, rounded down) and `range_sar.max` (darak.app's price-slider maximum for the property type); listings outside that range are reported in `below_range_count` / `above_range_count` and still count toward the median and percentiles.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"bucket_count","in":"query","required":false,"description":"Number of equal-width histogram buckets.","schema":{"default":30,"type":"integer","minimum":5,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"mean_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"percentiles_sar":{"type":"object","properties":{"p10":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p25":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p75":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p90":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["p10","p25","p75","p90"],"additionalProperties":false,"description":"Price percentiles in SAR."},"range_sar":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"required":["min","max"],"additionalProperties":false},"buckets":{"type":"array","items":{"type":"object","properties":{"min_sar":{"type":"integer","description":"Inclusive lower bound."},"max_sar":{"type":"integer","description":"Exclusive upper bound."},"count":{"type":"integer"}},"required":["min_sar","max_sar","count"],"additionalProperties":false}},"below_range_count":{"type":"integer"},"above_range_count":{"type":"integer"},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","price_basis","sample_size","median_price_sar","mean_price_sar","percentiles_sar","range_sar","buckets","below_range_count","above_range_count","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"price_basis":"yearly_rent","sample_size":214,"median_price_sar":null,"mean_price_sar":null,"percentiles_sar":{"p10":null,"p25":null,"p75":null,"p90":null},"range_sar":{"min":0,"max":0},"buckets":[{"min_sar":0,"max_sar":0,"count":0}],"below_range_count":0,"above_range_count":0,"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/area-distribution":{"get":{"operationId":"market.area_distribution","summary":"Area distribution","description":"Histogram and percentiles of floor/plot area (m²) over listings in the sample that state an area (`without_area_count` did not). Buckets are equal-width from 0 to `range_sqm.max` (darak.app's area-slider maximum for the property type); larger listings are counted in `above_range_count` and still count toward the median and percentiles.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"bucket_count","in":"query","required":false,"description":"Number of equal-width histogram buckets.","schema":{"default":30,"type":"integer","minimum":5,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"sample_size":{"type":"integer","description":"Listings that state an area."},"without_area_count":{"type":"integer"},"median_area_sqm":{"anyOf":[{"type":"integer"},{"type":"null"}]},"mean_area_sqm":{"anyOf":[{"type":"integer"},{"type":"null"}]},"percentiles_sqm":{"type":"object","properties":{"p10":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p25":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p75":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p90":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["p10","p25","p75","p90"],"additionalProperties":false,"description":"Area percentiles in m²."},"range_sqm":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"required":["min","max"],"additionalProperties":false},"buckets":{"type":"array","items":{"type":"object","properties":{"min_sqm":{"type":"integer","description":"Inclusive lower bound."},"max_sqm":{"type":"integer","description":"Exclusive upper bound."},"count":{"type":"integer"}},"required":["min_sqm","max_sqm","count"],"additionalProperties":false}},"above_range_count":{"type":"integer"},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","sample_size","without_area_count","median_area_sqm","mean_area_sqm","percentiles_sqm","range_sqm","buckets","above_range_count","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"sample_size":0,"without_area_count":0,"median_area_sqm":null,"mean_area_sqm":null,"percentiles_sqm":{"p10":null,"p25":null,"p75":null,"p90":null},"range_sqm":{"min":0,"max":0},"buckets":[{"min_sqm":0,"max_sqm":0,"count":0}],"above_range_count":0,"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/supply":{"get":{"operationId":"market.supply","summary":"New supply","description":"How many listings came onto the market recently: listings first seen in the last 7 days vs the 7 days before, and the last 30 days vs the 30 days before (rolling windows ending now). Counts only include listings that are still live and in the sample, so listings taken down since are missing from the earlier periods: `change_pct` leans upward and is best compared between filters or over time, not read as absolute growth.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"sample_size":{"type":"integer","description":"All listings in the sample."},"last_7_days":{"type":"object","properties":{"new_listings":{"type":"integer","description":"Listings in the sample first seen by Darak in this period."},"previous_new_listings":{"type":"integer","description":"The same count for the period of equal length just before."},"change_pct":{"description":"Percent change from the previous period; null when it had none.","type":["number","null"]}},"required":["new_listings","previous_new_listings","change_pct"],"additionalProperties":false},"last_30_days":{"type":"object","properties":{"new_listings":{"type":"integer","description":"Listings in the sample first seen by Darak in this period."},"previous_new_listings":{"type":"integer","description":"The same count for the period of equal length just before."},"change_pct":{"description":"Percent change from the previous period; null when it had none.","type":["number","null"]}},"required":["new_listings","previous_new_listings","change_pct"],"additionalProperties":false},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","sample_size","last_7_days","last_30_days","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"sample_size":0,"last_7_days":{"new_listings":0,"previous_new_listings":0,"change_pct":0},"last_30_days":{"new_listings":0,"previous_new_listings":0,"change_pct":0},"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/vacancy":{"get":{"operationId":"market.vacancy","summary":"Vacancy indicator","description":"How long listings in the sample have been on the market, as a proxy for vacancy (actual occupancy isn't observed). Days on market count from when Darak first saw the listing: listings that were already up before then, or before Darak covered their source, are undercounted, and an ad re-posted under a new id starts again at zero. Compare these numbers between neighborhoods, property types or over time rather than reading them as absolute vacancy.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"sample_size":{"type":"integer","example":214},"median_days_on_market":{"anyOf":[{"type":"integer"},{"type":"null"}]},"on_market_over_30_days":{"type":"object","properties":{"count":{"type":"integer"},"pct":{"description":"Share of `sample_size`, in percent.","type":["number","null"]}},"required":["count","pct"],"additionalProperties":false},"on_market_over_60_days":{"type":"object","properties":{"count":{"type":"integer"},"pct":{"description":"Share of `sample_size`, in percent.","type":["number","null"]}},"required":["count","pct"],"additionalProperties":false},"on_market_over_90_days":{"type":"object","properties":{"count":{"type":"integer"},"pct":{"description":"Share of `sample_size`, in percent.","type":["number","null"]}},"required":["count","pct"],"additionalProperties":false},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","sample_size","median_days_on_market","on_market_over_30_days","on_market_over_60_days","on_market_over_90_days","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"sample_size":214,"median_days_on_market":null,"on_market_over_30_days":{"count":0,"pct":0},"on_market_over_60_days":{"count":0,"pct":0},"on_market_over_90_days":{"count":0,"pct":0},"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/neighborhoods":{"get":{"operationId":"market.neighborhoods","summary":"Prices by neighborhood","description":"Median and quartile price per neighborhood in a city, most expensive first. Neighborhoods with fewer than `min_sample_size` listings are left out (one unusual listing would swing their median); `suppressed_neighborhoods` says how many. Listings without a known neighborhood are not counted. Pass a `property_type` (and `beds`) for like-for-like comparisons; otherwise a neighborhood's median depends on its mix of apartments and villas.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for `listing_type=rent` (monthly, weekly and daily postings are converted to a yearly amount), total price for `listing_type=sale`. Check `sample_size` before relying on a number; small samples are noisy.","tags":["Market data"],"x-scope":"market","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"min_sample_size","in":"query","required":false,"description":"Leave out neighborhoods with fewer listings than this.","schema":{"default":5,"type":"integer","minimum":3,"maximum":1000}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"min_sample_size":{"type":"integer"},"neighborhoods":{"type":"array","items":{"type":"object","properties":{"neighborhood_id":{"type":"integer"},"name_ar":{"type":"string"},"name_en":{"type":"string"},"center":{"anyOf":[{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"],"additionalProperties":false},{"type":"null"}],"description":"Approximate centroid."},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]},"median_price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["neighborhood_id","name_ar","name_en","center","sample_size","median_price_sar","p25_price_sar","p75_price_sar","median_price_per_sqm_sar"],"additionalProperties":false}},"suppressed_neighborhoods":{"type":"integer"},"suppressed_sample_size":{"type":"integer","description":"Listings in the neighborhoods left out."},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results are cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window every market number uses."}},"required":["filters","price_basis","min_sample_size","neighborhoods","suppressed_neighborhoods","suppressed_sample_size","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"price_basis":"yearly_rent","min_sample_size":0,"neighborhoods":[{"neighborhood_id":0,"name_ar":"<name_ar>","name_en":"<name_en>","center":{"lat":0,"lng":0},"sample_size":214,"median_price_sar":null,"p25_price_sar":null,"p75_price_sar":null,"median_price_per_sqm_sar":null}],"suppressed_neighborhoods":0,"suppressed_sample_size":0,"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/{id}/comparables":{"get":{"operationId":"analytics.listing_comparables","summary":"Get comparable listings","description":"Active listings similar to this one, nearest first, with how each one differs.\n\nA comparable has the same city, listing type and property type, is within about 5 km, and has an area between 2/3 and 1.5 times this listing's (the comparison-approach caliper). Residential comparables also have the same bedroom count and must pass Darak's price, bedroom, area, property-type and location quality checks. Both this listing's and each comparable's area must be trustworthy, so listings without coordinates or with an unreliable area return no comparables and say why in `unavailable_reason`.\n\n`summary` describes the comparables returned (it depends on `limit`). Prices are asking prices in SAR: yearly rent for rentals (monthly, weekly and daily postings are converted to a yearly amount), total price for sales.","tags":["Analytics"],"x-scope":"analytics","x-units":3,"security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Listing id.","example":128647,"schema":{"type":"integer","minimum":1,"maximum":2147483647}},{"name":"limit","in":"query","required":false,"description":"How many comparables to return.","schema":{"default":20,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"listing_id":{"type":"integer"},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"unavailable_reason":{"anyOf":[{"type":"string","enum":["no_coordinates","unreliable_area"]},{"type":"null"}],"description":"Why no comparables could be searched for: the listing has no coordinates, or its area is missing or failed Darak's area checks. Null when the search ran."},"criteria":{"type":"object","properties":{"max_distance_m":{"type":"integer","example":5000},"area_range_sqm":{"anyOf":[{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"}},"required":["min","max"],"additionalProperties":false},{"type":"null"}],"description":"Area band comparables fall in."},"same_bedrooms":{"type":"boolean","description":"Whether comparables must match the bedroom count."}},"required":["max_distance_m","area_range_sqm","same_bedrooms"],"additionalProperties":false},"summary":{"type":"object","properties":{"sample_size":{"type":"integer","description":"Comparables returned.","example":24},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price of the comparables returned; null below 5.","example":52000},"listing_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"This listing's price."},"diff_from_median_pct":{"description":"This listing's price vs that median, in percent (negative = cheaper).","example":-8.5,"type":["number","null"]}},"required":["sample_size","median_price_sar","listing_price_sar","diff_from_median_pct"],"additionalProperties":false},"comparables":{"type":"array","items":{"type":"object","properties":{"listing":{"$ref":"#/components/schemas/Listing"},"similarity":{"type":"object","properties":{"distance_m":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Straight-line distance from this listing."},"area_diff_pct":{"description":"Comparable's area vs this listing's, in percent.","type":["number","null"]},"price_diff_pct":{"description":"Comparable's price vs this listing's, in percent.","type":["number","null"]}},"required":["distance_m","area_diff_pct","price_diff_pct"],"additionalProperties":false}},"required":["listing","similarity"],"additionalProperties":false}}},"required":["listing_id","price_basis","unavailable_reason","criteria","summary","comparables"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"listing_id":0,"price_basis":"yearly_rent","unavailable_reason":"no_coordinates","criteria":{"max_distance_m":5000,"area_range_sqm":{"min":0,"max":0},"same_bedrooms":true},"summary":{"sample_size":24,"median_price_sar":52000,"listing_price_sar":null,"diff_from_median_pct":-8.5},"comparables":[{"listing":{"id":128647,"url":"https://darak.app/en/listing/128647","title":"<title>","headline":"3-bedroom apartment for rent in Al Malqa, Riyadh","description":"<description>","description_en":"<description_en>","listing_type":"rent","listing_category":"residential","property_type":"apartment","price":{"yearly_sar":60000,"as_posted":{"amount":5000,"frequency":"monthly"},"previous_yearly_sar":66000,"changed_at":"2026-09-21T10:00:00.000Z"},"financing":{"rent_now_pay_later_monthly_sar":null,"accepts_bank_financing":true,"landlord_payment_plans":{"monthly":true,"quarterly":true,"semiannually":true}},"bedrooms":3,"bathrooms":2,"livings":1,"area_sqm":140,"floor":"2","age_years":4,"furnished":false,"amenities":["ac","kitchen","parking"],"location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":12,"neighborhood_name_ar":"الملقا","neighborhood_name_en":"Al Malqa","lat":24.7869,"lng":46.6215,"street_width_m":20},"compound_name":"Sedra","project_id":null,"images":["https://images.darak.app/listings/128647/1.webp"],"image_count":8,"advertiser":{"type":"agency"},"verified_by_source":true,"source":{"name":"aqar","listing_id":"7788123","url":"https://sa.aqar.fm/7788123"},"also_listed_on":["bayut"],"first_seen_at":"2026-09-21T10:00:00.000Z","updated_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z","days_on_market":null},"similarity":{"distance_m":null,"area_diff_pct":0,"price_diff_pct":0}}]}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/listings/{id}/market-position":{"get":{"operationId":"analytics.listing_market_position","summary":"Get a listing's market position","description":"Where a listing's price sits in its market: percentile, quartiles and difference from the median, against like-for-like listings in its neighborhood and in its city.\n\nThe cohort is listings with the same listing type, category and property type, and for residential listings the same bedroom count. `basis` says which cohort the top-level `price_percentile` and `diff_from_median_pct` use: the neighborhood when it has at least 30 listings, otherwise the city.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for rentals (monthly, weekly and daily postings are converted to a yearly amount), total price for sales. Medians and quartiles are null when fewer than 5 listings back them; check `sample_size` before relying on a number. `listing_in_sample` says whether the listing itself passed those filters (a listing not updated in 30 days, or priced as an outlier, is compared but not counted).","tags":["Analytics"],"x-scope":"analytics","x-units":2,"security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Listing id.","example":128647,"schema":{"type":"integer","minimum":1,"maximum":2147483647}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"listing_id":{"type":"integer"},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"This listing's price.","example":50000},"price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"This listing's price per m², when it states an area."},"cohort":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"anyOf":[{"type":"string","enum":["rent","sale"]},{"type":"null"}]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"basis":{"anyOf":[{"type":"string","enum":["neighborhood","city"]},{"type":"null"}],"description":"Which cohort the top-level percentile and difference come from. Null when no cohort could be computed (no price, or a city Darak doesn't cover)."},"price_percentile":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"From the `basis` cohort."},"diff_from_median_pct":{"description":"From the `basis` cohort.","type":["number","null"]},"neighborhood":{"anyOf":[{"type":"object","properties":{"sample_size":{"type":"integer","description":"Listings in the cohort.","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price of the cohort.","example":55000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile price."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile price."},"median_price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price per m², over cohort listings that state an area."},"price_percentile":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Share of the cohort priced below this listing (ties count half), 0-100. 20 means cheaper than 80% of the cohort.","example":38},"diff_from_median_pct":{"description":"This listing's price vs the cohort median, in percent (negative = cheaper).","example":-9.1,"type":["number","null"]},"neighborhood_id":{"type":"integer"},"name_en":{"type":["string","null"]},"name_ar":{"type":["string","null"]}},"required":["sample_size","median_price_sar","p25_price_sar","p75_price_sar","median_price_per_sqm_sar","price_percentile","diff_from_median_pct","neighborhood_id","name_en","name_ar"],"additionalProperties":false},{"type":"null"}],"description":"Null when the listing has no neighborhood, no price, or is in a city Darak doesn't cover."},"city":{"anyOf":[{"type":"object","properties":{"sample_size":{"type":"integer","description":"Listings in the cohort.","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price of the cohort.","example":55000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile price."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile price."},"median_price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price per m², over cohort listings that state an area."},"price_percentile":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Share of the cohort priced below this listing (ties count half), 0-100. 20 means cheaper than 80% of the cohort.","example":38},"diff_from_median_pct":{"description":"This listing's price vs the cohort median, in percent (negative = cheaper).","example":-9.1,"type":["number","null"]}},"required":["sample_size","median_price_sar","p25_price_sar","p75_price_sar","median_price_per_sqm_sar","price_percentile","diff_from_median_pct"],"additionalProperties":false},{"type":"null"}],"description":"Null when the listing has no price or is in a city Darak doesn't cover."},"listing_in_sample":{"type":"boolean"},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results may be cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window of the market sample."}},"required":["listing_id","price_basis","price_sar","price_per_sqm_sar","cohort","basis","price_percentile","diff_from_median_pct","neighborhood","city","listing_in_sample","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"listing_id":0,"price_basis":"yearly_rent","price_sar":50000,"price_per_sqm_sar":null,"cohort":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"basis":"neighborhood","price_percentile":null,"diff_from_median_pct":0,"neighborhood":{"sample_size":214,"median_price_sar":55000,"p25_price_sar":null,"p75_price_sar":null,"median_price_per_sqm_sar":null,"price_percentile":38,"diff_from_median_pct":-9.1,"neighborhood_id":0,"name_en":"<name_en>","name_ar":"<name_ar>"},"city":{"sample_size":214,"median_price_sar":55000,"p25_price_sar":null,"p75_price_sar":null,"median_price_per_sqm_sar":null,"price_percentile":38,"diff_from_median_pct":-9.1},"listing_in_sample":true,"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/deals":{"get":{"operationId":"analytics.deals","summary":"Find below-market listings","description":"Residential listings asking noticeably less than similar listings nearby, biggest gap first.\n\nEach listing is compared with Darak's published nearby asking-price comparison: the same property type and bedroom count, a similar area, within a calibrated radius and look-back (disclosed per listing in `comparison`), one observation per distinct unit, and the subject's own duplicates excluded. A listing appears only when the comparison is published for its cohort and its direction is stable under a 95% cluster bootstrap, so thin or noisy evidence never produces a deal. This is an asking-price comparison, not a valuation.\n\nListings are drawn from the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for rentals (monthly, weekly and daily postings are converted to a yearly amount), total price for sales. Paginate with `cursor`.","tags":["Analytics"],"x-scope":"analytics","x-units":"2 per 25 results asked for with `limit` (default 25), up to your plan's page size","security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"property_type","in":"query","required":false,"description":"One residential property type.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to one or more neighborhoods (comma-separated ids from GET /cities/{city}/neighborhoods). Unknown ids are a 404.","example":[1287,1301],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"min_discount_pct","in":"query","required":false,"description":"Minimum percent below the nearby median.","example":15,"schema":{"default":10,"type":"number","minimum":5,"maximum":90}},{"name":"max_discount_pct","in":"query","required":false,"description":"Maximum percent below the nearby median. Listings priced far below their neighbors are usually mispriced or mislabeled, so they're left out by default.","example":50,"schema":{"default":50,"type":"number","minimum":10,"maximum":95}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"listing":{"$ref":"#/components/schemas/Listing"},"comparison":{"type":"object","properties":{"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median asking price of the nearby comparables.","example":60000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile of the nearby comparables."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile of the nearby comparables."},"percent_vs_median":{"description":"This listing's price vs that median, in percent (negative = cheaper).","example":-18.4,"type":["number","null"]},"sample_size":{"type":"integer","description":"Distinct comparable units.","example":87},"radius_m":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Search radius used."},"look_back_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"How far back comparables were observed."}},"required":["median_price_sar","p25_price_sar","p75_price_sar","percent_vs_median","sample_size","radius_m","look_back_days"],"additionalProperties":false}},"required":["listing","comparison"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"listing":{"id":128647,"url":"https://darak.app/en/listing/128647","title":"<title>","headline":"3-bedroom apartment for rent in Al Malqa, Riyadh","description":"<description>","description_en":"<description_en>","listing_type":"rent","listing_category":"residential","property_type":"apartment","price":{"yearly_sar":60000,"as_posted":{"amount":5000,"frequency":"monthly"},"previous_yearly_sar":66000,"changed_at":"2026-09-21T10:00:00.000Z"},"financing":{"rent_now_pay_later_monthly_sar":null,"accepts_bank_financing":true,"landlord_payment_plans":{"monthly":true,"quarterly":true,"semiannually":true}},"bedrooms":3,"bathrooms":2,"livings":1,"area_sqm":140,"floor":"2","age_years":4,"furnished":false,"amenities":["ac","kitchen","parking"],"location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":12,"neighborhood_name_ar":"الملقا","neighborhood_name_en":"Al Malqa","lat":24.7869,"lng":46.6215,"street_width_m":20},"compound_name":"Sedra","project_id":null,"images":["https://images.darak.app/listings/128647/1.webp"],"image_count":8,"advertiser":{"type":"agency"},"verified_by_source":true,"source":{"name":"aqar","listing_id":"7788123","url":"https://sa.aqar.fm/7788123"},"also_listed_on":["bayut"],"first_seen_at":"2026-09-21T10:00:00.000Z","updated_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z","days_on_market":null},"comparison":{"median_price_sar":60000,"p25_price_sar":null,"p75_price_sar":null,"percent_vs_median":-18.4,"sample_size":87,"radius_m":null,"look_back_days":null}}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/rental-yield":{"get":{"operationId":"analytics.rental_yield","summary":"Get gross rental yield","description":"Gross rental yield (median yearly asking rent ÷ median asking sale price) for one property type, over the whole city (or the requested neighborhoods) and per neighborhood, highest yield first.\n\nRent and sale medians come from the same cohort (property type, and bedrooms if given) in the same area. Neighborhoods are listed only when both sides have at least `min_sample_size` listings. Gross yield ignores vacancy, service charges, maintenance and transaction costs, and compares asking prices, not achieved rents or sale prices; use it to rank areas, not to value a property.\n\nBoth sides use the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median).","tags":["Analytics"],"x-scope":"analytics","x-units":3,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"property_type","in":"query","required":true,"description":"Required, so rents and prices of different kinds of property are never mixed.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"Limit to these neighborhoods (comma-separated ids). Unknown ids are a 404.","example":[1287,1301],"schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"min_sample_size","in":"query","required":false,"description":"Minimum listings on each side for a yield to be computed.","schema":{"default":5,"type":"integer","minimum":5,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"anyOf":[{"type":"string","enum":["rent","sale"]},{"type":"null"}]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"overall":{"type":"object","properties":{"median_yearly_rent_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median yearly asking rent.","example":55000},"median_sale_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median asking sale price.","example":1150000},"gross_yield_pct":{"description":"median_yearly_rent_sar / median_sale_price_sar × 100.","example":4.78,"type":["number","null"]},"rent_sample_size":{"type":"integer","example":214},"sale_sample_size":{"type":"integer","example":214}},"required":["median_yearly_rent_sar","median_sale_price_sar","gross_yield_pct","rent_sample_size","sale_sample_size"],"additionalProperties":false,"description":"The city, or the requested neighborhoods together."},"neighborhoods":{"type":"array","items":{"type":"object","properties":{"median_yearly_rent_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median yearly asking rent.","example":55000},"median_sale_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median asking sale price.","example":1150000},"gross_yield_pct":{"description":"median_yearly_rent_sar / median_sale_price_sar × 100.","example":4.78,"type":["number","null"]},"rent_sample_size":{"type":"integer","example":214},"sale_sample_size":{"type":"integer","example":214},"neighborhood_id":{"type":"integer"},"name_en":{"type":["string","null"]},"name_ar":{"type":["string","null"]}},"required":["median_yearly_rent_sar","median_sale_price_sar","gross_yield_pct","rent_sample_size","sale_sample_size","neighborhood_id","name_en","name_ar"],"additionalProperties":false}},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results may be cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window of the market sample."}},"required":["filters","overall","neighborhoods","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"overall":{"median_yearly_rent_sar":55000,"median_sale_price_sar":1150000,"gross_yield_pct":4.78,"rent_sample_size":214,"sale_sample_size":214},"neighborhoods":[{"median_yearly_rent_sar":55000,"median_sale_price_sar":1150000,"gross_yield_pct":4.78,"rent_sample_size":214,"sale_sample_size":214,"neighborhood_id":0,"name_en":"<name_en>","name_ar":"<name_ar>"}],"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/trends":{"get":{"operationId":"analytics.trends","summary":"Get price trends","description":"Monthly median asking price over recent months, for a city or for up to five neighborhoods (one series each).\n\nComputed from Darak's listing history, not from today's listings: every listing Darak has recorded, including ones since rented, sold or removed, and every price change (the price in force at each point in time, not the current one).\n\n- `on_market` (default): a listing counts in a month if it was live at any point that month (first seen before the month ended, and still active or last seen on or after the month started), at the price it had at the end of the month, or when last seen if it went off the market earlier.\n- `new_listings`: a listing counts in the month Darak first saw it, at its first recorded asking price.\n\nListings are deduplicated across sources and pass the same outlier filter as the current market (fences are today's), but not the 30-day freshness window, which doesn't apply to history. Prices are asking prices in SAR: yearly rent for rentals (monthly, weekly and daily postings are converted to a yearly amount), total price for sales. Medians and quartiles are null when fewer than 5 listings back them; check `sample_size` before relying on a number.\n\nHistory starts in March 2026, and Darak added sources over time, so the earliest months under-cover the market and a change between months can reflect coverage as well as prices. The current month is marked `partial`.","tags":["Analytics"],"x-scope":"analytics","x-units":5,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":false,"description":"One series per neighborhood (comma-separated ids, up to 5). Omit for one city-wide series. Unknown ids are a 404.","example":[1287,1301],"schema":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"months","in":"query","required":false,"description":"Calendar months to return, ending with the current one.","schema":{"default":6,"type":"integer","minimum":2,"maximum":12}},{"name":"basis","in":"query","required":false,"description":"`on_market`: listings live during the month, at their price then. `new_listings`: listings first seen that month, at their first asking price.","schema":{"default":"on_market","type":"string","enum":["on_market","new_listings"]}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"anyOf":[{"type":"string","enum":["rent","sale"]},{"type":"null"}]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"basis":{"type":"string","enum":["on_market","new_listings"]},"series":{"type":"array","items":{"type":"object","properties":{"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Null for the city-wide series."},"name_en":{"type":["string","null"]},"name_ar":{"type":["string","null"]},"change_pct":{"description":"Change in median from the first to the last complete month that has a median, in percent. Excludes the partial current month.","example":2.3,"type":["number","null"]},"points":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","description":"YYYY-MM (UTC).","example":"2026-08"},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median asking price.","example":45000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile."},"partial":{"type":"boolean","description":"True for the current, unfinished month."}},"required":["month","sample_size","median_price_sar","p25_price_sar","p75_price_sar","partial"],"additionalProperties":false}}},"required":["neighborhood_id","name_en","name_ar","change_pct","points"],"additionalProperties":false}},"methodology":{"type":"string","description":"How the numbers were computed."}},"required":["filters","price_basis","basis","series","methodology"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"price_basis":"yearly_rent","basis":"on_market","series":[{"neighborhood_id":null,"name_en":"<name_en>","name_ar":"<name_ar>","change_pct":2.3,"points":[{"month":"2026-08","sample_size":214,"median_price_sar":45000,"p25_price_sar":null,"p75_price_sar":null,"partial":true}]}],"methodology":"<methodology>"}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/market/neighborhoods/compare":{"get":{"operationId":"analytics.neighborhoods_compare","summary":"Compare neighborhoods","description":"Side-by-side profile of 2 to 5 neighborhoods: price quartiles, area, price per m², amenity shares, bedroom and property-type mix, and for rentals the gross yield against the same cohort's sale prices. Neighborhoods come back in the order requested, including ones with no listings in the sample.\n\nComputed over the market sample: active, deduplicated listings updated in the last 30 days (`updated_at`), after the same outlier filter darak.app uses (per-tier price fences from the median and MAD of log price, bedroom and area sanity checks, and a floor at 30% of the neighborhood median). Prices are asking prices in SAR: yearly rent for rentals (monthly, weekly and daily postings are converted to a yearly amount), total price for sales. Medians and quartiles are null when fewer than 5 listings back them; check `sample_size` before relying on a number.","tags":["Analytics"],"x-scope":"analytics","x-units":3,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":true,"description":"City slug from GET /cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"listing_type","in":"query","required":true,"description":"`rent` (prices are yearly rent) or `sale` (prices are total price).","schema":{"type":"string","enum":["rent","sale"]}},{"name":"listing_category","in":"query","required":false,"description":"Defaults to `residential` when `property_type` is omitted, so dwellings and commercial stock are never mixed into one median. With a `property_type`, omit it to include both categories of that type.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"property_type","in":"query","required":false,"description":"One property type, see GET /enums.","example":"apartment","schema":{"type":"string","enum":["apartment","villa","floor","duplex","office","shop","warehouse","land","building"]}},{"name":"beds","in":"query","required":false,"description":"Exact number of bedrooms (0 = studio).","example":2,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"neighborhood_id","in":"query","required":true,"description":"2 to 5 comma-separated neighborhood ids from GET /cities/{city}/neighborhoods. Unknown ids are a 404.","example":[1287,1301],"schema":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"filters":{"type":"object","properties":{"city":{"type":"string","example":"riyadh"},"listing_type":{"anyOf":[{"type":"string","enum":["rent","sale"]},{"type":"null"}]},"listing_category":{"anyOf":[{"type":"string","enum":["residential","commercial"]},{"type":"null"}],"description":"The category applied; null when both are included."},"property_type":{"type":["string","null"]},"neighborhood_ids":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"example":[12]},"beds":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["city","listing_type","listing_category","property_type","neighborhood_ids","beds"],"additionalProperties":false,"description":"The filters the numbers were computed for, after defaults."},"price_basis":{"type":"string","enum":["yearly_rent","sale_price"],"description":"What the `*_sar` price fields mean: `yearly_rent` (SAR per year) for rentals, `sale_price` (total SAR) for sales."},"neighborhoods":{"type":"array","items":{"type":"object","properties":{"neighborhood_id":{"type":"integer"},"name_en":{"type":"string"},"name_ar":{"type":"string"},"sample_size":{"type":"integer","example":214},"median_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median price.","example":48000},"p25_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"25th percentile price."},"p75_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"75th percentile price."},"median_area_sqm":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median area in m², over listings that state an area."},"median_price_per_sqm_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Median of each listing's price divided by its area."},"amenity_share_pct":{"type":"object","properties":{"ac":{"description":"Percent of the neighborhood's sample.","type":["number","null"]},"parking":{"description":"Percent of the neighborhood's sample.","type":["number","null"]},"pool":{"description":"Percent of the neighborhood's sample.","type":["number","null"]},"lift":{"description":"Percent of the neighborhood's sample.","type":["number","null"]},"furnished":{"description":"Percent of the neighborhood's sample.","type":["number","null"]}},"required":["ac","parking","pool","lift","furnished"],"additionalProperties":false},"bedrooms_mix":{"type":"object","properties":{"0":{"type":"integer"},"1":{"type":"integer"},"2":{"type":"integer"},"3":{"type":"integer"},"4":{"type":"integer"},"5_plus":{"type":"integer"}},"required":["0","1","2","3","4","5_plus"],"additionalProperties":false,"description":"Listings by bedroom count."},"property_type_mix":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer"},"description":"Listings by property type.","example":{"apartment":120}},"median_sale_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Rentals only: median asking sale price of the same cohort in the neighborhood."},"sale_sample_size":{"description":"Rentals only.","example":96,"type":"integer"},"gross_yield_pct":{"description":"Rentals only: median_price_sar / median_sale_price_sar × 100.","type":["number","null"]}},"required":["neighborhood_id","name_en","name_ar","sample_size","median_price_sar","p25_price_sar","p75_price_sar","median_area_sqm","median_price_per_sqm_sar","amenity_share_pct","bedrooms_mix","property_type_mix"],"additionalProperties":false}},"window":{"type":"object","properties":{"updated_within_days":{"type":"integer","example":30},"from":{"type":"string","description":"Listings updated at or after this time are included (ISO 8601).","example":"2026-08-23T09:00:00.000Z"},"to":{"type":"string","description":"When the numbers were computed (ISO 8601). Results may be cached up to an hour.","example":"2026-09-22T09:00:00.000Z"}},"required":["updated_within_days","from","to"],"additionalProperties":false,"description":"The freshness window of the market sample."}},"required":["filters","price_basis","neighborhoods","window"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"filters":{"city":"riyadh","listing_type":"rent","listing_category":"residential","property_type":"<property_type>","neighborhood_ids":[12],"beds":null},"price_basis":"yearly_rent","neighborhoods":[{"neighborhood_id":0,"name_en":"<name_en>","name_ar":"<name_ar>","sample_size":214,"median_price_sar":48000,"p25_price_sar":null,"p75_price_sar":null,"median_area_sqm":null,"median_price_per_sqm_sar":null,"amenity_share_pct":{"ac":0,"parking":0,"pool":0,"lift":0,"furnished":0},"bedrooms_mix":{"0":0,"1":0,"2":0,"3":0,"4":0,"5_plus":0},"property_type_mix":{"apartment":120},"median_sale_price_sar":null,"sale_sample_size":96,"gross_yield_pct":0}],"window":{"updated_within_days":30,"from":"2026-08-23T09:00:00.000Z","to":"2026-09-22T09:00:00.000Z"}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects":{"get":{"operationId":"projects.search","summary":"Search projects","description":"Off-plan and newly built residential and commercial projects from Saudi developers and portals, one entry per project (copies from several sources are merged). Prices are developer-advertised purchase prices in SAR. Paginate with `cursor`.","tags":["Off-plan projects"],"x-scope":"projects","x-units":"1 per 25 results asked for with `limit` (default 25), up to your plan's page size","security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":false,"description":"Omit for all cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"neighborhood_id","in":"query","required":false,"description":"Neighborhood ids from GET /cities/{city}/neighborhoods. Only projects mapped to a neighborhood match.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"developer","in":"query","required":false,"description":"Exact developer name, as returned by GET /developers.","example":"Retal Urban Development","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"status","in":"query","required":false,"description":"One or more, comma-separated.","example":["available","under_construction"],"schema":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["available","coming_soon","not_started","under_construction","completed","sold_out"]}},"style":"form","explode":false},{"name":"project_type","in":"query","required":false,"schema":{"type":"string","enum":["off_plan","ready"]}},{"name":"listing_category","in":"query","required":false,"description":"Omit for both.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"features","in":"query","required":false,"description":"Only projects with all of these, see GET /enums.","example":["pool","gym"],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"banks","in":"query","required":false,"description":"Only projects financed by all of these, see GET /enums.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"q","in":"query","required":false,"description":"Matches project or developer name (Arabic or English), case-insensitive.","example":"Sedra","schema":{"type":"string","minLength":2,"maxLength":100}},{"name":"price_min","in":"query","required":false,"description":"Minimum starting price, SAR. Projects without a published price are excluded.","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"price_max","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"sort","in":"query","required":false,"description":"`updated_desc` (most recently refreshed), `price_asc`/`price_desc` (by starting price, projects without one last).","schema":{"default":"updated_desc","type":"string","enum":["updated_desc","price_asc","price_desc"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":4812},"url":{"description":"The project's page on darak.app.","type":["string","null"]},"name_ar":{"example":"مشروع سدرة","type":["string","null"]},"name_en":{"example":"Sedra","type":["string","null"]},"developer":{"description":"Developer name as published. Pass as `developer` to filter; see GET /developers.","example":"Retal Urban Development","type":["string","null"]},"status":{"anyOf":[{"type":"string","enum":["available","coming_soon","not_started","under_construction","completed","sold_out"]},{"type":"null"}],"description":"Sales/construction status. Null when the source doesn't say."},"project_type":{"anyOf":[{"type":"string","enum":["off_plan","ready"]},{"type":"null"}],"description":"`off_plan` (sold before completion) or `ready`. Null when unknown."},"listing_category":{"type":"string","example":"residential"},"location":{"type":"object","properties":{"city":{"description":"City slug (see GET /cities).","example":"riyadh","type":["string","null"]},"city_name_en":{"example":"Riyadh","type":["string","null"]},"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"See GET /cities/{city}/neighborhoods. Not every project is mapped to a neighborhood yet."},"neighborhood_name_ar":{"type":["string","null"]},"neighborhood_name_en":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["city","city_name_en","neighborhood_id","neighborhood_name_ar","neighborhood_name_en","lat","lng"],"additionalProperties":false},"price":{"type":"object","properties":{"starting_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Lowest advertised purchase price in SAR (a sale price, not a rent).","example":850000},"from_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Lower end of the advertised price range, SAR."},"to_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Upper end of the advertised price range, SAR."}},"required":["starting_sar","from_sar","to_sar"],"additionalProperties":false,"description":"Developer-advertised purchase prices in SAR (total price, not yearly). Null when not published or implausibly low."},"area_sqm":{"type":"object","properties":{"min":{"type":["number","null"]},"max":{"type":["number","null"]}},"required":["min","max"],"additionalProperties":false,"description":"Advertised unit size range in square meters."},"advertised_unit_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Total units in the project, as the developer advertises it."},"linked_units":{"type":"object","properties":{"count":{"type":"integer","description":"Active listings on Darak linked to this project (see GET /projects/{id}/units). Usually far fewer than `advertised_unit_count`."},"bedrooms_min":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bedrooms_max":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["count","bedrooms_min","bedrooms_max"],"additionalProperties":false},"cover_image":{"description":"First image on Darak's CDN, if mirrored.","type":["string","null"]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"Last time Darak refreshed the project from its source."}},"required":["id","url","name_ar","name_en","developer","status","project_type","listing_category","location","price","area_sqm","advertised_unit_count","linked_units","cover_image","last_seen_at"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"id":4812,"url":"<url>","name_ar":"مشروع سدرة","name_en":"Sedra","developer":"Retal Urban Development","status":"available","project_type":"off_plan","listing_category":"residential","location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":null,"neighborhood_name_ar":"<neighborhood_name_ar>","neighborhood_name_en":"<neighborhood_name_en>","lat":0,"lng":0},"price":{"starting_sar":850000,"from_sar":null,"to_sar":null},"area_sqm":{"min":0,"max":0},"advertised_unit_count":null,"linked_units":{"count":0,"bedrooms_min":null,"bedrooms_max":null},"cover_image":"<cover_image>","last_seen_at":"2026-09-21T10:00:00.000Z"}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{id}":{"get":{"operationId":"projects.get","summary":"Get a project","description":"One project with its description, boundary, amenities, financing banks and a summary of the units listed on Darak. Page through the units with GET /projects/{id}/units. Returns 404 for inactive projects and for copies merged into another project.","tags":["Off-plan projects"],"x-scope":"projects","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Project id.","example":4812,"schema":{"type":"integer","minimum":1,"maximum":2147483647}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"integer","example":4812},"url":{"description":"The project's page on darak.app.","type":["string","null"]},"name_ar":{"example":"مشروع سدرة","type":["string","null"]},"name_en":{"example":"Sedra","type":["string","null"]},"developer":{"description":"Developer name as published. Pass as `developer` to filter; see GET /developers.","example":"Retal Urban Development","type":["string","null"]},"status":{"anyOf":[{"type":"string","enum":["available","coming_soon","not_started","under_construction","completed","sold_out"]},{"type":"null"}],"description":"Sales/construction status. Null when the source doesn't say."},"project_type":{"anyOf":[{"type":"string","enum":["off_plan","ready"]},{"type":"null"}],"description":"`off_plan` (sold before completion) or `ready`. Null when unknown."},"listing_category":{"type":"string","example":"residential"},"location":{"type":"object","properties":{"city":{"description":"City slug (see GET /cities).","example":"riyadh","type":["string","null"]},"city_name_en":{"example":"Riyadh","type":["string","null"]},"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"See GET /cities/{city}/neighborhoods. Not every project is mapped to a neighborhood yet."},"neighborhood_name_ar":{"type":["string","null"]},"neighborhood_name_en":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["city","city_name_en","neighborhood_id","neighborhood_name_ar","neighborhood_name_en","lat","lng"],"additionalProperties":false},"price":{"type":"object","properties":{"starting_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Lowest advertised purchase price in SAR (a sale price, not a rent).","example":850000},"from_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Lower end of the advertised price range, SAR."},"to_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Upper end of the advertised price range, SAR."}},"required":["starting_sar","from_sar","to_sar"],"additionalProperties":false,"description":"Developer-advertised purchase prices in SAR (total price, not yearly). Null when not published or implausibly low."},"area_sqm":{"type":"object","properties":{"min":{"type":["number","null"]},"max":{"type":["number","null"]}},"required":["min","max"],"additionalProperties":false,"description":"Advertised unit size range in square meters."},"advertised_unit_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Total units in the project, as the developer advertises it."},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"Last time Darak refreshed the project from its source."},"description":{"description":"As published (usually Arabic).","type":["string","null"]},"description_en":{"type":["string","null"]},"address":{"type":["string","null"]},"boundary":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["Polygon","MultiPolygon"]},"coordinates":{"type":"array","items":{}}},"required":["type","coordinates"],"additionalProperties":false},{"type":"null"}],"description":"Project boundary as GeoJSON ([lng, lat] order), where published."},"images":{"type":"array","items":{"type":"string"},"description":"Image URLs on Darak's CDN."},"features":{"type":"array","items":{"type":"string"},"description":"Amenities, as stable ids.","example":["elevator","parking","smart_home"]},"supported_banks":{"type":"array","items":{"type":"string"},"description":"Banks the developer lists for mortgage financing.","example":["alrajhi","alahli"]},"warranty":{"type":"array","items":{"type":"object","properties":{"item":{"type":"string"},"duration":{"type":["string","null"]}},"required":["item","duration"],"additionalProperties":false},"description":"Warranties the developer offers, e.g. `{ item: \"plumbing\", duration: \"5\" }`. `duration` is as published, usually years."},"links":{"type":"object","properties":{"brochure":{"type":["string","null"]},"virtual_tour":{"type":["string","null"]},"video":{"type":["string","null"]}},"required":["brochure","virtual_tour","video"],"additionalProperties":false},"source":{"type":"object","properties":{"name":{"type":"string","example":"wafi"},"url":{"description":"The original page. Attribution is required, see the terms.","type":["string","null"]}},"required":["name","url"],"additionalProperties":false},"linked_units":{"type":"object","properties":{"count":{"type":"integer"},"for_sale":{"type":"integer"},"for_rent":{"type":"integer"},"bedrooms_min":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bedrooms_max":{"anyOf":[{"type":"integer"},{"type":"null"}]},"area_sqm_min":{"type":["number","null"]},"area_sqm_max":{"type":["number","null"]},"sale_price_sar_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Cheapest linked unit for sale, SAR."},"sale_price_sar_max":{"anyOf":[{"type":"integer"},{"type":"null"}]},"yearly_rent_sar_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Cheapest linked rental, SAR per year."},"yearly_rent_sar_max":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["count","for_sale","for_rent","bedrooms_min","bedrooms_max","area_sqm_min","area_sqm_max","sale_price_sar_min","sale_price_sar_max","yearly_rent_sar_min","yearly_rent_sar_max"],"additionalProperties":false,"description":"Summary of the active listings linked to this project. Page through them with GET /projects/{id}/units."}},"required":["id","url","name_ar","name_en","developer","status","project_type","listing_category","location","price","area_sqm","advertised_unit_count","last_seen_at","description","description_en","address","boundary","images","features","supported_banks","warranty","links","source","linked_units"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":4812,"url":"<url>","name_ar":"مشروع سدرة","name_en":"Sedra","developer":"Retal Urban Development","status":"available","project_type":"off_plan","listing_category":"residential","location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":null,"neighborhood_name_ar":"<neighborhood_name_ar>","neighborhood_name_en":"<neighborhood_name_en>","lat":0,"lng":0},"price":{"starting_sar":850000,"from_sar":null,"to_sar":null},"area_sqm":{"min":0,"max":0},"advertised_unit_count":null,"last_seen_at":"2026-09-21T10:00:00.000Z","description":"<description>","description_en":"<description_en>","address":"<address>","boundary":{"type":"Polygon","coordinates":[null]},"images":["<images>"],"features":["elevator","parking","smart_home"],"supported_banks":["alrajhi","alahli"],"warranty":[{"item":"<item>","duration":"<duration>"}],"links":{"brochure":"<brochure>","virtual_tour":"<virtual_tour>","video":"<video>"},"source":{"name":"wafi","url":"<url>"},"linked_units":{"count":0,"for_sale":0,"for_rent":0,"bedrooms_min":null,"bedrooms_max":null,"area_sqm_min":0,"area_sqm_max":0,"sale_price_sar_min":null,"sale_price_sar_max":null,"yearly_rent_sar_min":null,"yearly_rent_sar_max":null}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/projects/{id}/units":{"get":{"operationId":"projects.units","summary":"List a project's units","description":"Active listings on Darak linked to one project: units for sale (total price) and, for some projects, rentals (yearly rent). Units priced implausibly low for their city are left out. Returns 404 if the project isn't active.","tags":["Off-plan projects"],"x-scope":"projects","x-units":"1 per 25 results asked for with `limit` (default 25), up to your plan's page size","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Project id.","example":4812,"schema":{"type":"integer","minimum":1,"maximum":2147483647}},{"name":"listing_type","in":"query","required":false,"description":"Omit for both. Most project units are for sale; some are rentals.","schema":{"type":"string","enum":["sale","rent"]}},{"name":"property_type","in":"query","required":false,"description":"One or more, comma-separated.","example":["apartment","villa"],"schema":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["apartment","villa","floor","land","building","office","shop"]}},"style":"form","explode":false},{"name":"bedrooms","in":"query","required":false,"description":"Exact number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bedrooms_min","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bedrooms_max","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms","in":"query","required":false,"description":"Exact number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_min","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"price_min","in":"query","required":false,"description":"SAR. Compared with `sale_price_sar` for sales and `yearly_rent_sar` for rentals; set `listing_type` to keep them apart.","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"price_max","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"area_min","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"area_max","in":"query","required":false,"schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"sort","in":"query","required":false,"description":"`price_asc`/`price_desc` (by SAR amount; sales and yearly rents sort together unless you set `listing_type`), `newest` (first seen by Darak), `area_desc`, `bedrooms_desc`.","schema":{"default":"price_asc","type":"string","enum":["price_asc","price_desc","newest","area_desc","bedrooms_desc"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Listing id; GET /listings/{id} returns the full listing (with the `listings` scope).","example":128647},"url":{"type":"string","description":"The listing's page on darak.app."},"project":{"type":"object","properties":{"id":{"type":"integer"},"name_ar":{"type":["string","null"]},"name_en":{"type":["string","null"]}},"required":["id","name_ar","name_en"],"additionalProperties":false},"link":{"type":"object","properties":{"type":{"type":"string","example":"source"},"confidence":{"type":"number"}},"required":["type","confidence"],"additionalProperties":false,"description":"How the listing was tied to the project: `source` (the source says so, confidence 1), `geo` (inside or next to the project's boundary) or `text` (project named in the ad). New types may be added."},"title":{"type":["string","null"]},"listing_type":{"type":"string","enum":["sale","rent"]},"property_type":{"type":"string","example":"apartment"},"sale_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Total purchase price in SAR. Null for rentals.","example":980000},"yearly_rent_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Rent in SAR per year (monthly and daily postings normalized to yearly). Null for units for sale."},"bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bathrooms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"area_sqm":{"type":["number","null"]},"floor":{"type":["string","null"]},"location":{"type":"object","properties":{"city":{"description":"City slug (see GET /cities).","example":"riyadh","type":["string","null"]},"city_name_en":{"example":"Riyadh","type":["string","null"]},"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"See GET /cities/{city}/neighborhoods. Not every project is mapped to a neighborhood yet."},"neighborhood_name_ar":{"type":["string","null"]},"neighborhood_name_en":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["city","city_name_en","neighborhood_id","neighborhood_name_ar","neighborhood_name_en","lat","lng"],"additionalProperties":false},"images":{"type":"array","items":{"type":"string"},"description":"Up to three image URLs on Darak's CDN."},"source":{"type":"object","properties":{"name":{"type":"string"},"url":{"description":"The original ad. Attribution is required, see the terms.","type":["string","null"]}},"required":["name","url"],"additionalProperties":false},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]}},"required":["id","url","project","link","title","listing_type","property_type","sale_price_sar","yearly_rent_sar","bedrooms","bathrooms","area_sqm","floor","location","images","source","first_seen_at","last_seen_at"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"id":128647,"url":"<url>","project":{"id":0,"name_ar":"<name_ar>","name_en":"<name_en>"},"link":{"type":"source","confidence":0},"title":"<title>","listing_type":"sale","property_type":"apartment","sale_price_sar":980000,"yearly_rent_sar":null,"bedrooms":null,"bathrooms":null,"area_sqm":0,"floor":"<floor>","location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":null,"neighborhood_name_ar":"<neighborhood_name_ar>","neighborhood_name_en":"<neighborhood_name_en>","lat":0,"lng":0},"images":["<images>"],"source":{"name":"<name>","url":"<url>"},"first_seen_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z"}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/project-units":{"get":{"operationId":"projects.units_search","summary":"Search project units","description":"Units across all projects: active listings linked to a project, filtered by the unit (bedrooms, price, area) and by its project (city, developer, status). A listing linked to several projects appears once, under its strongest link. Units priced implausibly low for their city (installments, typos) are left out.","tags":["Off-plan projects"],"x-scope":"projects","x-units":"1 per 25 results asked for with `limit` (default 25), up to your plan's page size","security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":false,"description":"Omit for all cities.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"neighborhood_id","in":"query","required":false,"description":"Neighborhood ids from GET /cities/{city}/neighborhoods; matches the unit's neighborhood, or its project's when the unit has none.","schema":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","minimum":1,"maximum":2147483647}},"style":"form","explode":false},{"name":"developer","in":"query","required":false,"description":"Exact developer name, as returned by GET /developers.","example":"Retal Urban Development","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"status","in":"query","required":false,"description":"One or more, comma-separated.","example":["available","under_construction"],"schema":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["available","coming_soon","not_started","under_construction","completed","sold_out"]}},"style":"form","explode":false},{"name":"project_type","in":"query","required":false,"schema":{"type":"string","enum":["off_plan","ready"]}},{"name":"listing_category","in":"query","required":false,"description":"Omit for both.","schema":{"type":"string","enum":["residential","commercial"]}},{"name":"features","in":"query","required":false,"description":"Only projects with all of these, see GET /enums.","example":["pool","gym"],"schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"banks","in":"query","required":false,"description":"Only projects financed by all of these, see GET /enums.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","pattern":"^[a-z_]+$"}},"style":"form","explode":false},{"name":"listing_type","in":"query","required":false,"description":"Omit for both. Most project units are for sale; some are rentals.","schema":{"type":"string","enum":["sale","rent"]}},{"name":"property_type","in":"query","required":false,"description":"One or more, comma-separated.","example":["apartment","villa"],"schema":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["apartment","villa","floor","land","building","office","shop"]}},"style":"form","explode":false},{"name":"bedrooms","in":"query","required":false,"description":"Exact number of bedrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bedrooms_min","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bedrooms_max","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms","in":"query","required":false,"description":"Exact number of bathrooms.","schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"bathrooms_min","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":20}},{"name":"price_min","in":"query","required":false,"description":"SAR. Compared with `sale_price_sar` for sales and `yearly_rent_sar` for rentals; set `listing_type` to keep them apart.","schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"price_max","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":2000000000}},{"name":"area_min","in":"query","required":false,"description":"Square meters.","schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"area_max","in":"query","required":false,"schema":{"type":"number","minimum":0,"maximum":10000000}},{"name":"sort","in":"query","required":false,"description":"`price_asc`/`price_desc` (by SAR amount; sales and yearly rents sort together unless you set `listing_type`), `newest` (first seen by Darak), `area_desc`, `bedrooms_desc`.","schema":{"default":"newest","type":"string","enum":["price_asc","price_desc","newest","area_desc","bedrooms_desc"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Listing id; GET /listings/{id} returns the full listing (with the `listings` scope).","example":128647},"url":{"type":"string","description":"The listing's page on darak.app."},"project":{"type":"object","properties":{"id":{"type":"integer"},"name_ar":{"type":["string","null"]},"name_en":{"type":["string","null"]}},"required":["id","name_ar","name_en"],"additionalProperties":false},"link":{"type":"object","properties":{"type":{"type":"string","example":"source"},"confidence":{"type":"number"}},"required":["type","confidence"],"additionalProperties":false,"description":"How the listing was tied to the project: `source` (the source says so, confidence 1), `geo` (inside or next to the project's boundary) or `text` (project named in the ad). New types may be added."},"title":{"type":["string","null"]},"listing_type":{"type":"string","enum":["sale","rent"]},"property_type":{"type":"string","example":"apartment"},"sale_price_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Total purchase price in SAR. Null for rentals.","example":980000},"yearly_rent_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Rent in SAR per year (monthly and daily postings normalized to yearly). Null for units for sale."},"bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bathrooms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"area_sqm":{"type":["number","null"]},"floor":{"type":["string","null"]},"location":{"type":"object","properties":{"city":{"description":"City slug (see GET /cities).","example":"riyadh","type":["string","null"]},"city_name_en":{"example":"Riyadh","type":["string","null"]},"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"See GET /cities/{city}/neighborhoods. Not every project is mapped to a neighborhood yet."},"neighborhood_name_ar":{"type":["string","null"]},"neighborhood_name_en":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["city","city_name_en","neighborhood_id","neighborhood_name_ar","neighborhood_name_en","lat","lng"],"additionalProperties":false},"images":{"type":"array","items":{"type":"string"},"description":"Up to three image URLs on Darak's CDN."},"source":{"type":"object","properties":{"name":{"type":"string"},"url":{"description":"The original ad. Attribution is required, see the terms.","type":["string","null"]}},"required":["name","url"],"additionalProperties":false},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]}},"required":["id","url","project","link","title","listing_type","property_type","sale_price_sar","yearly_rent_sar","bedrooms","bathrooms","area_sqm","floor","location","images","source","first_seen_at","last_seen_at"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"id":128647,"url":"<url>","project":{"id":0,"name_ar":"<name_ar>","name_en":"<name_en>"},"link":{"type":"source","confidence":0},"title":"<title>","listing_type":"sale","property_type":"apartment","sale_price_sar":980000,"yearly_rent_sar":null,"bedrooms":null,"bathrooms":null,"area_sqm":0,"floor":"<floor>","location":{"city":"riyadh","city_name_en":"Riyadh","neighborhood_id":null,"neighborhood_name_ar":"<neighborhood_name_ar>","neighborhood_name_en":"<neighborhood_name_en>","lat":0,"lng":0},"images":["<images>"],"source":{"name":"<name>","url":"<url>"},"first_seen_at":"2026-09-21T10:00:00.000Z","last_seen_at":"2026-09-21T10:00:00.000Z"}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/developers":{"get":{"operationId":"projects.developers","summary":"List developers","description":"Developers with active projects on Darak, most projects first. Developers are identified by name as their projects publish it; the same company can appear under an Arabic and an English spelling.","tags":["Off-plan projects"],"x-scope":"projects","x-units":1,"security":[{"apiKey":[]}],"parameters":[{"name":"city","in":"query","required":false,"description":"Only developers with projects in this city.","example":"riyadh","schema":{"type":"string","pattern":"^[a-z_]+$"}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Units allowed per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Units left this minute.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the minute window resets.","schema":{"type":"integer"}},"X-Request-Units":{"description":"Units this request cost.","schema":{"type":"integer"}},"X-Quota-Limit":{"description":"Units allowed this calendar month (UTC). Absent on unlimited plans.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Units left this calendar month (UTC). Absent on unlimited plans. Reads `0` once a plan with overage is past its quota and still serving.","schema":{"type":"integer"}},"X-Quota-Reset":{"description":"Seconds until the monthly quota resets. Absent on unlimited plans.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"As published. Pass as `developer` to GET /projects and GET /project-units.","example":"Retal Urban Development"},"project_count":{"type":"integer","description":"Active projects on Darak."},"active_project_count":{"type":"integer","description":"Projects whose status is available, coming_soon, not_started or under_construction."},"cities":{"type":"array","items":{"type":"string"},"description":"City slugs.","example":["riyadh","jeddah"]}},"required":["name","project_count","active_project_count","cities"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"name":"Retal Urban Development","project_count":0,"active_project_count":0,"cities":["riyadh","jeddah"]}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization":{"get":{"operationId":"organization.get","summary":"Get your organization","description":"Name, plan and limits, and this month's usage.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"status":{"type":"string","enum":["active","suspended"]},"plan":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"rate_limit_per_minute":{"type":"integer"},"monthly_quota_units":{"anyOf":[{"type":"integer"},{"type":"null"}]},"max_page_size":{"type":"integer"},"max_active_keys":{"type":"integer"}},"required":["id","name","scopes","rate_limit_per_minute","monthly_quota_units","max_page_size","max_active_keys"],"additionalProperties":false},"usage":{"type":"object","properties":{"month_units":{"type":"integer"},"resets_in_seconds":{"type":"integer"}},"required":["month_units","resets_in_seconds"],"additionalProperties":false}},"required":["id","name","slug","status","plan","usage"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":"<id>","name":"<name>","slug":"<slug>","status":"active","plan":{"id":"<id>","name":"<name>","scopes":["<scopes>"],"rate_limit_per_minute":0,"monthly_quota_units":null,"max_page_size":0,"max_active_keys":0},"usage":{"month_units":0,"resets_in_seconds":0}}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/keys":{"get":{"operationId":"organization.keys.list","summary":"List data keys","description":"Active data keys (`dk_live_…`). Secrets are never returned after creation.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"key_7Fh2kQ9cV1xZ3mB8nL0p"},"name":{"type":"string"},"hint":{"type":"string","description":"Last characters of the key","example":"dk_live_…a1b2"},"project_id":{"type":"string"},"scopes":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"APIs the key may call; null = every API on the plan."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"},{"type":"null"}],"description":"Updated at most hourly."}},"required":["id","name","hint","project_id","scopes","expires_at","created_at","last_used_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"key_7Fh2kQ9cV1xZ3mB8nL0p","name":"<name>","hint":"dk_live_…a1b2","project_id":"<project_id>","scopes":["<scopes>"],"expires_at":"2026-09-21T10:00:00.000Z","created_at":"2026-09-21T10:00:00.000Z","last_used_at":"2026-09-21T10:00:00.000Z"}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"organization.keys.create","summary":"Create a data key","description":"Creates a `dk_live_…` key. The secret is in the response once: store it now. Counts toward your plan's active-key limit.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A unique string (a UUID is ideal) making this call safe to retry. The same key with the same body replays the first response and sets `Idempotent-Replay: true`; with a different body it returns `409 idempotency_key_reuse`. Remembered for 24 hours.","schema":{"type":"string","maxLength":255},"example":"8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"project_id":{"description":"Defaults to your first project.","type":"string","maxLength":64},"scopes":{"description":"Limit the key to these APIs; omit for every API on your plan.","maxItems":20,"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["name"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string","description":"The secret. Shown once."},"hint":{"type":"string"}},"required":["id","name","key","hint"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":"<id>","name":"<name>","key":"<key>","hint":"<hint>"}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Clashes with the current state, or an `Idempotency-Key` was reused with a different body.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/keys/{key_id}/revoke":{"post":{"operationId":"organization.keys.revoke","summary":"Revoke a key","description":"Requests with the key are rejected right away. An admin key can revoke itself.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","maxLength":64}},{"name":"Idempotency-Key","in":"header","required":false,"description":"A unique string (a UUID is ideal) making this call safe to retry. The same key with the same body replays the first response and sets `Idempotent-Replay: true`; with a different body it returns `409 idempotency_key_reuse`. Remembered for 24 hours.","schema":{"type":"string","maxLength":255},"example":"8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa"}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"revoked":{"type":"boolean","const":true}},"required":["id","revoked"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":"<id>","revoked":true}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Clashes with the current state, or an `Idempotency-Key` was reused with a different body.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/projects":{"get":{"operationId":"organization.projects.list","summary":"List projects","description":"The projects this organization's keys belong to. A project groups keys and can carry its own monthly unit cap, so usage can be attributed to one product or environment.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"monthly_unit_cap":{"anyOf":[{"type":"integer"},{"type":"null"}]},"active_keys":{"type":"integer"},"month_units":{"type":"integer"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["id","name","monthly_unit_cap","active_keys","month_units","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"<id>","name":"<name>","monthly_unit_cap":null,"active_keys":0,"month_units":0,"created_at":"2026-09-21T10:00:00.000Z"}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/usage":{"get":{"operationId":"organization.usage","summary":"Daily usage","description":"Requests and units per UTC day, key, endpoint and result class, for the last 7, 30 or 90 days.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"days","in":"query","required":false,"description":"Default 30.","schema":{"type":"string","enum":["7","30","90"]}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","example":"2026-09-21"},"key_id":{"description":"null for dashboard playground calls","type":["string","null"]},"endpoint":{"type":"string","example":"listings.search"},"status_class":{"type":"integer","description":"2, 4 or 5"},"requests":{"type":"integer"},"units":{"type":"integer"}},"required":["day","key_id","endpoint","status_class","requests","units"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"day":"2026-09-21","key_id":"<key_id>","endpoint":"listings.search","status_class":0,"requests":0,"units":0}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/members":{"get":{"operationId":"organization.members.list","summary":"List members and invitations","description":"Everyone with access to this organization and every invitation not yet accepted, with each person's role.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":["string","null"]},"role":{"type":"string","enum":["owner","admin","member"]},"joined_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["email","name","role","joined_at"],"additionalProperties":false}},"invitations":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["email","role","expires_at"],"additionalProperties":false}}},"required":["members","invitations"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"members":[{"email":"<email>","name":"<name>","role":"owner","joined_at":"2026-09-21T10:00:00.000Z"}],"invitations":[{"email":"<email>","role":"owner","expires_at":"2026-09-21T10:00:00.000Z"}]}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/audit-events":{"get":{"operationId":"organization.audit_events.list","summary":"List audit events","description":"Newest first, 50 per page. Pass `next_cursor` back as `cursor` for older events.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":256}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","example":"key.created"},"target":{"type":["string","null"]},"actor":{"description":"Email of the person, or null for Darak or an admin key","type":["string","null"]},"actor_key_id":{"type":["string","null"]},"ip":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["action","target","actor","actor_key_id","ip","created_at"],"additionalProperties":false}},"pagination":{"type":"object","properties":{"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"],"additionalProperties":false}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"action":"key.created","target":"<target>","actor":"<actor>","actor_key_id":"<actor_key_id>","ip":"<ip>","created_at":"2026-09-21T10:00:00.000Z"}],"pagination":{"next_cursor":"<next_cursor>","has_more":true}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/request-logs":{"get":{"operationId":"organization.request_logs.list","summary":"List request logs","description":"Calls this organization made, newest first, within its retention window (7, 30 or 90 days, set on the Settings page). Filter by `request_id` to look up one call — that ignores every other filter. Rows carry no parameters, IP or user agent for organizations that turn off request details.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"request_id","in":"query","required":false,"description":"One exact call. Overrides the other filters.","example":"req_4f1c2d9a8b7e6f5a4b3c2d1e","schema":{"type":"string","maxLength":64}},{"name":"key_id","in":"query","required":false,"description":"Only calls made with this key.","schema":{"type":"string","maxLength":64}},{"name":"route","in":"query","required":false,"description":"Endpoint id, as in the reference.","example":"listings.search","schema":{"type":"string","maxLength":64}},{"name":"status","in":"query","required":false,"description":"`errors` is anything at or above 400.","schema":{"type":"string","enum":["errors","2xx","4xx","5xx"]}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"until","in":"query","required":false,"schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"limit","in":"query","required":false,"description":"Default 25.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"request_id":{"description":"Quote this to support.","type":["string","null"]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},"route":{"type":"string","example":"listings.search"},"status":{"type":"integer","example":200},"units":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"0 for anything that wasn't a 2xx."},"duration_ms":{"type":"integer","example":84},"key_id":{"description":"Null for calls made from the dashboard.","type":["string","null"]},"error":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","example":"invalid_value"},"message":{"description":"Null when the org stores no request details.","type":["string","null"]},"param":{"type":["string","null"]}},"required":["code","message","param"],"additionalProperties":false},{"type":"null"}],"description":"Present only on a failure."},"params":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"The filters as sent, redacted. Null when details aren't stored."}},"required":["request_id","at","route","status","units","duration_ms","key_id","error","params"],"additionalProperties":false}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"],"additionalProperties":false},"example":{"data":[{"request_id":"<request_id>","at":"2026-09-21T10:00:00.000Z","route":"listings.search","status":200,"units":null,"duration_ms":84,"key_id":"<key_id>","error":{"code":"invalid_value","message":"<message>","param":"<param>"},"params":{}}],"pagination":{"limit":25,"next_cursor":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","has_more":true,"result_window_reached":false}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/webhooks":{"post":{"operationId":"organization.webhooks.create","summary":"Create a webhook endpoint","description":"Subscribes an HTTPS URL to listing events. The signing secret is in the response once: store it now, you'll need it to verify deliveries. Filters must include a city.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"A unique string (a UUID is ideal) making this call safe to retry. The same key with the same body replays the first response and sets `Idempotent-Replay: true`; with a different body it returns `409 idempotency_key_reuse`. Remembered for 24 hours.","schema":{"type":"string","maxLength":255},"example":"8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":500,"format":"uri","example":"https://example.com/darak-webhook"},"event_types":{"minItems":1,"type":"array","items":{"type":"string","enum":["listing.created","listing.price_changed","listing.delisted"]},"description":"See the webhooks guide.","example":["listing.created"]},"filters":{"type":"object","properties":{"city":{"type":"string","pattern":"^[a-z_]+$","description":"City slug from GET /cities.","example":"riyadh"},"listing_type":{"type":"string","enum":["rent","sale"]},"listing_category":{"type":"string","enum":["residential","commercial"]},"property_type":{"type":"string","maxLength":40},"neighborhood":{"type":"string","maxLength":200},"beds":{"type":"string","maxLength":10},"beds_min":{"type":"string","maxLength":10},"price_min":{"type":"string","maxLength":20},"price_max":{"type":"string","maxLength":20},"area_min":{"type":"string","maxLength":20},"area_max":{"type":"string","maxLength":20}},"required":["city"],"additionalProperties":false,"description":"Which listings this endpoint wants, in the vocabulary of GET /listings."},"description":{"type":"string","maxLength":200}},"required":["url","event_types","filters"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"whe_7Fh2kQ9cV1xZ"},"url":{"type":"string"},"event_types":{"type":"array","items":{"type":"string"},"example":["listing.created"]},"filters":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"description":"`too_many_failures` when we stopped after repeated failures.","type":["string","null"]},"consecutive_failures":{"type":"integer"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"},"secret":{"type":"string","description":"The signing secret. Shown once."}},"required":["id","url","event_types","filters","description","status","disabled_reason","consecutive_failures","created_at","secret"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":"whe_7Fh2kQ9cV1xZ","url":"<url>","event_types":["listing.created"],"filters":{},"description":"<description>","status":"active","disabled_reason":"<disabled_reason>","consecutive_failures":0,"created_at":"2026-09-21T10:00:00.000Z","secret":"<secret>"}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Clashes with the current state, or an `Idempotency-Key` was reused with a different body.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"organization.webhooks.list","summary":"List webhook endpoints","description":"Every endpoint this organization has subscribed. Secrets are never returned.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"whe_7Fh2kQ9cV1xZ"},"url":{"type":"string"},"event_types":{"type":"array","items":{"type":"string"},"example":["listing.created"]},"filters":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"description":{"type":["string","null"]},"status":{"type":"string","enum":["active","disabled"]},"disabled_reason":{"description":"`too_many_failures` when we stopped after repeated failures.","type":["string","null"]},"consecutive_failures":{"type":"integer"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["id","url","event_types","filters","description","status","disabled_reason","consecutive_failures","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"whe_7Fh2kQ9cV1xZ","url":"<url>","event_types":["listing.created"],"filters":{},"description":"<description>","status":"active","disabled_reason":"<disabled_reason>","consecutive_failures":0,"created_at":"2026-09-21T10:00:00.000Z"}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/webhooks/{webhook_id}/delete":{"post":{"operationId":"organization.webhooks.delete","summary":"Delete a webhook endpoint","description":"Stops delivery and removes the endpoint and its delivery history.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","maxLength":64}},{"name":"Idempotency-Key","in":"header","required":false,"description":"A unique string (a UUID is ideal) making this call safe to retry. The same key with the same body replays the first response and sets `Idempotent-Replay: true`; with a different body it returns `409 idempotency_key_reuse`. Remembered for 24 hours.","schema":{"type":"string","maxLength":255},"example":"8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa"}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":"<id>","deleted":true}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Clashes with the current state, or an `Idempotency-Key` was reused with a different body.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/webhooks/{webhook_id}/deliveries":{"get":{"operationId":"organization.webhooks.deliveries","summary":"List deliveries","description":"What was sent to this endpoint, newest first, with what it answered. A delivery that ran out of attempts shows `failed`; replay it once the receiver is fixed.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","maxLength":64}},{"name":"limit","in":"query","required":false,"description":"Default 25.","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"event_id":{"type":"string","description":"Stable across retries and replays."},"event_type":{"type":"string"},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"anyOf":[{"type":"integer"},{"type":"null"}]},"response_snippet":{"description":"First 500 characters of the reply.","type":["string","null"]},"next_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]},"delivered_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z","description":"ISO 8601 time"}},"required":["id","event_id","event_type","status","attempts","response_status","response_snippet","next_attempt_at","delivered_at","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":0,"event_id":"<event_id>","event_type":"<event_type>","status":"pending","attempts":0,"response_status":null,"response_snippet":"<response_snippet>","next_attempt_at":"2026-09-21T10:00:00.000Z","delivered_at":"2026-09-21T10:00:00.000Z","created_at":"2026-09-21T10:00:00.000Z"}]}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/webhooks/{webhook_id}/deliveries/{delivery_id}/replay":{"post":{"operationId":"organization.webhooks.replay","summary":"Replay a delivery","description":"Queues the same payload again, with its original `event_id` so a receiver that already handled it can recognise the repeat. Use after fixing whatever rejected it.","tags":["Administration"],"x-scope":"organization","x-units":0,"security":[{"adminKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","maxLength":64}},{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","maxLength":32}},{"name":"Idempotency-Key","in":"header","required":false,"description":"A unique string (a UUID is ideal) making this call safe to retry. The same key with the same body replays the first response and sets `Idempotent-Replay: true`; with a different body it returns `409 idempotency_key_reuse`. Remembered for 24 hours.","schema":{"type":"string","maxLength":255},"example":"8f14e45f-ea6a-4cbb-9a2f-3d1c0b7e21aa"}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","const":"pending"}},"required":["id","status"],"additionalProperties":false}},"required":["data"],"additionalProperties":false},"example":{"data":{"id":0,"status":"pending"}}}}},"400":{"description":"Invalid request: unknown or malformed parameters.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Your plan or account doesn't allow this request.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method for this path. `Allow` lists the ones it takes.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Allow":{"description":"The methods this path accepts.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Clashes with the current state, or an `Idempotency-Key` was reused with a different body.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or monthly quota exceeded. See `Retry-After`.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always sent with a 429.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Our fault. Safe to retry with backoff.","headers":{"X-Request-Id":{"description":"Quote this when contacting support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Your secret API key, `dk_live_…`. Never put it in URLs or client-side code. Data endpoints also accept an OAuth access token issued by platform.darak.app, which acts for the person who granted it and can only read."},"testKey":{"type":"http","scheme":"bearer","description":"A test key, `dk_test_…`. Reads the same live data as `dk_live_…` under a small fixed allowance that is metered separately and never billed. Accepted anywhere a data key is."},"adminKey":{"type":"http","scheme":"bearer","description":"An admin key, `dk_admin_…`, created by an organization owner. These reach only the Administration endpoints, and a `dk_live_…` key is refused there — the two kinds never overlap."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["type","code","message","request_id","doc_url"],"properties":{"type":{"type":"string","enum":["invalid_request","authentication_error","permission_error","not_found","method_not_allowed","conflict","rate_limit_error","api_error"]},"code":{"type":"string","description":"Machine-readable. Codes are never renamed; new ones may be added.","examples":["invalid_value"]},"message":{"type":"string","description":"Human-readable; may change."},"param":{"type":"string","description":"The parameter or field at fault, if any."},"details":{"type":"object","additionalProperties":true},"request_id":{"type":"string","examples":["req_4f1c2d9a8b7e6f5a4b3c2d1e"]},"doc_url":{"type":"string"}}}}},"Listing":{"type":"object","properties":{"id":{"type":"integer","example":128647},"url":{"type":"string","description":"The listing's page on darak.app.","example":"https://darak.app/en/listing/128647"},"title":{"description":"The advertiser's title, as posted. Null for sources that don't have titles (for example Aqar); use `headline` for display.","type":["string","null"]},"headline":{"type":"string","description":"A short English description built from the listing's fields. Always present.","example":"3-bedroom apartment for rent in Al Malqa, Riyadh"},"description":{"description":"As posted (usually Arabic).","type":["string","null"]},"description_en":{"description":"English translation, where available.","type":["string","null"]},"listing_type":{"type":"string","example":"rent"},"listing_category":{"example":"residential","type":["string","null"]},"property_type":{"type":"string","example":"apartment"},"price":{"type":"object","properties":{"yearly_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Price in SAR per year for rentals (monthly/daily postings are normalized to yearly); total price for sales. Use this for comparisons.","example":60000},"as_posted":{"type":"object","properties":{"amount":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The price as the advertiser posted it.","example":5000},"frequency":{"description":"Rent period of `amount` (yearly, monthly, weekly, daily). Null for sales.","example":"monthly","type":["string","null"]}},"required":["amount","frequency"],"additionalProperties":false},"previous_yearly_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Price before the last change, if any.","example":66000},"changed_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"When the price last changed."}},"required":["yearly_sar","as_posted","previous_yearly_sar","changed_at"],"additionalProperties":false},"financing":{"type":"object","properties":{"rent_now_pay_later_monthly_sar":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Monthly price under the rent-now-pay-later financing option the source offers on this listing, as the source reports it. Rentals only; currently Aqar only."},"accepts_bank_financing":{"description":"Seller accepts a bank mortgage. Null when not stated. Currently Aqar only.","type":["boolean","null"]},"landlord_payment_plans":{"type":"object","properties":{"monthly":{"type":["boolean","null"]},"quarterly":{"type":["boolean","null"]},"semiannually":{"type":["boolean","null"]}},"required":["monthly","quarterly","semiannually"],"additionalProperties":false,"description":"Installment schedules the landlord accepts directly."}},"required":["rent_now_pay_later_monthly_sar","accepts_bank_financing","landlord_payment_plans"],"additionalProperties":false},"bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"example":3},"bathrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"example":2},"livings":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Living rooms.","example":1},"area_sqm":{"example":140,"type":["number","null"]},"floor":{"example":"2","type":["string","null"]},"age_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"example":4},"furnished":{"example":false,"type":["boolean","null"]},"amenities":{"type":"array","items":{"type":"string"},"example":["ac","kitchen","parking"]},"location":{"type":"object","properties":{"city":{"description":"City slug (see GET /cities).","example":"riyadh","type":["string","null"]},"city_name_en":{"example":"Riyadh","type":["string","null"]},"neighborhood_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"See GET /cities/{city}/neighborhoods.","example":12},"neighborhood_name_ar":{"example":"الملقا","type":["string","null"]},"neighborhood_name_en":{"example":"Al Malqa","type":["string","null"]},"lat":{"example":24.7869,"type":["number","null"]},"lng":{"example":46.6215,"type":["number","null"]},"street_width_m":{"example":20,"type":["number","null"]}},"required":["city","city_name_en","neighborhood_id","neighborhood_name_ar","neighborhood_name_en","lat","lng","street_width_m"],"additionalProperties":false},"compound_name":{"example":"Sedra","type":["string","null"]},"project_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Off-plan project this unit belongs to, if linked."},"images":{"type":"array","items":{"type":"string"},"description":"Image URLs on Darak's CDN.","example":["https://images.darak.app/listings/128647/1.webp"]},"image_count":{"type":"integer","example":8},"advertiser":{"type":"object","properties":{"type":{"description":"Advertiser category as the source reports it, verbatim — `agency`, `company_broker`, `developer`, `individual_broker`, `individual_owner` and similar. These are not the values the `advertiser_type` filter takes: that filter offers `company` and `individual`, which group these, so a response value cannot be passed straight back as a filter.","example":"agency","type":["string","null"]}},"required":["type"],"additionalProperties":false},"verified_by_source":{"description":"The source marks this ad as verified.","type":["boolean","null"]},"source":{"type":"object","properties":{"name":{"type":"string","description":"Source platform (see GET /enums).","example":"aqar"},"listing_id":{"example":"7788123","type":["string","null"]},"url":{"description":"The original ad. Attribution is required, see the terms.","example":"https://sa.aqar.fm/7788123","type":["string","null"]}},"required":["name","listing_id","url"],"additionalProperties":false},"also_listed_on":{"type":"array","items":{"type":"string"},"description":"Other sources carrying the same property. Darak shows one listing per property.","example":["bayut"]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"When Darak first saw the listing."},"updated_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"Last update at the source, or the last time Darak saw the listing if the source doesn't publish update times. Drives `updated_since` and the `updated_*` sorts."},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","example":"2026-09-21T10:00:00.000Z"},{"type":"null"}],"description":"Last time Darak confirmed the listing is live."},"days_on_market":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["id","url","title","headline","description","description_en","listing_type","listing_category","property_type","price","financing","bedrooms","bathrooms","livings","area_sqm","floor","age_years","furnished","amenities","location","compound_name","project_id","images","image_count","advertiser","verified_by_source","source","also_listed_on","first_seen_at","updated_at","last_seen_at","days_on_market"],"additionalProperties":false},"Pagination":{"type":"object","properties":{"limit":{"type":"integer","example":25},"next_cursor":{"description":"Pass as `cursor` for the next page.","example":"eyJvIjoyNSwiZiI6IksweTFfU1F3d1BXSiJ9.pkFEfJUOpRbZRS279EDC4v","type":["string","null"]},"has_more":{"type":"boolean","example":true},"result_window_reached":{"type":"boolean","example":false,"description":"True when more results exist but your plan's paging depth is reached. Narrow the filters, or for syncs continue with `updated_since` set to the last `updated_at` you received."}},"required":["limit","next_cursor","has_more","result_window_reached"],"additionalProperties":false}}}}