Quick start
After you subscribe and we confirm your payment, you receive a key for the propdata-ae product. Store it as an environment variable on your server, then:
# 1. Find a DLD registration area ID curl -s -H "x-api-key: $PROPDATA_AE_KEY" \ "https://api.dubai.proptechusa.ai/v1/ae/dubai/areas" # 2. Business Bay (area 526), Ready residential units, yearly curl -sG "https://api.dubai.proptechusa.ai/v1/ae/dubai/market" \ -d area_id=526 -d group=area -d period=year -d registration=Ready -d top=100 \ -H "x-api-key: $PROPDATA_AE_KEY" # 3. Community index for Business Bay, monthly from January 2026 curl -sG "https://api.dubai.proptechusa.ai/v1/ae/dubai/communities/business-bay/monthly" \ -d date_from=2026-01 \ -H "x-api-key: $PROPDATA_AE_KEY" # 4. Every verified month for Marsa Dubai (area 330), oldest first, 100 per page; follow pagination.next_offset curl -sG "https://api.dubai.proptechusa.ai/v1/ae/dubai/market" \ -d area_id=330 -d registration=Ready -d sort=period -d top=100 -d offset=0 \ -H "x-api-key: $PROPDATA_AE_KEY" # 5. Rents, yields and bedroom segments (publisher aggregates) curl -s -H "x-api-key: $PROPDATA_AE_KEY" "https://api.dubai.proptechusa.ai/v1/ae/dubai/rentals/communities" curl -s -H "x-api-key: $PROPDATA_AE_KEY" "https://api.dubai.proptechusa.ai/v1/ae/dubai/yields/communities" curl -s -H "x-api-key: $PROPDATA_AE_KEY" "https://api.dubai.proptechusa.ai/v1/ae/dubai/communities/business-bay/bedrooms" # 6. Project register: one developer's projects under construction, then one project with its capture history curl -sG "https://api.dubai.proptechusa.ai/v1/ae/dubai/projects" \ -d developer_number=1002 -d completion_min=1 -d completion_max=99 -d limit=200 \ -H "x-api-key: $PROPDATA_AE_KEY" curl -s -H "x-api-key: $PROPDATA_AE_KEY" "https://api.dubai.proptechusa.ai/v1/ae/dubai/projects/3073"
// Node 18+ on your server const BASE = "https://api.dubai.proptechusa.ai"; async function ae(path) { const res = await fetch(BASE + path, { headers: { "x-api-key": process.env.PROPDATA_AE_KEY } }); const body = await res.json(); if (!res.ok) throw new Error(`${res.status} ${body.error}${body.reason ? " (" + body.reason + ")" : ""}`); return { body, quotaRemaining: res.headers.get("x-ae-quota-remaining") }; } const { body } = await ae("/v1/ae/dubai/market?area_id=526&group=area&period=year®istration=Ready&top=100"); for (const g of body.data) console.log(g.period, g.sample_count, g.median_sale_price_per_sqm_aed); console.log(body.freshness.verified_complete_through, body.sources.attribution);
import os, requests BASE = "https://api.dubai.proptechusa.ai" s = requests.Session() s.headers["x-api-key"] = os.environ["PROPDATA_AE_KEY"] r = s.get(f"{BASE}/v1/ae/dubai/communities", timeout=30) r.raise_for_status() doc = r.json() print(doc["price_unit"], doc["freshness"]["publisher_data_through"]) for c in doc["data"][:5]: print(c["community_name"], c["median_price_per_sqft_aed"]) # Walk a full market history: sort=period and follow next_offset until it is None months, offset = [], 0 while offset is not None: page = s.get(f"{BASE}/v1/ae/dubai/market", params={"area_id": "330", "registration": "Ready", "sort": "period", "top": 100, "offset": offset}, timeout=30).json() months += [g["period"] for g in page["data"]] offset = page["pagination"]["next_offset"] print(len(months), page["pagination"]["document_complete"]) # every eligible month through the verified date
Authentication
Send your key in the x-api-key header, or as Authorization: Bearer <key>. Keys are issued for the propdata-ae product only; PropData US keys are not accepted.
The OpenAPI document at /v1/ae/openapi.json needs no key.
Datasets
| Contract | What it is | Unit | Geography |
|---|---|---|---|
propdata-ae-market/1 | Registered-sale statistics computed by PropData: median sale price and median, 25th and 75th percentile price per square metre | AED, AED/m² | DLD registration area, project name, building name |
propdata-ae-community/1 | Independent publisher's community index, republished unchanged; ready and off-plan pooled; monthly since 2021 and yearly since 2010 | AED/ft² | Communities (master projects) |
propdata-ae-rentals/1 | Ejari rent-contract counts and median annual rent per community, last 12 months, as published | AED/year | Communities |
propdata-ae-yields/1 | Gross rental yield per community by the publisher's segment method (median rent ÷ median ready-sale price inside each property class × bedroom segment) | % | Communities |
propdata-ae-bedrooms/1 | Bedroom-count segments, last 12 complete months: price sample, median price, AED/ft², size, median rent, contracts, gross yield | AED, AED/ft² | Dubai and communities |
propdata-ae-projects/1 | DLD project register (Mashrooi) snapshotted daily by Continental Club Property: completion % and inspection dates, registered units, declared handover; with PropData's capture history | register values | Project number |
propdata-ae-developers/1 | Developers keyed on the published DLD developer number: publisher sales summary plus PropData counts from the register snapshot | register values | Developer number |
Only propdata-ae-market/1 is computed by PropData; every other contract republishes a publisher's figures with its methodology (statistics_origin: publisher_aggregate_republished). Do not compare them without reading the not_comparable_with and methodology blocks in each response. Project and developer records are joined across publishers only on the registry numbers both publish, never on names, and never to individual sales.
Market statistics
GET/v1/ae/dubai/market
Registered-sale statistics for one DLD area, grouped by area, project name or building name.
| Parameter | Values | Notes |
|---|---|---|
area_id required | 1–6 digits | DLD area ID from /areas. An unknown ID returns 404 unknown_area. |
group | area (default), project, building | Project and building groups use free-text source names, not registry identifiers. |
period | month (default), quarter, year | |
registration | Ready, Off-Plan | Omit to pool both; the response then carries a registration_warning, because Ready and Off-Plan prices are not comparable. |
top | 1–100 (default 25) | Rows per page. See the note below. |
sort | sample_count (default), period | period returns rows oldest first; page with offset. |
offset | 0 or more | Rows to skip in the chosen order; follow pagination.next_offset until it is null. |
period_from, period_to | 2019, 2019-Q1, 2019-01 | Inclusive bounds on the period key. Not a custom window: nothing is recomputed and no extra entitlement is needed. |
date_from, date_to, property_type, usage | — | Custom windows, which are not available at launch: Starter returns 403 not_entitled, Professional returns 422 custom_window_requires_origin. The defaults are Unit / Residential. |
top rows by sample_count; use sort=period with offset, or period_from/period_to, to read a whole series in order. pagination reports matched_groups, total_groups_in_document, eligible_groups, document_complete and next_offset, so you can verify nothing was omitted.top selects rows. Each row in data is one group in one period. Eligible rows (30 or more sales) are ranked by sample_count, highest first, and the first top rows are returned, so data is not in date order. When a series has more than 100 periods, as monthly histories for busy areas do, some months are not returned. For a complete long-run series, request period=quarter or period=year, then sort by period.Each row in data
| Field | Meaning |
|---|---|
period | 2025, 2025-Q4 or 2025-12 |
source_name, name_variants | Group name (area, project or building) and the source spellings pooled into it |
sample_count | Registered sales in the group and period (minimum 30) |
median_sale_price_aed | Median sale price, as a decimal string |
median_sale_price_per_sqm_aed, p25_…, p75_… | Median and nearest-rank quartiles of AED per square metre |
oldest_sale_date, latest_sale_date | Date range of the sales in the row |
source_sha256s, source_urls | Exact source file version used |
The response also carries scope (the resolved query), sample_rule (including suppressed and excluded row counts), freshness, coverage, limitations, sources and bundle. Prices are decimal strings, so parse them with a decimal type if you need exact arithmetic.
Areas
GET/v1/ae/dubai/areas
Every DLD registration area with its source names, sale-row counts, date range, boundary note and completeness.
completeness.status and completeness.verified_through show whether, and up to when, an area was independently verified. Area IDs are registration districts. Area 330, Marsa Dubai, includes JBR and Bluewaters; it is not the Dubai Marina community.
Communities
GET/v1/ae/dubai/communities
Trailing 12-month summary for every community: registered sales, median price, median AED/ft², year-on-year changes, off-plan share, and the publisher's rent and yield aggregates.
All values are the publisher's community aggregates (statistics_origin: publisher_aggregate_republished). Rent figures are community summaries, not individual contracts. top_dld_area is the publisher's majority-area field and does not mean the boundaries are equivalent.
Community monthly & yearly
GET/v1/ae/dubai/communities/{slug}/yearly
Yearly registered sales, median price, median AED/ft² and registered value since 2010 for one community (dubai for emirate-wide). The latest year is partial.
GET/v1/ae/dubai/communities/{slug}/monthly
Monthly median AED/ft², Q1–Q3, median price and registered sales for one community. Use dubai as the slug for emirate-wide figures.
| Parameter | Values | Notes |
|---|---|---|
slug required | for example business-bay, dubai-marina, dubai | Slugs are listed by /communities. An unknown slug returns 404 unknown_community. |
date_from, date_to | YYYY-MM | Optional filter on the monthly series |
Each month carries sample_flag (the publisher's low-sample marker) and provisional. DLD keeps adding registrations after a month ends, so the latest months can still change.
Rents, yields and bedroom segments
GET/v1/ae/dubai/rentals/communities
Ejari rent-contract count and median annual rent (AED) per community over the last 12 months, with the publisher's gross yield (propdata-ae-rentals/1).
GET/v1/ae/dubai/yields/communities
Gross rental yield per community computed inside property-class × bedroom segments, with the segments, contracts and ready sales used (propdata-ae-yields/1).
GET/v1/ae/dubai/bedrooms
Dubai-wide bedroom-count segments, last 12 complete months (propdata-ae-bedrooms/1).
GET/v1/ae/dubai/communities/{slug}/bedrooms
The same segments for one community: price_sample, median_price_aed, median_price_per_sqft_aed, median_size_sqft, median_annual_rent_aed, rent_contracts, gross_yield_pct.
All values are the publisher's aggregates: rents are community or segment summaries of Ejari contracts, never individual tenancies; yields are gross, before service charges, vacancy, fees and financing, and are not a return forecast. Each response carries the publisher's methodology and freshness.publisher_data_through.
Project register
GET/v1/ae/dubai/projects
The Dubai Land Department project register (Mashrooi) as snapshotted daily by Continental Club Property: project number, developer number and name, community, land number, total area, registered units, completion % at the latest technical inspection and its date, the previous reading, start date and declared handover date (propdata-ae-projects/1).
| Parameter | Values | Notes |
|---|---|---|
developer_number | digits | Published DLD developer number |
community | register name | Exact match, case-insensitive (for example Business Bay) |
handover_year | YYYY | Declared handover year |
completion_min, completion_max | 0–100 | Completion percentage band |
inspected_since | YYYY-MM-DD | Latest inspection on or after this day |
offset, limit | limit 1–500 (default 100) | pagination.matched is the filtered total; follow next_offset |
GET/v1/ae/dubai/projects/{project_number}
One project: the register record, the second publisher's record for the same DLD project number (datadubai_project: status, escrow bank, registration date, coordinates and sales medians where published) and PropData's capture_history of every captured snapshot version with changed_fields.
The completion percentage is recorded by a DLD technical inspector and stays constant between inspections. The declared handover date is the date held in the register, not actual completion. No project is linked to an individual sale, unit or title.
Developers
GET/v1/ae/dubai/developers
Every developer in either dataset, keyed on the published DLD developer number: the publisher's company summary (last-12-month sales, medians, off-plan share, registered projects and units) where published, and PropData's register_summary computed only from the register snapshot (projects, registered units, completion distribution, latest inspection, declared handovers by year) (propdata-ae-developers/1).
GET/v1/ae/dubai/developers/{developer_number}
One developer with its register projects.
Company records only: no contact details, escrow balances or financial statements.
Sources
GET/v1/ae/dubai/sources
The sources behind the datasets: licence, attribution, licence quote, upstream statement, restrictions, coverage and the active snapshot hash.
Freshness & completeness
Registered-sale responses include a freshness block:
"freshness": {
"source_data_through": "2025-12-31",
"verified_complete_through": "2025-12-31",
"verified_complete_through_basis": "area_community_union",
"coverage_cutoff_applied": true
}| Basis | Meaning |
|---|---|
area_publisher_one_to_one | The area's monthly counts and medians matched an independent publisher through the date. |
area_community_union | The area's monthly counts matched the publisher's communities within it through the date. |
dubai_wide | The area could not be checked individually; the emirate-wide verified date applies. Treat it as lower confidence. |
source_declared | Fallback when no current audit exists. |
Months after verified_complete_through are withheld rather than estimated. Current dates: registered sales are verified through 31 Jan 2026 Dubai-wide, and up to 30 Sep 2026 for individually verified areas. Community index responses report publisher_data_through, currently 15 Oct 2026. The dates in each response take precedence over this page.
Every response names its release in bundle.version and bundle.manifest_sha256. Keep these if you need to reproduce a figure later.
Errors
Errors return JSON: {"error": "…", "reason": "…", "detail": "…"}. Only error is always present.
| Status | error | When |
|---|---|---|
| 400 | invalid_request, invalid_query_parameters, invalid_top | Bad or unknown parameters. Never counts against your quota. |
| 401 | invalid_api_key | Missing, unknown or revoked key (see reason) |
| 403 | not_entitled | Your plan does not include the route, for example a custom window on Starter |
| 404 | unknown_area, unknown_community, not_found | Unknown ID, slug or path |
| 405 | read_only | Any method other than GET |
| 422 | custom_window_requires_origin | Custom window on Professional (not available at launch) |
| 429 | rate_limited / monthly_quota_exhausted | Per-minute guard (Retry-After: 60) or monthly quota reached |
| 503 | auth_unavailable, bundle_unavailable | Temporarily unavailable; the API fails closed. Retry with backoff. |
Quotas & limits
| Plan | Price | Monthly requests | Per-minute guard | Custom windows |
|---|---|---|---|---|
| Starter | USD 99 / month | 5,000 | ~300 per key | Not included |
| Professional | USD 299 / month | 50,000 | ~300 per key | Not available at launch |
The monthly quota is enforced exactly and atomically per key. Successful responses include X-AE-Quota-Remaining. The per-minute guard is approximate and applied per location. Responses also include a Server-Timing header.
The data changes only when a new verified release is published, so cache responses on your side and use bundle.version to tell when to refresh.
Attribution
Both source publishers license their data under CC BY 4.0. Wherever you display or redistribute the data, show the attribution from sources.attribution and the non-endorsement notice from sources.endorsement_notice, link to the licence, and state any further changes you make.
Not provided
The API serves statistics and register records, not property records. It does not provide individual transaction records, unit or property histories, ownership, title or registry records, valuations or appraisals, individual rental (Ejari) contracts, developer contact details or escrow balances, any link from a project or developer to an individual sale, unit or title, parcel boundaries or maps. The project register carries the register's completion percentage and declared handover date, not a construction-progress assessment. Statistics are not investment advice, and gross yields are not return forecasts.
Questions: sales@proptechusa.ai.