# Qatar Living Classifieds, Property, Cars & Deals (qatarliving.com)

> Search or browse Qatar Living across all eight of its indexes — second-hand items, cars, property, services, merchant deals, news and events — with the price, images, district, geo-coordinates, category tree and every structured attribute the vertical publishes. Free text works in English and Arabic; leave the query out and it becomes a filtered, sorted browse of the whole index, which is also the only way to get an exact count.
> ReefAPI engine `qatarliving` · 8 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/qatarliving/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Send the key as `Authorization: Bearer <key>`, or put it in the URL (`?key=<key>`) when the client has no header field, as ChatGPT does.

## Endpoints

### POST https://api.reefapi.com/qatarliving/v1/search — 2 credits
Search or browse Qatar Living across all eight of its indexes — second-hand items, cars, property, services, merchant deals, news and events — with the price, images, district, geo-coordinates, category tree and every structured attribute the vertical publishes. Free text works in English and Arabic; leave the query out and it becomes a filtered, sorted browse of the whole index, which is also the only way to get an exact count.

**Parameters:**
- `query` (string, optional) — Free text, English or Arabic. Optional: leave it out to BROWSE the vertical with filters and a sort instead, which is also the only way to get an exact count (see `returns`).
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `sub_vertical` (enum, optional) — Narrow a vertical to one of its sections. 🔴 Use the SLUG: `items` (31,381 live), `stores` (3,061), `offers` (2,063), `pre-loved` (85), `collectibles` (76) on classifieds; `residential` (25,509), `commercial` (3,860), `agencies`, `international`, `schools` on properties. The display spellings the same API prints in its own facet (`Items`, `Pre-Loved`) are accepted upstream and then IGNORED, so this engine slugifies what you pass and fails the call if the source did not actually apply it. Every answer reports all the section counts in `section_counts` regardless. [one of: items, stores, offers, pre-loved, collectibles, residential, commercial, agencies, international, schools]
- `sort` (enum, optional, default "relevance") — Result order. [one of: relevance, newest, oldest, price_asc, price_desc, soonest, expiring_soon, discount_desc, discount_asc, rating_desc, nearest]
- `filters` (object, optional) — Structured filters, exactly as Qatar Living names them — 108 keys across the verticals. Lists for categorical keys, numbers for the min/max ones, booleans for the flags: `category`, `l1_category`, `l2_category`, `sub_vertical`, `brand`, `model`, `condition`, `color`, `location`, `zone`, `price` {min,max}, `is_freebie`, `is_featured`, `verified_only`, `freshness_days`, `date_from`/`date_to` · vehicles: `make`, `trim`, `year_min`/`year_max`/`year_int`, `mileage_max`, `fuel_type`, `gear_type`, `body_type`, `bike_type`, `boat_type`, `wheel_drive`, `seat_count`, `under_warranty`, `is_showroom`, `with_driver` · properties: `purpose`, `property_type`, `real_estate_type`, `bedrooms_min`/`bedrooms_max`, `bathrooms_min`, `furnishing`, `amenities`, `area_sqm_min`/`area_sqm_max`, `rent_frequency`, `ready_to_move`, `has_kahramaa` · deals: `agency_name`, `offer_type`, `sub_category`, `discount_percentage_min`, `is_deal_of_the_day` · geography: `geo` {lat, lon, radius_km}. An unknown key is rejected with the key named. Use the `facets` action to read the values a vertical publishes.
- `facets` (array, optional) — Also count these field names over the matching set — the cheapest way to see what a query's results are made of. 🔴 A field this vertical cannot facet on makes the source drop the WHOLE request, and the call then returns INVALID_PARAM naming it.
- `page` (integer, optional, default 1) — 1-based page number.
- `limit` (integer, optional, default 20) — Rows per page, 1-100. The source documents 200 but returns 100 (measured: page_size 200 and 100 gave byte-identical answers), so 100 is the honest ceiling.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Include the seller's phone number, WhatsApp number and display name. Withheld by default; every row says whether something was held back (`pii_withheld`). Only the classifieds vertical publishes phone numbers at all.

**Returns:** {query, vertical, sub_vertical, sort, page, limit, total_matched, total_reported, total_is_relevance_pool, total_pages, has_more, vertical_counts{}, section_counts{}, irrelevant_query, irrelevant_query_message, did_you_mean, facets{}, listings[], similar_listings[], search_id}. 🔴 `total_matched` is the number to trust: on deals, news and events a free-text total is a relevance-pool size (deals returns a flat 500 for every query, nonsense included) and `total_is_relevance_pool` says so. Each listing carries the source's own key set for that vertical — 52 fields on classifieds, 73 on properties, 101 on vehicles — plus id, url, vertical, price (null when none is published), currency QAR, image, images[], images_count, title_is_arabic and pii_withheld. Seller phone/WhatsApp/display name only when include_pii.

**Example request body:**
```json
{
  "query": "land cruiser",
  "vertical": "vehicles",
  "limit": 10
}
```

### POST https://api.reefapi.com/qatarliving/v1/listing — 1 credit
One Qatar Living listing in full, bilingual: the seller's own text and its Arabic or English counterpart, the price, the whole image set, the category breadcrumb, the geo-coordinates and every structured attribute the vertical publishes (make/model/year/mileage/gearbox on a car, bedrooms/bathrooms/area/furnishing/amenities on a flat, merchant/branches/validity/terms on a deal).

**Parameters:**
- `id` (string, required) — The listing id from a search row — `items-50156` (classifieds), `9708` (services), `1676` (deals), `306166` (properties), `car_197619` / `boat_360` / `motorbike_1450` (vehicles), `news-…` / `event-…` (editorial).
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Include the seller's phone number, WhatsApp number and display name. Withheld by default; every row says whether something was held back (`pii_withheld`). Only the classifieds vertical publishes phone numbers at all.

**Returns:** {listing{…}}. The row shape of `search` plus the `_ar` counterparts this surface adds — title_ar, description_ar, category_ar and up to 14 more per vertical (make_ar, year_ar, fuel_type_ar, purpose_ar, property_type_ar, furnishing_status_ar, offer_type_ar, claim_rules_ar, venue_ar …). 🔴 Ids are scoped to the vertical: the wrong pairing is NOT_FOUND.

**Example request body:**
```json
{
  "id": "items-50156"
}
```

### POST https://api.reefapi.com/qatarliving/v1/similar — 2 credits
More listings like this one — Qatar Living's own vector nearest-neighbour search over the listing's text. Give it a car and it returns comparable cars, give it a flat and it returns comparable flats; on news and events it returns related articles inside a recency window.

**Parameters:**
- `id` (string, required) — The listing id to find look-alikes for.
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `limit` (integer, optional, default 10) — How many look-alikes, 1-50.
- `months` (integer, optional, default 6) — News and events only: how far back the look-alike window reaches, 1-24 months.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Include the seller's phone number, WhatsApp number and display name. Withheld by default; every row says whether something was held back (`pii_withheld`). Only the classifieds vertical publishes phone numbers at all.

**Returns:** {id, vertical, count, listings[]} using the `search` row shape. For news and events the source's related-article route is used instead and each row is {id, title} with the article slug where the source gives one.

**Example request body:**
```json
{
  "id": "items-50156"
}
```

### POST https://api.reefapi.com/qatarliving/v1/suggest — 1 credit
Autocomplete the way Qatar Living's own search box does: the keywords and merchant names it would offer for a partial query, each with the number of listings or offers behind it, in English or Arabic.

**Parameters:**
- `query` (string, required) — The partial text a user has typed, 1-100 characters, English or Arabic.
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `limit` (integer, optional, default 5) — How many suggestions, 1-20.
- `fuzzy` (boolean, optional, default false) — Tolerate typos and partial words. Measured difference on `iph` + classifieds: off → "used ip phone" first, on → "iphone" first.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]

**Returns:** {query, vertical, fuzzy, count, suggestions[]}. Each suggestion: text, id, entry_type (keyword | merchant), category, match_count (listings behind a keyword), offer_count (offers behind a merchant), is_popular, popularity_rank, and for a merchant agency_id / agency_slug / logo.

**Example request body:**
```json
{
  "query": "iph",
  "vertical": "classifieds",
  "fuzzy": true,
  "limit": 5
}
```

### POST https://api.reefapi.com/qatarliving/v1/popular_keywords — 1 credit
What Qatar is actually searching for on Qatar Living right now, per vertical — the demand signal behind the marketplace. Measured examples: classifieds fridge / washing machine / wardrobe, vehicles land cruiser / prado / camry, properties studio apartment / 1 BHK / furnished studio, deals buffet / pool access / massage, services babysitting / electrician / ac repair.

**Parameters:**
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `limit` (integer, optional, default 12) — How many keywords, 1-50.
- `entry_type` (enum, optional) — Keep only one kind of entry: a search keyword, or a merchant name (deals). [one of: keyword, merchant]
- `sub_vertical` (string, optional) — Scope the list to one section slug, e.g. `pre-loved`. Falls back to the vertical-wide list when that section has none, so it is always safe to pass.
- `all_verticals` (boolean, optional, default false) — Merge every vertical's popular keywords round-robin instead of reading one vertical. Each keyword then says which vertical it belongs to.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]

**Returns:** {vertical, count, keywords[]}. Each keyword: keyword, id, entry_type, category, match_count, offer_count, vertical (filled when all_verticals is used) and the merchant fields when the entry is a merchant.

**Example request body:**
```json
{
  "vertical": "vehicles",
  "limit": 5
}
```

### POST https://api.reefapi.com/qatarliving/v1/facets — 1 credit
The filter VOCABULARY and the size of every bucket, in one call — the category tree, the car makes and models, the property types and purposes, the brands, conditions, colours and districts a vertical actually publishes, each with its live count. This is the dictionary the `filters` parameter needs, and it doubles as a market snapshot (vehicles: SUV/4x4 4154, Sedan 1131, Petrol 4634, Diesel 69 at capture).

**Parameters:**
- `facets` (array, required) — The field names to count. Measured working names — classifieds: category, l1_category, l2_category, brand, condition, color, sub_vertical, ad_type, price_type, location, is_freebie · vehicles: make, model, body_type, fuel_type, gear_type, condition, purpose, year_int · properties: purpose, property_type, category, rent_frequency · services: category, l1_category, location · deals: category, sub_category, offer_type, agency_name · events: category, access_type, location · news: category, author, sub_category. 🔴 A name the vertical cannot facet on (properties `location`, `bedrooms`, `furnishing_status`) makes the source drop the whole request → INVALID_PARAM.
- `vertical` (enum, optional, default "classifieds") — Which Qatar Living index to read. Listing ids are scoped to the vertical, so the vertical a row came from is the vertical its `listing` call needs. [one of: classifieds, vehicles, properties, services, deals, news, events, jobs]
- `query` (string, optional) — Count over the results of this query instead of the whole index.
- `filters` (object, optional) — Structured filters, exactly as Qatar Living names them — 108 keys across the verticals. Lists for categorical keys, numbers for the min/max ones, booleans for the flags: `category`, `l1_category`, `l2_category`, `sub_vertical`, `brand`, `model`, `condition`, `color`, `location`, `zone`, `price` {min,max}, `is_freebie`, `is_featured`, `verified_only`, `freshness_days`, `date_from`/`date_to` · vehicles: `make`, `trim`, `year_min`/`year_max`/`year_int`, `mileage_max`, `fuel_type`, `gear_type`, `body_type`, `bike_type`, `boat_type`, `wheel_drive`, `seat_count`, `under_warranty`, `is_showroom`, `with_driver` · properties: `purpose`, `property_type`, `real_estate_type`, `bedrooms_min`/`bedrooms_max`, `bathrooms_min`, `furnishing`, `amenities`, `area_sqm_min`/`area_sqm_max`, `rent_frequency`, `ready_to_move`, `has_kahramaa` · deals: `agency_name`, `offer_type`, `sub_category`, `discount_percentage_min`, `is_deal_of_the_day` · geography: `geo` {lat, lon, radius_km}. An unknown key is rejected with the key named. Use the `facets` action to read the values a vertical publishes.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]

**Returns:** {vertical, query, total_matched, total_reported, facets{name:[{value, count}]}, vertical_counts{}, section_counts{}}. Counts are the source's own and are taken over the filtered set, so passing `filters` gives conditional counts (models within one make, bedrooms within one district).

**Example request body:**
```json
{
  "vertical": "vehicles",
  "facets": [
    "make",
    "body_type"
  ]
}
```

### POST https://api.reefapi.com/qatarliving/v1/deals_map — 2 credits
Every merchant offer matching a query as a map pin, one pin per branch and no paging — an offer with four branches becomes four pins with the same offer id and distinct coordinates. The whole of Qatar Living's deals catalogue on a map in a single call.

**Parameters:**
- `query` (string, optional) — Free text to narrow the pins; leave it out for every pin.
- `filters` (object, optional) — Structured filters, exactly as Qatar Living names them — 108 keys across the verticals. Lists for categorical keys, numbers for the min/max ones, booleans for the flags: `category`, `l1_category`, `l2_category`, `sub_vertical`, `brand`, `model`, `condition`, `color`, `location`, `zone`, `price` {min,max}, `is_freebie`, `is_featured`, `verified_only`, `freshness_days`, `date_from`/`date_to` · vehicles: `make`, `trim`, `year_min`/`year_max`/`year_int`, `mileage_max`, `fuel_type`, `gear_type`, `body_type`, `bike_type`, `boat_type`, `wheel_drive`, `seat_count`, `under_warranty`, `is_showroom`, `with_driver` · properties: `purpose`, `property_type`, `real_estate_type`, `bedrooms_min`/`bedrooms_max`, `bathrooms_min`, `furnishing`, `amenities`, `area_sqm_min`/`area_sqm_max`, `rent_frequency`, `ready_to_move`, `has_kahramaa` · deals: `agency_name`, `offer_type`, `sub_category`, `discount_percentage_min`, `is_deal_of_the_day` · geography: `geo` {lat, lon, radius_km}. An unknown key is rejected with the key named. Use the `facets` action to read the values a vertical publishes.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]

**Returns:** {count, pins[]} — each pin: offer_id, lat, lon, image (merchant logo path).

**Example request body:**
```json
{
  "filters": {
    "make": [
      "Toyota"
    ],
    "year_min": 2022
  }
}
```

### POST https://api.reefapi.com/qatarliving/v1/merchants_map — 2 credits
Every merchant whose offers match a query as a map pin, one pin per distinct branch and deduped across that merchant's offers — the merchant footprint behind the deals catalogue, with no paging.

**Parameters:**
- `query` (string, optional) — Free text to narrow the pins; leave it out for every pin.
- `filters` (object, optional) — Structured filters, exactly as Qatar Living names them — 108 keys across the verticals. Lists for categorical keys, numbers for the min/max ones, booleans for the flags: `category`, `l1_category`, `l2_category`, `sub_vertical`, `brand`, `model`, `condition`, `color`, `location`, `zone`, `price` {min,max}, `is_freebie`, `is_featured`, `verified_only`, `freshness_days`, `date_from`/`date_to` · vehicles: `make`, `trim`, `year_min`/`year_max`/`year_int`, `mileage_max`, `fuel_type`, `gear_type`, `body_type`, `bike_type`, `boat_type`, `wheel_drive`, `seat_count`, `under_warranty`, `is_showroom`, `with_driver` · properties: `purpose`, `property_type`, `real_estate_type`, `bedrooms_min`/`bedrooms_max`, `bathrooms_min`, `furnishing`, `amenities`, `area_sqm_min`/`area_sqm_max`, `rent_frequency`, `ready_to_move`, `has_kahramaa` · deals: `agency_name`, `offer_type`, `sub_category`, `discount_percentage_min`, `is_deal_of_the_day` · geography: `geo` {lat, lon, radius_km}. An unknown key is rejected with the key named. Use the `facets` action to read the values a vertical publishes.
- `lang` (enum, optional, default "en") — Response language. `ar` puts the Arabic text in the ORDINARY fields (title, category) — it does not fill `title_ar`; the `listing` action is the bilingual one. [one of: en, ar]

**Returns:** {count, pins[]} — each pin: agency_id, lat, lon, logo (merchant logo path).

**Example request body:**
```json
{
  "filters": {
    "make": [
      "Toyota"
    ],
    "year_min": 2022
  }
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=qatarliving
- Human docs page: https://reefapi.com/docs/qatarliving
- Overview page: https://reefapi.com/qatarliving-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
