# Jiji API — Africa's largest classifieds network (Nigeria, Ghana, Kenya, Tanzania, Uganda) and Bangladesh's bikroy.com, which runs on the same platform. Search every vertical with the site's own filters, read an ad in full with the seller's published contact, follow a seller's whole stock and their buyer feedback, and get the category, region and filter lists free.

> Search a Jiji storefront across every vertical — vehicles, property, electronics, phones, jobs, services, fashion, home and garden, babies, agriculture, animals — by keyword and/or category, with the filters that category actually publishes. Each row carries the ad id and URL, title, price in local currency, the category's own attributes (a car's condition and transmission, a flat's bedrooms, a phone's storage), the state and town, the cover photo, the seller's account and rating, and Jiji's own trust labels. 🔴 Jiji ACCEPTS a filter name it does not know and returns the unfiltered list — `make=Toyota` and `region=137` both did — so every filter you send is checked against Jiji's published schema first and a wrong one comes back as an error naming the ones that exist. Jiji's paid TOP ads come back in a separate `promoted` list, never mixed into `results` or `count`: they sit in a fixed slot on every page and would repeat from page to page.
> ReefAPI engine `jiji` · 10 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/jiji/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/jiji/v1/search — 2 credits
Search a Jiji storefront across every vertical — vehicles, property, electronics, phones, jobs, services, fashion, home and garden, babies, agriculture, animals — by keyword and/or category, with the filters that category actually publishes. Each row carries the ad id and URL, title, price in local currency, the category's own attributes (a car's condition and transmission, a flat's bedrooms, a phone's storage), the state and town, the cover photo, the seller's account and rating, and Jiji's own trust labels. 🔴 Jiji ACCEPTS a filter name it does not know and returns the unfiltered list — `make=Toyota` and `region=137` both did — so every filter you send is checked against Jiji's published schema first and a wrong one comes back as an error naming the ones that exist. Jiji's paid TOP ads come back in a separate `promoted` list, never mixed into `results` or `count`: they sit in a fixed slot on every page and would repeat from page to page.

**Parameters:**
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `query` (string, optional) — Free-text search, e.g. 'toyota camry', 'iphone 15', '3 bedroom flat'. Combine with `category` to search inside one vertical.
- `category` (string, optional) — A category by slug, numeric id or name — `cars`, `mobile-phones`, `houses-apartments-for-rent`, `jobs`, 29, 'Cars'. Validated against Jiji's own tree (the free `categories` action), because Jiji answers an unknown category slug with the WHOLE site instead of an error.
- `region` (string, optional) — A state / city / district by slug, id or name — `lagos`, `nairobi`, `greater-accra`, `dhaka`, 119. The free `regions` action lists every one.
- `price_min` (number, optional) — Lowest price, in the country's own currency.
- `price_max` (number, optional) — Highest price, in the country's own currency.
- `filters` (string, optional) — Category filters, as `name=value` pairs separated by ';' (or a JSON object). Names and values are the ones Jiji itself publishes for that category — ask the free `filters` action. Ranges take `from-to`, `from-` or `-to`. Several values for one filter are comma-separated. Examples: `make=Toyota;model=Camry`, `condition=Foreign Used;year_of_manufacture=2018-2021`, `colour=Black,Blue;mileage=-80000`. A name Jiji does not publish is REJECTED rather than silently ignored — see the action description.
- `sort` (enum, optional, default "relevance") — Result order. `relevance` is Jiji's own Recommended order, which the site re-ranks on every request (paid ranking), so paging through it can return a few adverts twice and skip others. To walk every page of a search, use `newest`: its order is stable from page to page. [one of: relevance, newest, price_asc, price_desc]
- `posted_within` (enum, optional) — Only ads posted in the last hour or the last day. [one of: hour, day]
- `page` (integer, optional, default 1) — Which page of results to start from (1-based). Jiji's own window ends at `total_pages`; asking past it is an error, never an empty page.
- `limit` (integer, optional, default 24) — How many ads to return in `results`, 1-96. Jiji's page is fixed at 24 slots and cannot be widened, so anything above 24 is fetched as consecutive pages. Jiji's paid TOP ads take 1-5 of those slots and are returned in `promoted` instead, so one page usually yields 19-23 results.

**Returns:** results[]{listing_id (the guid every other action takes), advert_id (the numeric id `similar` and `price_history` take), title, url, price, price_label, price_not_published, currency, condition (null where the category publishes none), description, category{id, name, slug}, location{region_id, region, area, slug, label}, attributes[]{name, value, unit}, labels[]{type, value}, image, image_count, is_promoted (always false in results), boost_package (the seller's paid Jiji package — enterprise, diamond, premium, vip_gold, vip, basic — or null), paid_placement ('cpc' when Jiji ranked the row through its pay-per-click auction, else null), is_inspected, is_job, status, seller{user_id, name, rating, avatar_url}, can_view_contacts}, promoted[] (Jiji's paid TOP placements, same row shape with is_promoted true; kept OUT of results and of count because Jiji puts them in a fixed slot on every page, so they repeat from page to page), count (rows in results only), total_results, page, pages_fetched, total_pages, page_size, has_more, next_page, country, currency, category, region, filters_applied[], posted_in_last_day, posted_in_last_hour, empty_confirmed (only on an empty answer: true = Jiji answered empty twice from two different exits, so it is a real no-match rather than a throttle)

**Example request body:**
```json
{
  "country": "ng",
  "category": "cars",
  "limit": 24
}
```

### POST https://api.reefapi.com/jiji/v1/listing — 2 credits
One ad in full: title, the complete description, price with Jiji's own market-price band, every photo at full resolution, every attribute the category defines, when it was posted, how many people have viewed and saved it, the trust labels, the breadcrumb path, and the seller — account id, display name, rating, how long they have been on Jiji, when they were last seen, their shop pages, and the phone number(s) the ad publishes.

**Parameters:**
- `listing_id` (string, required) — The ad's id — the `listing_id` a search row returns, or a full jiji ad URL, or the ...-<id>.html tail of one.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `include_phone` (boolean, optional, default true) — Fetch the seller's published phone number(s) as well (one extra upstream call). On by default.

**Returns:** listing{listing_id, advert_id, title, url, price, price_label, price_not_published, currency, condition, market_price, has_price_history, description, category{}, location{}, attributes[]{name, value, unit}, highlights[], labels[], images[]{url, width, height, is_main}, image_count, posted_at, posted_at_label, view_count, favourite_count, status, is_active, is_closed, is_job, is_cv, breadcrumbs[], similar_slug, seller{user_id, seller_id, name, phone, phones[], profile_url, avatar_url, adverts_count, feedback_count, member_since_label, last_seen_label, response_time, is_premium, chat_enabled, labels[], is_shop, shop_slug, business_evidence[], stores[]}}

**Example request body:**
```json
{
  "country": "ng",
  "listing_id": "cZb9ZNOeiNZvGeLI8WxYwNQE"
}
```

### POST https://api.reefapi.com/jiji/v1/seller_listings — 2 credits
Every live ad of one seller — a dealer, an agency, a shop or a private account — in the same row shape as `search`, so a whole inventory comes back page by page. The seller's own paid TOP ads come back in a separate `promoted` list, not in `results`.

**Parameters:**
- `user_id` (integer, required) — The seller's numeric account id — `seller.user_id` on any of their ads.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `query` (string, optional) — Free-text search, e.g. 'toyota camry', 'iphone 15', '3 bedroom flat'. Combine with `category` to search inside one vertical.
- `category` (string, optional) — A category by slug, numeric id or name — `cars`, `mobile-phones`, `houses-apartments-for-rent`, `jobs`, 29, 'Cars'. Validated against Jiji's own tree (the free `categories` action), because Jiji answers an unknown category slug with the WHOLE site instead of an error.
- `region` (string, optional) — A state / city / district by slug, id or name — `lagos`, `nairobi`, `greater-accra`, `dhaka`, 119. The free `regions` action lists every one.
- `sort` (enum, optional, default "relevance") — Result order. `relevance` is Jiji's own Recommended order, which the site re-ranks on every request (paid ranking), so paging through it can return a few adverts twice and skip others. To walk every page of a search, use `newest`: its order is stable from page to page. [one of: relevance, newest, price_asc, price_desc]
- `page` (integer, optional, default 1) — Which page of results to start from (1-based). Jiji's own window ends at `total_pages`; asking past it is an error, never an empty page.
- `limit` (integer, optional, default 24) — How many ads to return in `results`, 1-96. Jiji's page is fixed at 24 slots and cannot be widened, so anything above 24 is fetched as consecutive pages. Jiji's paid TOP ads take 1-5 of those slots and are returned in `promoted` instead, so one page usually yields 19-23 results.

**Returns:** results[]{listing_id (the guid every other action takes), advert_id (the numeric id `similar` and `price_history` take), title, url, price, price_label, price_not_published, currency, condition (null where the category publishes none), description, category{id, name, slug}, location{region_id, region, area, slug, label}, attributes[]{name, value, unit}, labels[]{type, value}, image, image_count, is_promoted (always false in results), boost_package (the seller's paid Jiji package — enterprise, diamond, premium, vip_gold, vip, basic — or null), paid_placement ('cpc' when Jiji ranked the row through its pay-per-click auction, else null), is_inspected, is_job, status, seller{user_id, name, rating, avatar_url}, can_view_contacts}, promoted[] (Jiji's paid TOP placements, same row shape with is_promoted true; kept OUT of results and of count because Jiji puts them in a fixed slot on every page, so they repeat from page to page), count (rows in results only), total_results, page, pages_fetched, total_pages, page_size, has_more, next_page, country, currency, category, region, filters_applied[], posted_in_last_day, posted_in_last_hour, empty_confirmed (only on an empty answer: true = Jiji answered empty twice from two different exits, so it is a real no-match rather than a throttle), user_id

**Example request body:**
```json
{
  "country": "ng",
  "user_id": 11803654,
  "limit": 24
}
```

### POST https://api.reefapi.com/jiji/v1/seller_reviews — 1 credit
What buyers wrote about a seller: the good / neutral / bad counts, and each review with its rating, text, date, the reviewer, the ad it was left on and the seller's reply.

**Parameters:**
- `seller_id` (string, required) — The seller's id string — `seller.seller_id` from a `listing` answer.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `page` (integer, optional, default 1) — Which page of results to start from (1-based). Jiji's own window ends at `total_pages`; asking past it is an error, never an empty page.
- `rating` (enum, optional) — Only reviews of one kind. [one of: good, neutral, bad]

**Returns:** seller{user_id, seller_id, name, avatar_url, is_premium}, stats{good, neutral, bad}, reviews[]{id, rating (good|neutral|bad), stars (1-5), text, created_at, created_at_unix, likes, edited, author{user_id, seller_id, name, avatar_url}, advert{advert_id, title, url}, reply_count, replies[]{text, created_at, author, likes}}, count, page, has_more

**Example request body:**
```json
{
  "country": "ng",
  "seller_id": "wdnFCNPH7TUWayfgjcuvuaR7"
}
```

### POST https://api.reefapi.com/jiji/v1/similar — 2 credits
Jiji's own comparable live ads for one listing — what the same market is asking right now, in the search row shape. Any paid TOP ad comes back in a separate `promoted` list, not in `results`.

**Parameters:**
- `advert_id` (string, required) — The ad's NUMERIC id (`advert_id` in a search row). A `listing_id` guid is also accepted and costs one extra lookup.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `page` (integer, optional, default 1) — Which page of results to start from (1-based). Jiji's own window ends at `total_pages`; asking past it is an error, never an empty page.

**Returns:** results[]{listing_id (the guid every other action takes), advert_id (the numeric id `similar` and `price_history` take), title, url, price, price_label, price_not_published, currency, condition (null where the category publishes none), description, category{id, name, slug}, location{region_id, region, area, slug, label}, attributes[]{name, value, unit}, labels[]{type, value}, image, image_count, is_promoted (always false in results), boost_package (the seller's paid Jiji package — enterprise, diamond, premium, vip_gold, vip, basic — or null), paid_placement ('cpc' when Jiji ranked the row through its pay-per-click auction, else null), is_inspected, is_job, status, seller{user_id, name, rating, avatar_url}, can_view_contacts}, promoted[] (Jiji's paid TOP placements, same row shape with is_promoted true; kept OUT of results and of count because Jiji puts them in a fixed slot on every page, so they repeat from page to page), count (rows in results only), total_results, page, pages_fetched, total_pages, page_size, has_more, next_page, country, currency, category, region, filters_applied[], posted_in_last_day, posted_in_last_hour, empty_confirmed (only on an empty answer: true = Jiji answered empty twice from two different exits, so it is a real no-match rather than a throttle), advert_id

**Example request body:**
```json
{
  "country": "ng",
  "advert_id": "8167428"
}
```

### POST https://api.reefapi.com/jiji/v1/price_history — 1 credit
Every price the seller has asked for this ad since it was posted, with the date of each change — Jiji's own record, not a reconstruction.

**Parameters:**
- `advert_id` (string, required) — The ad's NUMERIC id (`advert_id` in a search row). A `listing_id` guid is also accepted and costs one extra lookup.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]

**Returns:** history[]{date, price, label}, count, advert_id, currency, first_price, latest_price, change, change_pct

**Example request body:**
```json
{
  "country": "ng",
  "advert_id": "48153873"
}
```

### POST https://api.reefapi.com/jiji/v1/suggest — 1 credit
Jiji's keyword autocomplete — what real buyers type, each suggestion carrying the category it belongs to and a ready-made search URL, so a half-typed word becomes a valid query without guessing a category.

**Parameters:**
- `query` (string, required) — The partial phrase to complete.
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `category` (string, optional) — A category by slug, numeric id or name — `cars`, `mobile-phones`, `houses-apartments-for-rent`, `jobs`, 29, 'Cars'. Validated against Jiji's own tree (the free `categories` action), because Jiji answers an unknown category slug with the WHOLE site instead of an error.

**Returns:** suggestions[]{query, category, category_slug, url}, count, term

**Example request body:**
```json
{
  "country": "ng",
  "query": "toyota"
}
```

### POST https://api.reefapi.com/jiji/v1/categories — 1 credit
Jiji's whole category tree for a country — every group and sub-category with its id, slug, name and live advert count. Free: these are the values `search` and `filters` take, so nobody has to guess one.

**Parameters:**
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]

**Returns:** categories[]{id, name, slug, advert_count, image_url, children[]}, count, flat[]{id, name, slug, parent_id, parent_name}, country

**Example request body:**
```json
{
  "country": "ng"
}
```

### POST https://api.reefapi.com/jiji/v1/regions — 1 credit
Every state, city and district Jiji lists for a country, with ids and slugs and which ones it treats as popular. Free: these are the values `region` takes.

**Parameters:**
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]

**Returns:** regions[]{id, name, slug, is_popular, areas[]{id, name, slug, is_popular}}, count, area_count, country

**Example request body:**
```json
{
  "country": "ng"
}
```

### POST https://api.reefapi.com/jiji/v1/filters — 1 credit
Every filter one category publishes, with the allowed values, the range bounds and the unit — car makes and their models, property types and bedroom counts, phone brands and storage sizes, job types, conditions, colours. Free, and the authoritative input for `search`'s `filters` parameter. Pass `filters` here too to see the child filters a choice unlocks (choose a make, get its models).

**Parameters:**
- `country` (enum, optional, default "ng") — Which Jiji storefront to read. Each country is its own domain and its own catalogue, prices and currency. `bd` reads bikroy.com, Bangladesh's Jiji storefront; its site prints prices in lakh grouping (`BDT 17,00,000`), and `price` is the plain number (1700000). [one of: ng, gh, ke, tz, ug, bd]
- `category` (string, optional) — A category by slug, numeric id or name — `cars`, `mobile-phones`, `houses-apartments-for-rent`, `jobs`, 29, 'Cars'. Validated against Jiji's own tree (the free `categories` action), because Jiji answers an unknown category slug with the WHOLE site instead of an error.
- `region` (string, optional) — A state / city / district by slug, id or name — `lagos`, `nairobi`, `greater-accra`, `dhaka`, 119. The free `regions` action lists every one.
- `filters` (string, optional) — Category filters, as `name=value` pairs separated by ';' (or a JSON object). Names and values are the ones Jiji itself publishes for that category — ask the free `filters` action. Ranges take `from-to`, `from-` or `-to`. Several values for one filter are comma-separated. Examples: `make=Toyota;model=Camry`, `condition=Foreign Used;year_of_manufacture=2018-2021`, `colour=Black,Blue;mileage=-80000`. A name Jiji does not publish is REJECTED rather than silently ignored — see the action description.

**Returns:** category{id, name, slug}, filters[]{name, key, label, kind (single|multi|range), unit, parent, values[], value_count, min, max}, count, country

**Example request body:**
```json
{
  "country": "ng",
  "category": "cars"
}
```

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