# 4Sale Kuwait Classifieds (q84sale.com)

> Keyword search across every 4Sale vertical — cars, property, electronics, furniture, animals, jobs and services — with the price, images, district, category and both language versions of each listing. This is the only 4Sale surface that honours a free-text query.
> ReefAPI engine `q84sale` · 8 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/q84sale/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/q84sale/v1/search — 2 credits
Keyword search across every 4Sale vertical — cars, property, electronics, furniture, animals, jobs and services — with the price, images, district, category and both language versions of each listing. This is the only 4Sale surface that honours a free-text query.

**Parameters:**
- `query` (string, required) — Free-text query, exactly as a Kuwaiti buyer would type it. Arabic works best because that is what sellers write: `لاند كروزر` returned 1,825 hits where the Latin spelling `camry` returned 1,477 and `iphone` 1,432. An unknown term honestly returns 0 rows.
- `category_id` (integer, optional) — Restrict to one 4Sale category id (any level: vertical, group or leaf). Measured to bite: query `camry` gave 1,475 hits unfiltered, 1,335 inside used-cars (2897) and 0 inside mobile phones (99). The 14 top-level vertical SLUGS are also accepted.
- `sort` (enum, optional, default "relevance") — Result order. `relevance` is 4Sale's own default search order. [one of: relevance, newest, oldest, price_desc, price_asc]
- `page` (integer, optional, default 1) — 1-based result page. `total_pages` in the response is the real last page; asking past it returns zero rows (the source does not repeat the last page).
- `limit` (integer, optional, default 30) — Rows per page (1-50). 4Sale returns exactly this many organic rows until the last page.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Return the seller's display name and phone number. 4Sale publishes both on every listing; they are withheld by default. `seller_id` and `seller_is_business` are always returned.

**Returns:** {query, total_listings, total_pages, page, limit, sort, listings[], paid_placements[]}. Each listing: id, url, slug, title, title_is_arabic, description + description_translated + description_ar + description_en, price (null when the seller published none) and currency KWD, category_id, district_ids / district_name, published_at and bumped_at (ISO-8601 +03:00), image / thumbnail / thumbnails / images_count, is_premium, is_chat_enabled, status, seller_id, seller_is_business, attributes_raw (decode it with `category_attributes`), and seller_name / seller_phone only when include_pii.

**Example request body:**
```json
{
  "query": "camry",
  "limit": 20,
  "lang": "en"
}
```

### POST https://api.reefapi.com/q84sale/v1/category_listings — 2 credits
Browse one 4Sale category end to end, newest-first or by price — the whole Kuwaiti used-car, flat-to-rent or iPhone market as a paged feed. Returns the same listing shape as `search` plus the category names 4Sale attaches here.

**Parameters:**
- `category_id` (integer, required) — The 4Sale category to browse (any level). Use `suggest` to turn a keyword into a category id, or `category_path` to walk one. The 14 vertical slugs are accepted too (automotive, property, electronics, furniture, jobs …).
- `sort` (enum, optional, default "newest") — Result order. `newest` is 4Sale's own browse order. [one of: newest, oldest, price_desc, price_asc]
- `page` (integer, optional, default 1) — 1-based result page. `total_pages` in the response is the real last page; asking past it returns zero rows (the source does not repeat the last page).
- `limit` (integer, optional, default 30) — Rows per page (1-50). 4Sale returns exactly this many organic rows until the last page.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Return the seller's display name and phone number. 4Sale publishes both on every listing; they are withheld by default. `seller_id` and `seller_is_business` are always returned.

**Returns:** {category_id, total_listings, total_pages, page, limit, sort, listings[], paid_placements[]}. Listing shape as in `search`, and here category_name_en / category_name_ar are filled in by the source.

**Example request body:**
```json
{
  "category_id": 2897,
  "limit": 20,
  "sort": "newest"
}
```

### POST https://api.reefapi.com/q84sale/v1/listing — 2 credits
One listing in full: the seller's own text and its translation, price, the complete image set, the category breadcrumb, the view count, the publish and bump times, and the category attributes (Year, Mileage, Colour, Brand …) decoded into names and values.

**Parameters:**
- `id` (integer, optional) — 4Sale listing id — the trailing number of any listing URL (`/en/listing/cayenne-21238153` → 21238153). Give this or `url`.
- `url` (string, optional) — A 4Sale listing URL instead of an id; the id is read out of it.
- `include_attributes` (boolean, optional, default true) — Also download the listing category's attribute dictionary so `attributes` arrives named and decoded (Year, Mileage, Colour, Brand … instead of option ids). Costs one extra upstream call; turn it off if you already hold the dictionary from `category_attributes`.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]
- `include_pii` (boolean, optional, default false) — Return the seller's display name and phone number. 4Sale publishes both on every listing; they are withheld by default. `seller_id` and `seller_is_business` are always returned.

**Returns:** {id, url, slug, title, title_translated, description, description_translated, original_language, price, currency, category_id, category_name, category_path[] (leaf → vertical), vertical, district_id, published_at, created_at, bumped_at, expires_at, view_count, images[], images_count, is_premium, is_paid_placement, is_chat_enabled, status, source_app, seller_id, seller_member_since, seller_status, attributes[] {attribute_id, label, value, raw_value, is_option, unit}, attributes_raw[]}. seller_name / seller_phone only when include_pii. Either `id` or `url` must be given.

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

### POST https://api.reefapi.com/q84sale/v1/category_attributes — 1 credit
The filter attributes 4Sale defines for one category, with every drop-down option — the dictionary that turns `attributes_raw` on a listing row into real values, and the list of filters the site itself offers on that category.

**Parameters:**
- `category_id` (integer, required) — The 4Sale category whose filter attributes and option dictionary you want. Used cars (2897) publishes 42 attributes; a leaf model category such as Cayenne (2241) publishes 43, including the ones inherited from its parents.
- `filterable_only` (boolean, optional, default false) — Return only the attributes 4Sale itself exposes as search filters.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]

**Returns:** {category_id, attribute_count, attributes[]}. Each attribute: attribute_id, label (requested language), label_en, label_ar, type (drop_down / number / text …), unit, is_filterable, is_required, selection_type, min / max, options[] {id, label, label_en, label_ar}.

**Example request body:**
```json
{
  "category_id": 2897
}
```

### POST https://api.reefapi.com/q84sale/v1/category_path — 1 credit
A category's ancestor chain in both languages — leaf first up to one of 4Sale's 14 verticals. Use it to label a listing's category_id, or to walk from a model (Cayenne) up to its make and vertical.

**Parameters:**
- `category_id` (integer, required) — Any 4Sale category id; the answer is its chain up to the vertical, leaf first.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]

**Returns:** {category_id, depth, path[]} with the leaf first. Each node: id, parent_id, slug, name (requested language), name_en, name_ar, description_en, description_ar, is_leaf, image. Plus `vertical` {id, slug, name_en, name_ar} when the chain reaches one of the 14 verticals.

**Example request body:**
```json
{
  "category_id": 2897
}
```

### POST https://api.reefapi.com/q84sale/v1/suggest — 1 credit
4Sale's own search autocomplete: the keywords it recognises for what you typed and, for each, the category id and the predefined filters it maps that keyword onto. The cheapest way to turn a word into a category id.

**Parameters:**
- `query` (string, required) — Partial or complete keyword. 4Sale answers with the keywords it recognises and, for each, the category and predefined filters it maps that keyword to — which is how you turn a word into a `category_id` for `search` or `category_listings`.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]

**Returns:** {query, suggestion_count, suggestions[]} — each {keyword, display_name, category_id, predefined_filters} where predefined_filters is the attribute → option-id map 4Sale would apply for that keyword.

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

### POST https://api.reefapi.com/q84sale/v1/districts — 1 credit
Kuwait's geography as 4Sale publishes it: the six governorates, or the areas inside one of them. These are the ids that appear as `district_ids` on every listing.

**Parameters:**
- `district_id` (integer, optional, default 1) — Parent district to expand. 1 (the default) lists Kuwait's six governorates; pass one of those ids (e.g. 2 = Ahmadi) to get its areas.
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]

**Returns:** {district_id, district_count, districts[]} — each {id, parent_id, level, name (requested language), name_en, name_ar}.

**Example request body:**
```json
{
  "district_id": 1
}
```

### POST https://api.reefapi.com/q84sale/v1/trending — 1 credit
The search terms 4Sale is promoting as trending right now, in Arabic and English — a live read on what Kuwait is shopping for.

**Parameters:**
- `lang` (enum, optional, default "en") — Language 4Sale should answer in. Listings are written by Kuwaiti sellers, so most titles and descriptions are Arabic whatever you pick; this chooses which side of the machine translation is returned and which language category and attribute labels use. [one of: en, ar]

**Returns:** {title, trend_count, trends[]} — each {keyword, keyword_en, keyword_ar}.

**Example request body:**
```json
{
  "lang": "en"
}
```

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