# Syarah — Saudi Arabia car marketplace (used + new, SAR, Arabic + English)

> Search Syarah's Saudi car stock by free text (English or Arabic), make, model, trim, condition, seller type, body style, fuel, transmission, drivetrain, origin, colours, seats, cylinders, engine size, payment scheme, model year, price, mileage and monthly instalment, with seven verified sort orders. Every row carries price in SAR, mileage, year, trim, city, seller kind and the photo set. 🔴 Unlike the UAE marketplaces, the FULL result set is reachable here: a measured full walk returned 109 unique rows for a stated 109, and `summary.total_results` / `summary.reachable_results` always say both numbers.
> ReefAPI engine `syarah` · 8 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/syarah/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/syarah/v1/search — 2 credits
Search Syarah's Saudi car stock by free text (English or Arabic), make, model, trim, condition, seller type, body style, fuel, transmission, drivetrain, origin, colours, seats, cylinders, engine size, payment scheme, model year, price, mileage and monthly instalment, with seven verified sort orders. Every row carries price in SAR, mileage, year, trim, city, seller kind and the photo set. 🔴 Unlike the UAE marketplaces, the FULL result set is reachable here: a measured full walk returned 109 unique rows for a stated 109, and `summary.total_results` / `summary.reachable_results` always say both numbers.

**Parameters:**
- `text` (string, optional) — Free-text query, in English OR Arabic. Measured: `toyota`, `تويوتا` and `land cruiser` all resolve against the same index (673 / 673 / 39 rows) and a nonsense term honestly returns 0. Unlike the id filters this also matches trims and body words.
- `make_id` (integer, optional) — Numeric make id as syarah publishes it (Toyota 4, Hyundai 60, Kia 38, Nissan 58, Suzuki 33, MG 78, Lexus 48, BMW 15). Call `makes` for all 65 with live counts.
- `model_id` (integer, optional) — Numeric model id. 🔴 Only bites together with `make_id` — on its own syarah swallows it and returns the whole catalogue, so this engine rejects that combination. `models` gives the pair.
- `trim_id` (integer, optional) — Numeric trim id. Requires BOTH `make_id` and `model_id`. The `filters` action lists trims with their parent make/model ids.
- `condition` (enum, optional) — New or used. Measured bite: `new` 796 of 3,674, `used` 2,878. New stock carries no odometer reading at all (19/19 of the new rows sampled). [one of: used, new]
- `seller_type` (enum, optional) — Who owns the car. `syarah` is Syarah's own inspected inventory (sits in Riyadh), `dealer` is third-party dealer stock (Al Qurayyat, Dammam, Jeddah …). Measured split 1,769 / 1,905, and the two sum exactly to the site total. [one of: syarah, dealer]
- `fuel` (enum, optional) — Fuel type. [one of: gasoline, diesel, hybrid, electric]
- `transmission` (enum, optional) — Gearbox type. [one of: automatic, cvt, manual]
- `drivetrain` (enum, optional) — Drive configuration. [one of: fwd, 4x4, rwd, 4wd, awd]
- `body_shape` (enum, optional) — Body style as syarah classifies it. [one of: sedan, suv, crossover, pickup, van, hatchback, sport]
- `origin` (enum, optional) — Where the car was specified for. [one of: saudi, gcc, other]
- `category` (enum, optional) — Syarah's own buyer-intent grouping. [one of: family, off-road, budget, economic, luxury, sports]
- `make_country` (enum, optional) — Country the brand comes from. [one of: japan, korea, china, america, german, france, british, italy, india]
- `payment` (enum, optional) — Accepted payment / instalment scheme. [one of: cash, cash_and_finance, tamara, tabby, amwal]
- `exterior_color_id` (integer, optional) — Exterior colour id (White 1, Black 2, Silver 3, Grey 10, Leaden 26 — 32 colours). `filters` lists them all with counts and hex codes.
- `interior_color_id` (integer, optional) — Interior colour id (Beige 16, Black 2, Grey 10, Camel 17 — 24 values).
- `cylinders` (integer, optional) — Cylinder count (3, 4, 5, 6 or 8).
- `seats` (integer, optional) — Seat count (2-26; 5 seats = 2,936 of 3,674).
- `cabins` (integer, optional) — Pickup cabin count: 1 = single cab (26 rows), 2 = double cab (83).
- `engine_size` (string, optional) — Engine displacement exactly as syarah labels it ('1.5', '2.0', '2.5', '5.7' — 34 values).
- `feature_ids` (string, optional) — Equipment / feature ids, comma-separated. Measured bite: 15 (Rear Camera) → 2,121 of 3,674 · 6 (Cruise Control) → 2,838 · 20 (Alloy wheels) → 3,005. 🔴 Several ids are OR'd by the source, not AND'd ("15,6" → 3,076, i.e. more cars, not fewer). The `filters` action lists every feature id with its live count under the popular / comfort / technology / safety / exterior groups.
- `deal_id` (integer, optional) — Syarah's own running campaign id (the `deal` block of any search answer names the current one). Measured: deal 124 'Last Chance' held 23 cars.
- `booked` (boolean, optional) — Restrict to cars already reserved (true, 506 rows) or still open (false, 3,168).
- `year_min` (integer, optional) — Earliest model year. 🔴 A one-sided range is IGNORED by syarah, so if you omit `year_max` this engine supplies the source's own upper bound and says so in `meta.warnings`.
- `year_max` (integer, optional) — Latest model year (inclusive).
- `price_min` (integer, optional) — Lowest asking price, in the currency the answer reports (SAR on every measured call).
- `price_max` (integer, optional) — Highest asking price.
- `km_min` (integer, optional) — Lowest odometer reading in kilometres.
- `km_max` (integer, optional) — Highest odometer reading in kilometres. Measured bite: 0-20,000 km = 1,128 of 3,674.
- `installment_min` (integer, optional) — Lowest monthly instalment. 🔴 Any instalment range also drops the 1,218 cars that carry no instalment at all (measured: the widest possible range returns 2,456 of 3,674).
- `installment_max` (integer, optional) — Highest monthly instalment.
- `sort` (enum, optional, default "newest") — Result order. 🔴 `newest` is the site's own `-first_active_date` and was MEASURED to be a real listing date, not a refresh/bump: 12/12 rows on page 1 were listed the previous day (`days_on_lot` 0-1) while the default order mixed cars 3 to 83 days old. The date itself comes back from `detail.listed_at`. [one of: relevance, newest, price_asc, price_desc, km_asc, km_desc, discount_desc]
- `page` (integer, optional, default 1) — 1-based page. There is no artificial ceiling on this source: a page past the end returns an empty list, never a silent repeat of the last page.
- `page_size` (integer, optional, default 24) — Rows per upstream page. syarah itself refuses more than 100 (HTTP 400 with that exact message), so the maximum here is 100.
- `max_results` (integer, optional, default 24) — Stop after this many rows, walking upstream pages of `page_size`. Capped at 1000 per call; to go deeper, page or narrow the query.
- `lang` (enum, optional, default "en") — Language of the LABELS in the answer (make/model/colour/fuel names). The id filters and the `text` query work the same on both. [one of: en, ar]

**Returns:** `rows[]` plus a `summary`. Each row: id, url, title, price, price_currency (read back from the source, never hard-coded), price_disagrees, monthly_installment, discount, price_before_discount, year, make, model, trim, condition, kilometers (+ kilometers_unit, kilometers_reported), fuel_type, transmission, drivetrain, engine_size, exterior_color, interior_color, car_origin, city, seller_type (syarah | dealer | individual) + seller_label, financing_available, is_booked, has_tamara, warranty + warranty_label, tags[], image, preview_photos[] + preview_photos_count, position. `summary` carries total_results (the source's own count for this query), reachable_results, last_page, page, page_size, has_more, filters_applied, sort, currency and deal (the campaign the site is running). 🔴 `discount` is the price CUT; `price_before_discount` is the pre-cut price (measured: price + discount == price_before_discount on 59/59 discounted rows). 🔴 `preview_photos` is the search service's 5-thumbnail preview, NOT the gallery — the same car carried 32 photos on `detail`. 🔴 `cylinders` and `cabins` are not returned on search rows (0/278 filled, measured) although both work as filters; `detail` publishes them. 🔴 search rows carry NO listing date: use `sort=newest` for the order and `detail.listed_at` for the date.

**Example request body:**
```json
{
  "make_id": 4,
  "condition": "used",
  "sort": "newest",
  "max_results": 24
}
```

### POST https://api.reefapi.com/syarah/v1/detail — 1 credit
The full record for one listing: the complete spec card (body style, fuel, transmission and gear count, drivetrain, cylinders, engine size and type, seats, doors, key count, both colours with hex codes, origin), the option list grouped by Safety / Comfort / Technology / Exterior, every gallery photo, the financing breakdown, the inspection-report link — and the listing's REAL first-activation date plus how many days it has been on the lot. Takes the numeric id from a `search` row or the listing URL.

**Parameters:**
- `id` (string, required) — Listing id as `search` returns it in `rows[].id` (e.g. 316148). A full syarah listing URL is accepted too — the id is read out of its slug.
- `lang` (enum, optional, default "en") — Language of the labels. ⚠️ A few trim names come back in Arabic even on the English surface — that is how the source stores them. [one of: en, ar]

**Returns:** One listing in full: id, url, title, headline, price / price_currency / price_display / price_note, price_disagrees + price_witnesses (three independent numbers off the same payload), discount + price_before_discount, monthly_installment + installment_months / first / last payment, financing_available, make (+ make_id), model (+ model_id), trim (+ trim_id), year, condition, kilometers, body_shape, fuel_type, transmission, gear_speeds, drivetrain, cylinders, engine_size, engine_type, horsepower, fuel_tank_litres, seats, doors, number_of_keys, both colours with their hex codes, car_origin, city, seller_type + seller_label, **listed_at (the real first-activation date) and days_on_lot**, is_sold, is_deleted, limited_quantity, is_preowned_programme, warranty, tags[], features[] grouped by category + features_count, photos[] + photos_count, has_video, faqs[]. VIN is NOT returned: the listing page prints a placeholder of zeros, so there is nothing true to publish.

**Example request body:**
```json
{
  "id": "316148"
}
```

### POST https://api.reefapi.com/syarah/v1/count — 1 credit
How many cars match a filter combination, from Syarah's own count — one tiny request, no row parsing. Built for market sizing: combine make, body style, fuel, price band and seller type and read the number back. Also reports whether the whole set is walkable and in how many pages.

**Parameters:**
- `text` (string, optional) — Free-text query, in English OR Arabic. Measured: `toyota`, `تويوتا` and `land cruiser` all resolve against the same index (673 / 673 / 39 rows) and a nonsense term honestly returns 0. Unlike the id filters this also matches trims and body words.
- `make_id` (integer, optional) — Numeric make id as syarah publishes it (Toyota 4, Hyundai 60, Kia 38, Nissan 58, Suzuki 33, MG 78, Lexus 48, BMW 15). Call `makes` for all 65 with live counts.
- `model_id` (integer, optional) — Numeric model id. 🔴 Only bites together with `make_id` — on its own syarah swallows it and returns the whole catalogue, so this engine rejects that combination. `models` gives the pair.
- `trim_id` (integer, optional) — Numeric trim id. Requires BOTH `make_id` and `model_id`. The `filters` action lists trims with their parent make/model ids.
- `condition` (enum, optional) — New or used. Measured bite: `new` 796 of 3,674, `used` 2,878. New stock carries no odometer reading at all (19/19 of the new rows sampled). [one of: used, new]
- `seller_type` (enum, optional) — Who owns the car. `syarah` is Syarah's own inspected inventory (sits in Riyadh), `dealer` is third-party dealer stock (Al Qurayyat, Dammam, Jeddah …). Measured split 1,769 / 1,905, and the two sum exactly to the site total. [one of: syarah, dealer]
- `fuel` (enum, optional) — Fuel type. [one of: gasoline, diesel, hybrid, electric]
- `transmission` (enum, optional) — Gearbox type. [one of: automatic, cvt, manual]
- `drivetrain` (enum, optional) — Drive configuration. [one of: fwd, 4x4, rwd, 4wd, awd]
- `body_shape` (enum, optional) — Body style as syarah classifies it. [one of: sedan, suv, crossover, pickup, van, hatchback, sport]
- `origin` (enum, optional) — Where the car was specified for. [one of: saudi, gcc, other]
- `category` (enum, optional) — Syarah's own buyer-intent grouping. [one of: family, off-road, budget, economic, luxury, sports]
- `make_country` (enum, optional) — Country the brand comes from. [one of: japan, korea, china, america, german, france, british, italy, india]
- `payment` (enum, optional) — Accepted payment / instalment scheme. [one of: cash, cash_and_finance, tamara, tabby, amwal]
- `exterior_color_id` (integer, optional) — Exterior colour id (White 1, Black 2, Silver 3, Grey 10, Leaden 26 — 32 colours). `filters` lists them all with counts and hex codes.
- `interior_color_id` (integer, optional) — Interior colour id (Beige 16, Black 2, Grey 10, Camel 17 — 24 values).
- `cylinders` (integer, optional) — Cylinder count (3, 4, 5, 6 or 8).
- `seats` (integer, optional) — Seat count (2-26; 5 seats = 2,936 of 3,674).
- `cabins` (integer, optional) — Pickup cabin count: 1 = single cab (26 rows), 2 = double cab (83).
- `engine_size` (string, optional) — Engine displacement exactly as syarah labels it ('1.5', '2.0', '2.5', '5.7' — 34 values).
- `feature_ids` (string, optional) — Equipment / feature ids, comma-separated. Measured bite: 15 (Rear Camera) → 2,121 of 3,674 · 6 (Cruise Control) → 2,838 · 20 (Alloy wheels) → 3,005. 🔴 Several ids are OR'd by the source, not AND'd ("15,6" → 3,076, i.e. more cars, not fewer). The `filters` action lists every feature id with its live count under the popular / comfort / technology / safety / exterior groups.
- `deal_id` (integer, optional) — Syarah's own running campaign id (the `deal` block of any search answer names the current one). Measured: deal 124 'Last Chance' held 23 cars.
- `booked` (boolean, optional) — Restrict to cars already reserved (true, 506 rows) or still open (false, 3,168).
- `year_min` (integer, optional) — Earliest model year. 🔴 A one-sided range is IGNORED by syarah, so if you omit `year_max` this engine supplies the source's own upper bound and says so in `meta.warnings`.
- `year_max` (integer, optional) — Latest model year (inclusive).
- `price_min` (integer, optional) — Lowest asking price, in the currency the answer reports (SAR on every measured call).
- `price_max` (integer, optional) — Highest asking price.
- `km_min` (integer, optional) — Lowest odometer reading in kilometres.
- `km_max` (integer, optional) — Highest odometer reading in kilometres. Measured bite: 0-20,000 km = 1,128 of 3,674.
- `installment_min` (integer, optional) — Lowest monthly instalment. 🔴 Any instalment range also drops the 1,218 cars that carry no instalment at all (measured: the widest possible range returns 2,456 of 3,674).
- `installment_max` (integer, optional) — Highest monthly instalment.
- `lang` (enum, optional, default "en") — Language of the LABELS in the answer (make/model/colour/fuel names). The id filters and the `text` query work the same on both. [one of: en, ar]

**Returns:** `{total_results, reachable_results, fully_reachable, pages_at_100, currency, filters_applied, deal}`. On this source `reachable_results` has equalled `total_results` on every measured query.

**Example request body:**
```json
{
  "make_id": 4,
  "condition": "used"
}
```

### POST https://api.reefapi.com/syarah/v1/makes — 2 credits
Every car make Syarah currently lists, with the numeric `make_id` that `search`, `count` and `models` take, the live stock count and the brand logo. 65 makes / 3,674 cars at capture. Accepts the same filters as `search`, so you can ask "which brands have hybrids under 80,000 SAR" in one call.

**Parameters:**
- `text` (string, optional) — Free-text query, in English OR Arabic. Measured: `toyota`, `تويوتا` and `land cruiser` all resolve against the same index (673 / 673 / 39 rows) and a nonsense term honestly returns 0. Unlike the id filters this also matches trims and body words.
- `make_id` (integer, optional) — Numeric make id as syarah publishes it (Toyota 4, Hyundai 60, Kia 38, Nissan 58, Suzuki 33, MG 78, Lexus 48, BMW 15). Call `makes` for all 65 with live counts.
- `model_id` (integer, optional) — Numeric model id. 🔴 Only bites together with `make_id` — on its own syarah swallows it and returns the whole catalogue, so this engine rejects that combination. `models` gives the pair.
- `trim_id` (integer, optional) — Numeric trim id. Requires BOTH `make_id` and `model_id`. The `filters` action lists trims with their parent make/model ids.
- `condition` (enum, optional) — New or used. Measured bite: `new` 796 of 3,674, `used` 2,878. New stock carries no odometer reading at all (19/19 of the new rows sampled). [one of: used, new]
- `seller_type` (enum, optional) — Who owns the car. `syarah` is Syarah's own inspected inventory (sits in Riyadh), `dealer` is third-party dealer stock (Al Qurayyat, Dammam, Jeddah …). Measured split 1,769 / 1,905, and the two sum exactly to the site total. [one of: syarah, dealer]
- `fuel` (enum, optional) — Fuel type. [one of: gasoline, diesel, hybrid, electric]
- `transmission` (enum, optional) — Gearbox type. [one of: automatic, cvt, manual]
- `drivetrain` (enum, optional) — Drive configuration. [one of: fwd, 4x4, rwd, 4wd, awd]
- `body_shape` (enum, optional) — Body style as syarah classifies it. [one of: sedan, suv, crossover, pickup, van, hatchback, sport]
- `origin` (enum, optional) — Where the car was specified for. [one of: saudi, gcc, other]
- `category` (enum, optional) — Syarah's own buyer-intent grouping. [one of: family, off-road, budget, economic, luxury, sports]
- `make_country` (enum, optional) — Country the brand comes from. [one of: japan, korea, china, america, german, france, british, italy, india]
- `payment` (enum, optional) — Accepted payment / instalment scheme. [one of: cash, cash_and_finance, tamara, tabby, amwal]
- `exterior_color_id` (integer, optional) — Exterior colour id (White 1, Black 2, Silver 3, Grey 10, Leaden 26 — 32 colours). `filters` lists them all with counts and hex codes.
- `interior_color_id` (integer, optional) — Interior colour id (Beige 16, Black 2, Grey 10, Camel 17 — 24 values).
- `cylinders` (integer, optional) — Cylinder count (3, 4, 5, 6 or 8).
- `seats` (integer, optional) — Seat count (2-26; 5 seats = 2,936 of 3,674).
- `cabins` (integer, optional) — Pickup cabin count: 1 = single cab (26 rows), 2 = double cab (83).
- `engine_size` (string, optional) — Engine displacement exactly as syarah labels it ('1.5', '2.0', '2.5', '5.7' — 34 values).
- `feature_ids` (string, optional) — Equipment / feature ids, comma-separated. Measured bite: 15 (Rear Camera) → 2,121 of 3,674 · 6 (Cruise Control) → 2,838 · 20 (Alloy wheels) → 3,005. 🔴 Several ids are OR'd by the source, not AND'd ("15,6" → 3,076, i.e. more cars, not fewer). The `filters` action lists every feature id with its live count under the popular / comfort / technology / safety / exterior groups.
- `deal_id` (integer, optional) — Syarah's own running campaign id (the `deal` block of any search answer names the current one). Measured: deal 124 'Last Chance' held 23 cars.
- `booked` (boolean, optional) — Restrict to cars already reserved (true, 506 rows) or still open (false, 3,168).
- `year_min` (integer, optional) — Earliest model year. 🔴 A one-sided range is IGNORED by syarah, so if you omit `year_max` this engine supplies the source's own upper bound and says so in `meta.warnings`.
- `year_max` (integer, optional) — Latest model year (inclusive).
- `price_min` (integer, optional) — Lowest asking price, in the currency the answer reports (SAR on every measured call).
- `price_max` (integer, optional) — Highest asking price.
- `km_min` (integer, optional) — Lowest odometer reading in kilometres.
- `km_max` (integer, optional) — Highest odometer reading in kilometres. Measured bite: 0-20,000 km = 1,128 of 3,674.
- `installment_min` (integer, optional) — Lowest monthly instalment. 🔴 Any instalment range also drops the 1,218 cars that carry no instalment at all (measured: the widest possible range returns 2,456 of 3,674).
- `installment_max` (integer, optional) — Highest monthly instalment.
- `lang` (enum, optional, default "en") — Language of the LABELS in the answer (make/model/colour/fuel names). The id filters and the `text` query work the same on both. [one of: en, ar]

**Returns:** `rows[]` of {make_id, name, name_en, name_ar, count, logo} ordered by stock, plus `summary.total_results` for the same query.

**Example request body:**
```json
{
  "text": "land cruiser"
}
```

### POST https://api.reefapi.com/syarah/v1/models — 2 credits
Every model Syarah lists, with the numeric `model_id` that `search` takes and the parent `make_id` it must be paired with. Omit `make_id` for all 337 models across every brand; pass one to scope it (MG 78 → 8 models).

**Parameters:**
- `text` (string, optional) — Free-text query, in English OR Arabic. Measured: `toyota`, `تويوتا` and `land cruiser` all resolve against the same index (673 / 673 / 39 rows) and a nonsense term honestly returns 0. Unlike the id filters this also matches trims and body words.
- `make_id` (integer, optional) — Numeric make id as syarah publishes it (Toyota 4, Hyundai 60, Kia 38, Nissan 58, Suzuki 33, MG 78, Lexus 48, BMW 15). Call `makes` for all 65 with live counts.
- `model_id` (integer, optional) — Numeric model id. 🔴 Only bites together with `make_id` — on its own syarah swallows it and returns the whole catalogue, so this engine rejects that combination. `models` gives the pair.
- `trim_id` (integer, optional) — Numeric trim id. Requires BOTH `make_id` and `model_id`. The `filters` action lists trims with their parent make/model ids.
- `condition` (enum, optional) — New or used. Measured bite: `new` 796 of 3,674, `used` 2,878. New stock carries no odometer reading at all (19/19 of the new rows sampled). [one of: used, new]
- `seller_type` (enum, optional) — Who owns the car. `syarah` is Syarah's own inspected inventory (sits in Riyadh), `dealer` is third-party dealer stock (Al Qurayyat, Dammam, Jeddah …). Measured split 1,769 / 1,905, and the two sum exactly to the site total. [one of: syarah, dealer]
- `fuel` (enum, optional) — Fuel type. [one of: gasoline, diesel, hybrid, electric]
- `transmission` (enum, optional) — Gearbox type. [one of: automatic, cvt, manual]
- `drivetrain` (enum, optional) — Drive configuration. [one of: fwd, 4x4, rwd, 4wd, awd]
- `body_shape` (enum, optional) — Body style as syarah classifies it. [one of: sedan, suv, crossover, pickup, van, hatchback, sport]
- `origin` (enum, optional) — Where the car was specified for. [one of: saudi, gcc, other]
- `category` (enum, optional) — Syarah's own buyer-intent grouping. [one of: family, off-road, budget, economic, luxury, sports]
- `make_country` (enum, optional) — Country the brand comes from. [one of: japan, korea, china, america, german, france, british, italy, india]
- `payment` (enum, optional) — Accepted payment / instalment scheme. [one of: cash, cash_and_finance, tamara, tabby, amwal]
- `exterior_color_id` (integer, optional) — Exterior colour id (White 1, Black 2, Silver 3, Grey 10, Leaden 26 — 32 colours). `filters` lists them all with counts and hex codes.
- `interior_color_id` (integer, optional) — Interior colour id (Beige 16, Black 2, Grey 10, Camel 17 — 24 values).
- `cylinders` (integer, optional) — Cylinder count (3, 4, 5, 6 or 8).
- `seats` (integer, optional) — Seat count (2-26; 5 seats = 2,936 of 3,674).
- `cabins` (integer, optional) — Pickup cabin count: 1 = single cab (26 rows), 2 = double cab (83).
- `engine_size` (string, optional) — Engine displacement exactly as syarah labels it ('1.5', '2.0', '2.5', '5.7' — 34 values).
- `feature_ids` (string, optional) — Equipment / feature ids, comma-separated. Measured bite: 15 (Rear Camera) → 2,121 of 3,674 · 6 (Cruise Control) → 2,838 · 20 (Alloy wheels) → 3,005. 🔴 Several ids are OR'd by the source, not AND'd ("15,6" → 3,076, i.e. more cars, not fewer). The `filters` action lists every feature id with its live count under the popular / comfort / technology / safety / exterior groups.
- `deal_id` (integer, optional) — Syarah's own running campaign id (the `deal` block of any search answer names the current one). Measured: deal 124 'Last Chance' held 23 cars.
- `booked` (boolean, optional) — Restrict to cars already reserved (true, 506 rows) or still open (false, 3,168).
- `year_min` (integer, optional) — Earliest model year. 🔴 A one-sided range is IGNORED by syarah, so if you omit `year_max` this engine supplies the source's own upper bound and says so in `meta.warnings`.
- `year_max` (integer, optional) — Latest model year (inclusive).
- `price_min` (integer, optional) — Lowest asking price, in the currency the answer reports (SAR on every measured call).
- `price_max` (integer, optional) — Highest asking price.
- `km_min` (integer, optional) — Lowest odometer reading in kilometres.
- `km_max` (integer, optional) — Highest odometer reading in kilometres. Measured bite: 0-20,000 km = 1,128 of 3,674.
- `installment_min` (integer, optional) — Lowest monthly instalment. 🔴 Any instalment range also drops the 1,218 cars that carry no instalment at all (measured: the widest possible range returns 2,456 of 3,674).
- `installment_max` (integer, optional) — Highest monthly instalment.
- `lang` (enum, optional, default "en") — Language of the LABELS in the answer (make/model/colour/fuel names). The id filters and the `text` query work the same on both. [one of: en, ar]

**Returns:** `rows[]` of {model_id, name, name_en, name_ar, count, make_id, make_name}. 🔴 `model_id` only filters when sent together with its `make_id`.

**Example request body:**
```json
{
  "make_id": 4
}
```

### POST https://api.reefapi.com/syarah/v1/filters — 2 credits
The complete, live filter vocabulary Syarah publishes: every enum (condition, seller type, fuel, transmission, drivetrain, body shape, origin, category, make country, payment scheme, 32 exterior and 24 interior colours with hex codes, cylinders, seats, cabins, 34 engine sizes, makes, models, trims) with its live stock count, and the real bounds of the four numeric ranges (year, price, odometer, monthly instalment) with their source-published units. Read this before building a faceted query instead of guessing ids.

**Parameters:**
- `text` (string, optional) — Free-text query, in English OR Arabic. Measured: `toyota`, `تويوتا` and `land cruiser` all resolve against the same index (673 / 673 / 39 rows) and a nonsense term honestly returns 0. Unlike the id filters this also matches trims and body words.
- `make_id` (integer, optional) — Numeric make id as syarah publishes it (Toyota 4, Hyundai 60, Kia 38, Nissan 58, Suzuki 33, MG 78, Lexus 48, BMW 15). Call `makes` for all 65 with live counts.
- `model_id` (integer, optional) — Numeric model id. 🔴 Only bites together with `make_id` — on its own syarah swallows it and returns the whole catalogue, so this engine rejects that combination. `models` gives the pair.
- `trim_id` (integer, optional) — Numeric trim id. Requires BOTH `make_id` and `model_id`. The `filters` action lists trims with their parent make/model ids.
- `condition` (enum, optional) — New or used. Measured bite: `new` 796 of 3,674, `used` 2,878. New stock carries no odometer reading at all (19/19 of the new rows sampled). [one of: used, new]
- `seller_type` (enum, optional) — Who owns the car. `syarah` is Syarah's own inspected inventory (sits in Riyadh), `dealer` is third-party dealer stock (Al Qurayyat, Dammam, Jeddah …). Measured split 1,769 / 1,905, and the two sum exactly to the site total. [one of: syarah, dealer]
- `fuel` (enum, optional) — Fuel type. [one of: gasoline, diesel, hybrid, electric]
- `transmission` (enum, optional) — Gearbox type. [one of: automatic, cvt, manual]
- `drivetrain` (enum, optional) — Drive configuration. [one of: fwd, 4x4, rwd, 4wd, awd]
- `body_shape` (enum, optional) — Body style as syarah classifies it. [one of: sedan, suv, crossover, pickup, van, hatchback, sport]
- `origin` (enum, optional) — Where the car was specified for. [one of: saudi, gcc, other]
- `category` (enum, optional) — Syarah's own buyer-intent grouping. [one of: family, off-road, budget, economic, luxury, sports]
- `make_country` (enum, optional) — Country the brand comes from. [one of: japan, korea, china, america, german, france, british, italy, india]
- `payment` (enum, optional) — Accepted payment / instalment scheme. [one of: cash, cash_and_finance, tamara, tabby, amwal]
- `exterior_color_id` (integer, optional) — Exterior colour id (White 1, Black 2, Silver 3, Grey 10, Leaden 26 — 32 colours). `filters` lists them all with counts and hex codes.
- `interior_color_id` (integer, optional) — Interior colour id (Beige 16, Black 2, Grey 10, Camel 17 — 24 values).
- `cylinders` (integer, optional) — Cylinder count (3, 4, 5, 6 or 8).
- `seats` (integer, optional) — Seat count (2-26; 5 seats = 2,936 of 3,674).
- `cabins` (integer, optional) — Pickup cabin count: 1 = single cab (26 rows), 2 = double cab (83).
- `engine_size` (string, optional) — Engine displacement exactly as syarah labels it ('1.5', '2.0', '2.5', '5.7' — 34 values).
- `feature_ids` (string, optional) — Equipment / feature ids, comma-separated. Measured bite: 15 (Rear Camera) → 2,121 of 3,674 · 6 (Cruise Control) → 2,838 · 20 (Alloy wheels) → 3,005. 🔴 Several ids are OR'd by the source, not AND'd ("15,6" → 3,076, i.e. more cars, not fewer). The `filters` action lists every feature id with its live count under the popular / comfort / technology / safety / exterior groups.
- `deal_id` (integer, optional) — Syarah's own running campaign id (the `deal` block of any search answer names the current one). Measured: deal 124 'Last Chance' held 23 cars.
- `booked` (boolean, optional) — Restrict to cars already reserved (true, 506 rows) or still open (false, 3,168).
- `year_min` (integer, optional) — Earliest model year. 🔴 A one-sided range is IGNORED by syarah, so if you omit `year_max` this engine supplies the source's own upper bound and says so in `meta.warnings`.
- `year_max` (integer, optional) — Latest model year (inclusive).
- `price_min` (integer, optional) — Lowest asking price, in the currency the answer reports (SAR on every measured call).
- `price_max` (integer, optional) — Highest asking price.
- `km_min` (integer, optional) — Lowest odometer reading in kilometres.
- `km_max` (integer, optional) — Highest odometer reading in kilometres. Measured bite: 0-20,000 km = 1,128 of 3,674.
- `installment_min` (integer, optional) — Lowest monthly instalment. 🔴 Any instalment range also drops the 1,218 cars that carry no instalment at all (measured: the widest possible range returns 2,456 of 3,674).
- `installment_max` (integer, optional) — Highest monthly instalment.
- `lang` (enum, optional, default "en") — Language of the LABELS in the answer (make/model/colour/fuel names). The id filters and the `text` query work the same on both. [one of: en, ar]

**Returns:** `{enums{<field>: [{id, name, name_en, name_ar, count, hex_code?, parent_ids?}]}, ranges{<field>: {start, end, gap, unit}}, total_results, currency}`. Field names are the source's own.

**Example request body:**
```json
{
  "text": "land cruiser"
}
```

### POST https://api.reefapi.com/syarah/v1/suggest — 1 credit
Syarah's own type-ahead for a partial query, in English or Arabic. Use it to turn a shopper's half-typed phrase into terms the `text` filter actually matches. 182 bytes a call.

**Parameters:**
- `q` (string, required) — Partial query, English or Arabic ('camry', 'كامري', 'land cru').
- `lang` (enum, optional, default "en") — Language surface. [one of: en, ar]

**Returns:** `rows[]` of {suggestion} in the source's own order.

**Example request body:**
```json
{
  "q": "camry"
}
```

### POST https://api.reefapi.com/syarah/v1/batch — 2 credits
Up to 100 listings' search-shaped rows in ONE request — the cheap way to re-check prices and availability on a watchlist instead of calling `detail` per car. Returns the same row shape as `search`, plus the ids that no longer exist so a disappeared listing is visible rather than silently missing.

**Parameters:**
- `ids` (array, required) — Listing ids (array, or a comma-separated string). At most 100 per call — measured working at 100 ids / 209 KB in a single request.
- `lang` (enum, optional, default "en") — Language of the labels. [one of: en, ar]

**Returns:** `{rows[], found, requested, missing_ids[]}` — rows in the `search` shape. `missing_ids` are the requested ids the source did not return.

**Example request body:**
```json
{
  "ids": [
    "316148",
    "319173"
  ]
}
```

## 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=syarah
- Human docs page: https://reefapi.com/docs/syarah
- Overview page: https://reefapi.com/syarah-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
