# Chairish — US vintage & design marketplace (furniture, lighting, rugs, art, decor)

> Search or browse Chairish's live US marketplace of vintage, antique and used design. Scope the request with free text, a collection path, a brand/designer storefront or one of the site's own keyword pages, then narrow it with the site's own facets: style label, category code, colour hex, price band, vintage vs newly made, on-sale, ready-to-ship, editorial shelf. Every row carries the price AND the pre-markdown price when the seller has discounted it, the currency, the dealer id with their city and state, the condition, the brand, the colour, the materials and the height/width/depth in inches — the measurements are the question buyers actually ask in this market. Exactly one upstream page per call; the source serves 48 rows per page.
Exactly one of `query`, `category`, `maker` or `keyword` is required: the source serves one scope at a time and combining two returns nothing.
The source's own count comes back as `total_available`, with `total_is_capped: true` when it has hit the site's 10,000 ceiling — two capped totals are not comparable and this endpoint says so rather than pretending otherwise.
> ReefAPI engine `chairish` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/chairish/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/chairish/v1/search — 3 credits
Search or browse Chairish's live US marketplace of vintage, antique and used design. Scope the request with free text, a collection path, a brand/designer storefront or one of the site's own keyword pages, then narrow it with the site's own facets: style label, category code, colour hex, price band, vintage vs newly made, on-sale, ready-to-ship, editorial shelf. Every row carries the price AND the pre-markdown price when the seller has discounted it, the currency, the dealer id with their city and state, the condition, the brand, the colour, the materials and the height/width/depth in inches — the measurements are the question buyers actually ask in this market. Exactly one upstream page per call; the source serves 48 rows per page.
Exactly one of `query`, `category`, `maker` or `keyword` is required: the source serves one scope at a time and combining two returns nothing.
The source's own count comes back as `total_available`, with `total_is_capped: true` when it has hit the site's 10,000 ceiling — two capped totals are not comparable and this endpoint says so rather than pretending otherwise.

**Parameters:**
- `query` (string, optional) — Free-text search across the whole marketplace, exactly as the site's own search box takes it. Exactly one of `query`, `category`, `maker` or `keyword` is required — see the action description.
- `category` (string, optional) — A Chairish collection path: 1-3 lower-case slug segments exactly as they appear after /collection/ in a browse URL — 'rings', 'seating', 'floor-lamps', 'rugs/persian', 'paintings/abstract'. Call the `filters` action for the category tree the site serves. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `maker` (string, optional) — A brand or designer storefront slug as it appears after /maker/ — 'herman-miller', 'eames', 'cartier', 'chanel', 'restoration-hardware'. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `keyword` (string, optional) — One of Chairish's own editorial keyword pages, as it appears after /keyword/ — 'landscape-paintings', 'swag-lamps', 'round-rugs', 'tiger-rugs'. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `styles` (array, optional) — Style filter. Takes Chairish's own style LABEL, not the URL slug: 'Art Deco', 'Mid-Century Modern', 'Hollywood Regency', 'Victorian', 'Rustic'. Several values are OR-ed. The exact labels a scope serves, with counts, come from the `filters` action — a label the source does not know returns an honest zero, not an error.
- `categories` (array, optional) — Narrow a scope to one or more Chairish category CODES: 'U' furniture, 'L' lighting, 'D' decor, 'R' fine art, or a deeper code such as 'ART:PAINTINGS' or 'SEATING:OFFICECHAIR'. Codes, labels and counts come from the `filters` action.
- `colors` (array, optional) — Colour filter. Takes the site's own 6-digit HEX code, not a colour name: FF0000 red, 0000FF blue, FFFF00 yellow, FFA500 orange, 000000 black. The palette a scope serves, with counts, comes from the `filters` action.
- `item_type` (enum, optional) — Vintage/antique/pre-owned pieces or newly made ones. Measured bite on /collection/rings within one minute: vintage 7,149 · new 5,644. [one of: vintage, new]
- `on_sale` (boolean, optional) — Only items the seller has marked down (the site's own 'On Sale' facet). Measured bite on /collection/rings: 10,000 (capped) → 1,916.
- `ready_to_ship` (boolean, optional) — Only items the site flags 'Ready to Ship', i.e. in stock with no made-to-order lead time.
- `featured` (enum, optional) — One of Chairish's own editorial shelves. [one of: new_arrivals, a_list]
- `shipping` (enum, optional) — Shipping-offer filter as the site publishes it. Measured bite: /collection/accent-chairs 10,000 (capped) → 459 with free_shipping. 🔴 It cannot be combined with `styles`: the source returns MORE rows for the pair than for the style filter alone (1,280 → 2,798), so that combination is refused rather than answered wrongly. It does combine correctly with category, colors, price bands, item_type and on_sale. `free_local_pickup` and `ships_to_my_location` are location-dependent on the site and may not bite, because this endpoint never sends a buyer postal code. [one of: free_shipping, low_flat_rate, free_local_pickup, ships_to_my_location]
- `price_min` (integer, optional) — Lowest USD price to include. Sent as the site's own price-range facet.
- `price_max` (integer, optional) — Highest USD price to include. Measured bite on /collection/rings: 10,000 (capped) → 2,566 at price_max=500.
- `sort` (enum, optional, default "curated") — Result order. 'curated' is the site's own default ranking. [one of: curated, newest, price_asc, price_desc, most_favorited]
- `page` (integer, optional, default 1) — 1-based page number. The page size is fixed at 48 by the source. Measured ceiling: page 99 answers and page 100 is refused, so 4,752 rows is the reachable window for any one scope — narrow it with filters to reach the rest.
- `max_results` (integer, optional, default 48) — How many of the page's rows to return (1-48). The source serves 48 rows per page, so this does not change the upstream cost; use `page` to go further.

**Returns:** {scope{kind, value}, source_path, total_available, total_is_capped, total_cap, page, page_size, page_cap, last_page, has_more, filters_applied{}, results[]} — each row: {item_id, url, title, price, currency, price_display, price_unit, price_status, original_price, discount_percent, is_markdown, availability, price_mismatch, quantity, condition, product_state, is_purchasable, is_on_hold, is_made_to_order, is_newly_made, lead_time, category_code, category_path, brand, color, materials[], dimensions_in{height,width,depth}, description, images[], seller_id, seller_url, ships_from_city, ships_from_region, ships_from_country, ships_to_countries[], shipping_type, local_pickup_available, is_promoted, badges[]}. `price` is null — never 0 — when the source publishes no amount, and `price_status` says why.

**Example request body:**
```json
{
  "category": "floor-lamps",
  "max_results": 12
}
```

### POST https://api.reefapi.com/chairish/v1/detail — 3 credits
The full listing page for one to five items: the dealer's complete description, every photo, the price with its pre-markdown figure, the condition grade AND the dealer's own condition notes, and the site's whole detail table. That table is per vertical — a chair publishes Number of Seats and Seat Height, a painting publishes Art Subject and Framing, a lamp publishes Lamp Shade — so it is returned whole in `details[]` and projected into `attributes{}`, with period, country of origin, item type, styles, materials, colour, brand and designer promoted to named fields. Includes the dealer's shop handle, display name, city/state, year they joined and the sales band the site prints, plus the schema.org offer block as an independent second witness on the price and the availability.

**Parameters:**
- `item` (array, required) — One to 5 Chairish item ids (the `item_id` a search row returns, e.g. '35654342'), or full /product/<id>/… listing URLs. Each id is one upstream page fetch.

**Returns:** {requested, found, not_found[]{item_id, reason}, items[]} — each item: {item_id, url, title, price, currency, price_display, price_status, original_price, discount_percent, is_markdown, availability, price_mismatch, condition, condition_grade, condition_notes, category_code, category_path, brand, designer, period, country_of_origin, item_type, styles[], materials[], color, dimensions_display, dimensions_in{height,width,depth}, description, images[], seller{seller_id, slug, name, location, since_year, sales_band}, ships_from_city, ships_from_region, ships_from_country, details[]{label, values[]}, attributes{}, schema_org_offer{price, price_currency, availability, item_condition, price_valid_until}}.

**Example request body:**
```json
{
  "item": [
    "35654342"
  ]
}
```

### POST https://api.reefapi.com/chairish/v1/seller — 3 credits
One dealer's storefront: who they are (display name, city and state, the year they joined Chairish, the sales band the site prints) and their live inventory with the same row shape as `search`, filterable the same way. Takes the vanity slug from a /shop/<slug> URL or the dealer id a search row returns as `seller_id`. A dealer who exists but currently lists nothing is an answer, not an error: `has_live_inventory` is false and `results` is empty. An unknown handle is NOT_FOUND.

**Parameters:**
- `seller` (string, required) — A dealer storefront handle exactly as it appears after /shop/ in the URL: either the vanity slug ('ambassador', 'rushhouse') or the dealer id a search row publishes as `seller_id` ('9ny9p3'). Both resolve to the same shop.
- `styles` (array, optional) — Style filter. Takes Chairish's own style LABEL, not the URL slug: 'Art Deco', 'Mid-Century Modern', 'Hollywood Regency', 'Victorian', 'Rustic'. Several values are OR-ed. The exact labels a scope serves, with counts, come from the `filters` action — a label the source does not know returns an honest zero, not an error.
- `categories` (array, optional) — Narrow a scope to one or more Chairish category CODES: 'U' furniture, 'L' lighting, 'D' decor, 'R' fine art, or a deeper code such as 'ART:PAINTINGS' or 'SEATING:OFFICECHAIR'. Codes, labels and counts come from the `filters` action.
- `colors` (array, optional) — Colour filter. Takes the site's own 6-digit HEX code, not a colour name: FF0000 red, 0000FF blue, FFFF00 yellow, FFA500 orange, 000000 black. The palette a scope serves, with counts, comes from the `filters` action.
- `item_type` (enum, optional) — Vintage/antique/pre-owned pieces or newly made ones. Measured bite on /collection/rings within one minute: vintage 7,149 · new 5,644. [one of: vintage, new]
- `on_sale` (boolean, optional) — Only items the seller has marked down (the site's own 'On Sale' facet). Measured bite on /collection/rings: 10,000 (capped) → 1,916.
- `price_min` (integer, optional) — Lowest USD price to include. Sent as the site's own price-range facet.
- `price_max` (integer, optional) — Highest USD price to include. Measured bite on /collection/rings: 10,000 (capped) → 2,566 at price_max=500.
- `sort` (enum, optional, default "curated") — Result order. 'curated' is the site's own default ranking. [one of: curated, newest, price_asc, price_desc, most_favorited]
- `page` (integer, optional, default 1) — 1-based page number. The page size is fixed at 48 by the source. Measured ceiling: page 99 answers and page 100 is refused, so 4,752 rows is the reachable window for any one scope — narrow it with filters to reach the rest.
- `max_results` (integer, optional, default 48) — How many of the page's rows to return (1-48). The source serves 48 rows per page, so this does not change the upstream cost; use `page` to go further.

**Returns:** {seller{handle, seller_id, name, location, since_year, sales_band, url}, total_available, total_is_capped, total_cap, page, page_size, page_cap, last_page, has_more, has_live_inventory, filters_applied{}, results[]} — rows identical to `search`.

**Example request body:**
```json
{
  "seller": "ambassador",
  "max_results": 12
}
```

### POST https://api.reefapi.com/chairish/v1/filters — 3 credits
The filter values Chairish itself serves for a scope, with its own counts: the category tree (code, label, count, nested up to three deep), style labels, colour hex codes, price bands, availability, sales, shipping options and the vertical-specific facets (Number of Seats, Art Subject, Art Size, Art Orientation, Lamp Shade). Use it to learn the exact values `search` accepts instead of guessing — a value the source does not know returns an honest zero rather than an error, so guessing is expensive.
🔴 The site does not serve this list for every scope: measured within one minute, /collection/rings served 17 facets and /collection/seating served none. When that happens `filters_available` is false and `filters` is empty — the endpoint reports the gap instead of implying the scope has no filters. A dealer storefront (`seller`) has served them on every sample.
Takes the same scope pair as `search`, or a `seller` handle.

**Parameters:**
- `query` (string, optional) — Free-text search across the whole marketplace, exactly as the site's own search box takes it. Exactly one of `query`, `category`, `maker` or `keyword` is required — see the action description.
- `category` (string, optional) — A Chairish collection path: 1-3 lower-case slug segments exactly as they appear after /collection/ in a browse URL — 'rings', 'seating', 'floor-lamps', 'rugs/persian', 'paintings/abstract'. Call the `filters` action for the category tree the site serves. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `maker` (string, optional) — A brand or designer storefront slug as it appears after /maker/ — 'herman-miller', 'eames', 'cartier', 'chanel', 'restoration-hardware'. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `keyword` (string, optional) — One of Chairish's own editorial keyword pages, as it appears after /keyword/ — 'landscape-paintings', 'swag-lamps', 'round-rugs', 'tiger-rugs'. Exactly one of `query`, `category`, `maker` or `keyword` is required.
- `seller` (string, optional) — Read the facets of one dealer's storefront instead of a browse scope. Takes the same handle as the `seller` action — the vanity slug or the dealer id.

**Returns:** {scope{kind, value}, source_path, total_available, total_is_capped, filters_available, filter_count, filters[]{name, label, value_count, values[]{value, label, count, depth, note, valid_distances, children[]}}} — `name` is exactly the `search` parameter it feeds where one exists: categories, styles, colors, price, misc_sales, misc_availability, misc_featured, shipping_options.

**Example request body:**
```json
{
  "category": "rings"
}
```

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