# Gazelle API — live data from buy.gazelle.com, the US first-party refurbished phone and tablet store (an ecoATM company). Browse the whole live catalogue — 1,000 products over 108 model lines and 13,329 priced variants on 2026-10-08 — with a price for every cosmetic grade (Fair / Good / Excellent), every colour, every capacity and every carrier, then open one product for the complete model matrix: each storage x carrier sibling with its own offer table, the real unit count behind each variant (which no JSON surface of the site publishes) and the new-device MSRP to measure the saving against. Also returns Gazelle's own faceted inventory census and its 205 collections. One seller, one warranty, USD, no login, no API key.

> Browse the Gazelle catalogue: one row per PRODUCT (a model x storage x carrier) with its price band, the cheapest price AT EACH cosmetic grade, the colours and grades it is stocked in, and how many of its variants can actually be bought today. Free-text `q` plus filters on brand, model line, capacity, carrier, colour, cosmetic grade, device class, price band and stock. Two numbers are always given side by side, because the source makes them differ: `price_min` over every published variant and `price_min_available` over the ones you can buy — on 55 of the 153 in-stock products the cheapest variant is sold out and the cheapest buyable one costs more. Gazelle's catalogue endpoint honours only `limit` and `page` (every filter and sort parameter it advertises was measured returning the identical product ids in the identical order), so the filtering and ordering here are done by this API over the source's own fields and `meta.filtering` says so rather than pretending otherwise.
> ReefAPI engine `gazelle` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/gazelle/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/gazelle/v1/search — 6 credits
Browse the Gazelle catalogue: one row per PRODUCT (a model x storage x carrier) with its price band, the cheapest price AT EACH cosmetic grade, the colours and grades it is stocked in, and how many of its variants can actually be bought today. Free-text `q` plus filters on brand, model line, capacity, carrier, colour, cosmetic grade, device class, price band and stock. Two numbers are always given side by side, because the source makes them differ: `price_min` over every published variant and `price_min_available` over the ones you can buy — on 55 of the 153 in-stock products the cheapest variant is sold out and the cheapest buyable one costs more. Gazelle's catalogue endpoint honours only `limit` and `page` (every filter and sort parameter it advertises was measured returning the identical product ids in the identical order), so the filtering and ordering here are done by this API over the source's own fields and `meta.filtering` says so rather than pretending otherwise.

**Parameters:**
- `collection` (string, optional, default "all") — Which Gazelle collection to read, by the storefront's own handle: `all` (the whole live catalogue, 1,000 products on 2026-10-08), `iphone` (332), `ipads`, `samsung-galaxy`, `google-phones`, `unlocked`, `best-sellers`, `clearance`, and 202 more that the `collections` action lists. Narrowing the collection is also the way to make this call cheaper: the source only honours `limit` and `page`, so a smaller collection is fewer pages to read. A handle that does not exist is NOT_FOUND — the source answers one with an empty list and HTTP 200, exactly like a real collection that happens to be empty, so the handle is verified separately.
- `q` (string, optional) — Free-text match over each product's title, model line and tags, applied by this API over the rows the source returned. All words must appear (order does not matter), so `pro max 256` finds the 256 GB Pro Max products. Gazelle's own catalogue endpoint ignores every query parameter except `limit` and `page` (measured: `q=iphone 15` returned the identical 250 product ids in the identical order as no query at all), so nothing here is passed to it as a filter.
- `brand` (enum, optional) — Keep only this manufacturer. Live on 2026-10-08: Apple, Samsung and Google only, and the storefront's own counts were 518 / 304 / 177 of its 1,000 products — it publishes no other brand in stock. The source's own `Brand:` tag is missing on 477 of 1,000 products, so brand is derived from the model line (which covers all 108 of them) and each row says which witness was used in `brand_source`. [one of: Apple, Samsung, Google, OnePlus, Motorola, LG, Sony, Nokia, Microsoft]
- `model` (array, optional) — Keep only these model lines, matched case-insensitively against the source's own model name — 'iPhone 15 Pro', 'Galaxy S24 Ultra', 'Google Pixel 9', 'iPad Pro 11-inch (M4)'. 108 model lines were live on 2026-10-08 and every `search` row returns its own as `model_line`. A prefix is enough: 'iPhone 15' also matches 'iPhone 15 Pro' and 'iPhone 15 Plus'.
- `storage` (array, optional) — Keep only these capacities, in GB (16, 32, 64, 128, 256, 512, 1024 = 1 TB, 2048 = 2 TB). Gazelle's own counts over its whole live catalogue: 256 GB is the commonest with 336 products, then 512 GB (261), 128 GB (214), 1 TB (129), 64 GB (31), 2 TB (15), 32 GB (9), 16 GB (2). '1TB' and '1024' both work.
- `carrier` (enum, optional) — Keep only devices on this carrier. Gazelle's own counts over its whole live catalogue: Unlocked 307 products, Verizon 205, AT&T 201, T-Mobile 198, Wi-Fi 87 (the Wi-Fi-only iPads). The source spells that last one two different ways in its own tags (`WiFi` on 56 products, `WIFI` on 31); both are accepted and every row keeps the source's own spelling in `carrier_raw`. [one of: Unlocked, AT&T, T-Mobile, Verizon, Wi-Fi]
- `color` (array, optional) — Keep only products offered in these colours, matched case-insensitively against the source's own colour names. 118 distinct colour names were live on 2026-10-08 — Silver, Blue, Graphite, Black, White, Space Gray, Obsidian, Natural Titanium, Cosmic Orange and so on. A colour selects the PRODUCT when any of its variants has it; use `product` for the colour-by-condition price table.
- `condition` (enum, optional) — Keep only products available in this cosmetic grade. Gazelle grades every device itself into exactly three tiers and prices each one separately: measured on the iPhone 17e 256 GB in one run, Fair USD 489.99, Good 509.99, Excellent 524.99. Nearly every product carries all three — 4,442 Fair / 4,442 Good / 4,438 Excellent variants, and the storefront's own facet counts 922 / 923 / 922 products out of 1,000 — so this is most useful together with `in_stock_only` — a grade is often the thing that is sold out. [one of: Fair, Good, Excellent]
- `product_type` (enum, optional) — Keep only this device class, the source's own words. The live catalogue on 2026-10-08 was 824 Cell Phones, 175 iPads and 1 Digital Warranty — and nothing else. Gazelle's MacBook and Apple-Watch collections still exist but return zero products, so there is no laptop or watch class to ask for. [one of: Cell Phones, iPads, Digital Warranty]
- `min_price` (number, optional) — Lowest price, in USD MAJOR units (400 = USD 400.00, not 40000). Compared against each product's cheapest variant — or, with `in_stock_only`, its cheapest BUYABLE variant, which on 55 of the 153 in-stock products is a different and dearer number. Live prices ran USD 46.99 to 2,199.99.
- `max_price` (number, optional) — Highest price, same units as `min_price`. Combine the two for a band.
- `in_stock_only` (boolean, optional, default false) — Keep only products with at least one BUYABLE variant, and judge every other filter against the buyable variants alone. This matters more on Gazelle than on most catalogues: it publishes 13,329 priced variants of which only 464 were buyable on 2026-10-08, across 153 of the 1,000 products. Off by default so you can see the full price history of the catalogue; switch it on to see what can actually be bought today.
- `sort` (enum, optional, default "source") — Row order. Applied by this API, like the filters: the source's catalogue endpoint ignores its own `sort_by` parameter there (measured — `sort_by=price-ascending`, `price-descending` and `title-ascending` each returned the identical 250 product ids in the identical order). Any sort other than `source` reads the whole collection first so that the order is over the real catalogue and not over one page of it. [one of: source, price_asc, price_desc, title_asc, title_desc, newest, oldest, stock_first]
- `limit` (integer, optional, default 50) — How many product rows to return, 1-250 (default 50). This is the API's page size, not the source's: Gazelle serves 250 products per request and silently clamps anything larger, so a `limit` of 250 with no filter is exactly one upstream call.
- `page` (integer, optional, default 1) — Which page of `limit` rows to return, 1-based. Paging over the FILTERED and SORTED result, so it is stable for a given set of parameters. `meta.has_more` and `meta.total_matched` tell you when to stop; the live catalogue is small enough (1,000 products) that everything is reachable.
- `include_pii` (boolean, optional, default false) — Accepted for gateway compatibility. There is no personal data on this source: the only seller is Gazelle itself, a company, and it is always returned in full.

**Returns:** products[]{handle, product_id, title, url, brand, brand_source, model_line, storage_gb, storage_label, carrier, carrier_raw, product_type, currency, price_min, price_max, price_min_available, price_max_available, compare_at_price_max, in_stock, variant_count, available_variant_count, colors[], colors_available[], conditions[], conditions_available[], price_by_condition{}, price_by_condition_available{}, tags[], image_url, image_count, created_at, updated_at, published_at, detail_params{handle}} + seller{} + meta{collection, total_matched, source_product_count, source_variant_count, source_available_variant_count, in_stock_product_count, returned, page, has_more, price_range{min,max}, filters_applied{}, filtering, source_pages_read, currency}

**Example request body:**
```json
{
  "collection": "iphone",
  "in_stock_only": true,
  "sort": "price_asc",
  "limit": 25
}
```

### POST https://api.reefapi.com/gazelle/v1/product — 4 credits
The COMPLETE live offer table of one Gazelle product and, by default, of every sibling product of the same model — each capacity x carrier combination — in a single request, straight from the storefront's own variant picker. Per offer: colour, cosmetic grade, price, the crossed-out price when there is a real one, and THE ACTUAL UNIT COUNT, which neither /products.json nor the product's own JSON endpoint publishes anywhere on the site. Per product: the new-device MSRP and the saving against it, the warranty code, the collections it sits in, and the cheapest price at each grade. Measured on 2026-10-08: 8 sibling products / 72 offers for the iPhone 17e, 12 / 144 for the Galaxy Z Fold8 Ultra, 3 / 36 for the iPhone 11 Pro 512 GB. The page's own schema.org block is read as a second witness for price and availability and any disagreement is reported in `meta.ld_json_cross_check`, not hidden. An unknown handle is NOT_FOUND.

**Parameters:**
- `handle` (string, required) — The product handle, as the storefront's own URL spells it — the part after /products/. Every `search` row returns it as `handle` and as ready-made `detail_params`. A full buy.gazelle.com product URL is also accepted and the handle is taken out of it. A handle that does not exist is NOT_FOUND (the source answers HTTP 404 for one).
- `include_group` (boolean, optional, default true) — Also return every SIBLING product of the same model — each storage and carrier combination, with its own full offer table. This is the reason to use `product` rather than read a search row: Gazelle's product page ships the whole group in one response, so a single call returns the complete model matrix. Measured: 8 products / 72 variants for the iPhone 17e, 12 / 144 for the Galaxy Z Fold8 Ultra, 3 / 36 for the iPhone 11 Pro 512 GB. Switch it off for the requested product alone.
- `in_stock_only_offers` (boolean, optional, default false) — Drop offers whose unit count is zero. Gazelle publishes sold-out variants with a live price (67 of the iPhone 17e group's 72 variants were at zero units), so this is off by default — the full table is the price history. The counts themselves are the real thing: no JSON surface of the site publishes them, only this page does.
- `include_pii` (boolean, optional, default false) — Accepted for gateway compatibility. There is no personal data on this source: the only seller is Gazelle itself, a company, and it is always returned in full.

**Returns:** product{handle, product_id, title, url, brand, brand_source, model_line, model, storage_gb, storage_label, carrier, carrier_raw, product_type, currency, msrp, msrp_minor, price_min, price_max, price_min_available, price_max_available, savings_vs_msrp_pct, in_stock, variant_count, available_variant_count, units_in_stock, units_by_condition{}, colors[], colors_available[], conditions[], conditions_available[], price_by_condition{}, price_by_condition_available{}, warranty_code, tags[], collections[], image_url, description, published_at, offers[]{variant_id, sku, title, color, condition, condition_rank, price, price_minor, currency, compare_at_price, available, units_in_stock, inventory_policy, inventory_tracked, incoming, next_incoming_date, requires_shipping, shipping_weight_grams, image_url, url}}, group[]{same shape}, seller{}, summary{group_product_count, offer_count, available_offer_count, units_in_stock, price_min, price_max, price_min_available, price_by_condition{}, units_by_condition{}, storages_gb[], carriers[], colors[], conditions[]} + meta{handle, stock_source, ld_json_cross_check{}, offers_hidden_sold_out}

**Example request body:**
```json
{
  "handle": "iphone-17e-256gb-unlocked"
}
```

### POST https://api.reefapi.com/gazelle/v1/facets — 3 credits
Gazelle's own inventory census of one collection: every value its storefront filter form offers for brand, model, capacity, carrier, colour, cosmetic grade and availability, each with THE SOURCE'S OWN product count beside it, plus the price slider's bounds and the live page count of the grid. This is the one number on the site that can be trusted about size: `collections.json` claims 4,058 products for `all` while the catalogue pages out at 1,000, and claims 1,224 MacBooks where there are none. Unlike the catalogue endpoint, the collection page really does honour filters, so `filters` returns Gazelle's own answer to a combined question (how many Unlocked iPhone 15 Pro in Excellent, etc.). Filter values are case-sensitive at the source — `brand=apple` returns 0 products with HTTP 200 while `brand=Apple` returns all 332 — so every value sent is checked against the form the source renders back and anything it does not offer lands in `meta.warnings`.

**Parameters:**
- `collection` (string, optional, default "all") — Which Gazelle collection to read, by the storefront's own handle: `all` (the whole live catalogue, 1,000 products on 2026-10-08), `iphone` (332), `ipads`, `samsung-galaxy`, `google-phones`, `unlocked`, `best-sellers`, `clearance`, and 202 more that the `collections` action lists. Narrowing the collection is also the way to make this call cheaper: the source only honours `limit` and `page`, so a smaller collection is fewer pages to read. A handle that does not exist is NOT_FOUND — the source answers one with an empty list and HTTP 200, exactly like a real collection that happens to be empty, so the handle is verified separately.
- `filters` (object, optional) — Narrow the facet counts with the storefront's OWN filters, as {filter: value} or {filter: [values]} over brand, model, storage, carrier, color, condition and availability. Unlike the catalogue endpoint, the collection page really does honour these, so the counts that come back are Gazelle's own answer to a combined question. Values are case-sensitive at the source — `brand=apple` returned 0 products and `brand=Apple` returned all 332 — so every value sent is checked against the filter form the source renders back and anything it does not offer is reported in `meta.warnings` instead of passing as a successful narrowing.
- `min_price` (number, optional) — Lowest price, in USD MAJOR units (400 = USD 400.00, not 40000). Compared against each product's cheapest variant — or, with `in_stock_only`, its cheapest BUYABLE variant, which on 55 of the 153 in-stock products is a different and dearer number. Live prices ran USD 46.99 to 2,199.99.
- `max_price` (number, optional) — Highest price, same units as `min_price`. Combine the two for a band.
- `include_pii` (boolean, optional, default false) — Accepted for gateway compatibility. There is no personal data on this source: the only seller is Gazelle itself, a company, and it is always returned in full.

**Returns:** collection{handle, title, url, products_count_claimed}, facets[]{filter, source_parameter, label, values[]{value, product_count}}, grid{products_per_page, last_page, approx_live_products, empty_notice, handles[]}, price_input{} + meta{collection, filters_applied{}, filters_not_offered[], approx_live_products, products_count_claimed, count_discrepancy}

**Example request body:**
```json
{
  "collection": "iphone"
}
```

### POST https://api.reefapi.com/gazelle/v1/collections — 1 credit
Every collection the Gazelle storefront publishes — 205 on 2026-10-08 — with its handle, title, URL and ready-made `search_params`. This is how you find the handle to narrow `search` and `facets` with, which is also how you make those calls cheap. The count the source attaches to each collection is published as `products_count_claimed` and nothing else, because it is not a live number: it says 4,058 for `all` where the catalogue really pages out at 1,000, and it says 1,224 for `macbook-pro` and 2 for `apple-watches` where both return zero products and the storefront itself prints 'No products found'. Use `facets` or `search` for a number you can rely on.

**Parameters:**
- `q` (string, optional) — Keep only collections whose handle or title contains this text (case-insensitive).
- `limit` (integer, optional, default 250) — How many collections to return, 1-250. Gazelle published 205 on 2026-10-08, so the default returns all of them.
- `include_pii` (boolean, optional, default false) — Accepted for gateway compatibility. There is no personal data on this source: the only seller is Gazelle itself, a company, and it is always returned in full.

**Returns:** collections[]{handle, title, collection_id, url, products_count_claimed, published_at, updated_at, image_url, search_params{}} + meta{total_collections, returned, products_count_claimed_warning}

**Example request body:**
```json
{
  "q": "iphone",
  "limit": 100
}
```

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