# KEH API — live used photo and video gear from keh.com, the United States' largest managed second-hand camera store. KEH buys, inspects, grades and warranties every item itself, so a listing is one model held in KEH's own cosmetic grades (New, Like New, Like New Minus, Excellent Plus, Excellent, Bargain, Ugly, As Is). Search or browse the whole 54,000-product catalogue — 7,500 of them in stock today — by keyword, brand, KEH's own grade, category, system, gear type, lens mount, sensor or film format, megapixels, film type, filter thread and type, prime vs zoom, focus type, maximum aperture, focal length, memory-card type, special optical design, TTL flash system, intended use and price; pull the live filter taxonomy with counts for any slice of it; walk KEH's 135-node category tree; autocomplete a half-typed model name; or read one product's full record with its spec sheet, which grades KEH holds of it, how many units and its description. No login, no API key.

> Search or browse KEH's catalogue. Pass `query`, or any combination of the twenty-six filters, or nothing at all to walk the whole shop. Every row carries KEH's own product id, title (with the brace shorthand KEH prints in it pulled out as `title_tokens`), brand, price, how many units are in stock, the product URL, image and description. `meta.total_results` is KEH's own exact match count for the request, so a filter that bites and a filter that is ignored are told apart without guessing, and `meta.search_page_url` is the public KEH page that shows the same slice. IN-STOCK ONLY BY DEFAULT: 46,946 of the 54,499 indexed products are sold out and their indexed price is stale, so pass `in_stock=any` if you want those records too. NOTE `price` is the CHEAPEST grade's price — the catalogue index carries no per-grade price (measured against the product page: one body indexed at $1,352 is offered at $1,352 / $1,469 / $1,527 across its three grades) — so call `product` to see which grades exist.
> ReefAPI engine `keh` · 5 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/keh/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/keh/v1/search — 2 credits
Search or browse KEH's catalogue. Pass `query`, or any combination of the twenty-six filters, or nothing at all to walk the whole shop. Every row carries KEH's own product id, title (with the brace shorthand KEH prints in it pulled out as `title_tokens`), brand, price, how many units are in stock, the product URL, image and description. `meta.total_results` is KEH's own exact match count for the request, so a filter that bites and a filter that is ignored are told apart without guessing, and `meta.search_page_url` is the public KEH page that shows the same slice. IN-STOCK ONLY BY DEFAULT: 46,946 of the 54,499 indexed products are sold out and their indexed price is stale, so pass `in_stock=any` if you want those records too. NOTE `price` is the CHEAPEST grade's price — the catalogue index carries no per-grade price (measured against the product page: one body indexed at $1,352 is offered at $1,352 / $1,469 / $1,527 across its three grades) — so call `product` to see which grades exist.

**Parameters:**
- `query` (string, optional) — Free-text keyword over KEH's catalogue (model, brand, lens, accessory). Leave it out to browse the whole catalogue and filter instead. ⚠️ MEASURED 2026-10-08: KEH's search RELAXES rather than answering empty, so a keyword that matches nothing still returns rows — 'zzqqxxnotathingqq' returned 1,217, 'qwertyasdfzxcv' 870, 'xyzzy plugh frobnitz' 4, 'gibberishwordhere' 1. The relevance score does not separate a real hit from that fallback (520.9 vs 505.3), so judge a long-tail keyword by the row titles, not by the fact that rows came back. A precise model name is exact: 'canon eos r6' 157 rows, 'canon eos r6 mark ii black body' 13, 'hasselblad 503cw' 293.
- `brand` (array, optional) — One or more brands as KEH spells them. 577 are live; the largest on 2026-10-08 are Nikon 3,782, Miscellaneous 3,163, Canon 2,983, Leica 2,850, Sigma 1,848, Pentax 1,629, Sony 1,366, Fuji 1,311, Olympus 1,301, Vivitar 1,231, Minolta 1,174, Hasselblad 1,134. Several values are OR-ed (measured: Canon 2,983 + Nikon 3,782 = 6,765). Call `facets` for the live list with counts.
- `category` (array, optional) — One or more of KEH's own category IDS (not names — the index filters on the id). 135 are live: 8226 Used Camera Lenses (15,795), 8231 Accessories (18,390), 8258 Used Cameras (9,248), 8227 Used SLR & DSLR Lenses (9,939), 8373 Used Film Cameras (4,948), 8369 Used Digital Cameras (4,323), 8240 Tripods & Supports (4,692)… A parent id includes its children. The `categories` action returns the whole tree with ids, parents, breadcrumbs and counts.
- `grade` (array, optional) — KEH's OWN cosmetic grade — the field that makes a used-gear listing. KEH inspects and grades every item itself: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is (its short forms LN, LN-, EX+, EX, BGN, UG are accepted too). Several values are OR-ed. ⚠️ A grade only exists on a product KEH actually has in stock: with `in_stock=false` the grade facet comes back EMPTY (measured), so combining `grade` with out-of-stock stock returns nothing, honestly. [one of: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is]
- `system` (array, optional) — KEH's own system family, which is how photographers actually shop a used catalogue: Tripods 3,481, Filters 3,138, Large Format 2,915, Nikon Manual Focus 2,443, Canon EOS 1,787, Nikon Autofocus 1,582, Sony E System 1,527, Leica M 1,485, Nikon Digital 1,415, Canon Digital 1,409, Canon Manual Focus 1,307… 139 live values; `facets` has the list.
- `product_type` (array, optional) — KEH's own gear class, a finer cut than `category`: 'Fixed Focal Length Lenses, Mfg' 5,646, 'Fixed Focal Length Lenses, Non-Mfg' 4,967, Filters 4,188, 'Point & Shoots' 3,529, Bodies 3,494, 'Zoom Lenses, Non-Mfg' 3,370, 'Tripod Accessories' 1,749, 'Lens Shades' 1,497, Flashes 1,317… 91 live values.
- `format` (array, optional) — Sensor or film coverage, in KEH's own spelling: 'Full Frame 35mm (24x36mm)' 14,010, 'APS-C & DX' 1,993, '4x5"' 968, 'Four Thirds' 763, '6x6 (56x56mm) & 2-1/4x2-1/4"' 688, '645 (56x42mm)' 367, '8x10"' 146… 75 live values.
- `lens_mount` (array, optional) — The lens bayonet, as KEH names it — 257 live values, which is the point of a catalogue this old: 'Canon EF' 1,629, 'Sony E Mount' 964, 'Sony A & Minolta A' 898, 'Leica M' 882, 'Canon FD' 848, 'Nikon F Mount Ai' 818, 'M42 - Pentax Screw' 744, 'Micro Four Thirds' 742, 'Minolta MD' 663 … down to 'Agfa Agfaflex III,IV,V & Ambiflex I,II,III' with exactly 1. Pass the spelling `facets` gives you; it is long and exact.
- `megapixels` (array, optional) — Sensor resolution as KEH buckets it, including the unit: '16 MP' 794, '12 MP' 632, '10 MP' 388, '14 MP' 343, '24 MP' 314, '20 MP' 313, '45 MP', '60MP'… 49 live values, only set on digital bodies (4,098 products carry one).
- `film_type` (array, optional) — Which film the camera takes, with its 2026-10-08 counts. Only film gear carries it (3,507 products). Two values KEH's own taxonomy lists are left out of this list on purpose - 'Instax Mini' (37) and '70mm roll' (9) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured), so they are refused with that reason instead of answered with an empty success. [one of: 35mm roll, 120 roll, 220 roll, 4x5 sheet, 5x7 sheet, 8x10 sheet, 11x14 sheet, Instax Wide, Instax Square, APS cartridge, 110 cartridge, 126 cartridge, 127 roll, 116 roll, 620 roll, 8mm roll, 16mm roll, Super 8 cartridge, Polaroid Spectra cartridge, Polaroid Type 80 cartridge]
- `filter_size` (array, optional) — Filter thread / series size with its unit: '52mm' 1,977, '55mm' 1,554, '77mm' 1,441, '58mm' 1,374, '72mm' 1,369, '67mm' 1,252, '62mm' 1,241, '49mm' 1,025, '82mm' 627, '40.5mm (.5 pitch)' 299… 80 live values.
- `filter_type` (array, optional) — What an optical filter does, with its 2026-10-08 counts. KEH holds 4,189 filters, which is a real part of why people shop used. Two of KEH's own values are left out - 'ND - Variable Neutral Density' (58) and 'Cross-Screen / Star' (23) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured). [one of: UV / Haze / Skylight, Black & White Contrast, Polarizing - Circular Polarizers, ND - Fixed Neutral Density, Clear & Protective, Polarizing - Linear Polarizers, Diffuser / Soft Focus, ND - Graduated Neutral Density, Enhancing / Warming, IR - Infrared, Close-Up, Special Effects & Other, Color Conversion, ND - Center Neutral Density, Color Compensating, Scientific / Astronomy]
- `zoom_or_prime` (enum, optional) — Prime or zoom. The complete live vocabulary (two values) with its counts. [one of: prime, zoom]
- `focus_type` (enum, optional) — How the lens focuses — the complete live vocabulary with its counts. The camera-motor vs lens-motor split is the one that decides whether an old autofocus lens will actually focus on a modern body. [one of: manual_only, autofocus_lens_motor, autofocus_camera_motor, fixed_focus, manual_option]
- `lens_type` (array, optional) — Angle-of-view class — the complete live vocabulary with its 2026-10-08 counts. Several values are OR-ed. [one of: Telephoto / Long, Wide-Angle, Standard / Normal, Short Tele / Portrait, All-In-One, Ultrawide]
- `max_aperture` (array, optional) — Maximum aperture in KEH's own notation, zooms included: 'f/2.8' 3,178, 'f/3.5' 1,585, 'f/4' 1,068, 'f/5.6' 1,057, 'f/4.5' 1,035, 'f/2' 956, 'f/1.4' 772, 'f/3.5-4.5' 588, 'f/4-5.6' 577, 'f/1.8' 528, and cine 'T1.5'… 258 live values.
- `memory_card` (array, optional) — Which card the body takes: SDHC 1,698, SD 1,644, SDXC 1,478, 'SDXC UHS-I' 876, 'SDHC UHS-I' 815, 'Compact Flash (Type I)' 370, 'SDXC UHS-II' 292, 'CFxpress Type B' 58, 'CFast 2.0' 33… 32 live values. Two flaws in KEH's own data here, both reported rather than hidden: one value is the literal string '2931' (4 products), and 'Sony Memory Stick PRO Duo' (194) carries a stray trailing space that makes it unfilterable — that one is refused with the reason instead of answered with an empty success.
- `lens_design` (array, optional) — Special optical design — the complete live vocabulary with its counts. Several values are OR-ed. [one of: Macro Feature, Macro, Fisheye, Pancake, Tilt / Shift / Perspective Control, Mirror / Catadioptric, Soft Focus, Pinhole, Defocus Control, Stereo]
- `flash_system` (array, optional) — Which TTL flash protocol the gear speaks, which is exactly what an old flash needs matching: 'Canon E-TTL' 318, 'Canon E-TTL II' 271, 'Olympus/Panasonic TTL' 236, 'Nikon i-TTL' 190, 'Minolta/Sony TTL (Pre-Flash)' 184, 'Canon TTL (Film Cameras)' 181… 22 live values, all of them in `facets`.
- `photography_type` (array, optional) — KEH's own 'what is this for' tag — the complete live vocabulary with its 2026-10-08 counts. Multi-valued per product, several values are OR-ed. [one of: Travel Photography, Portraiture / People Photography, Street Photography, Landscape Photography, Sports Photography, Wedding Photography, Family Photography, Concert / Music Photography, Wildlife Photography, Vlogging Photography, Astrophotography, Underwater Photography, Aerial Photography]
- `tag` (array, optional) — KEH's own merchandising shelves — this is how you ask 'what did KEH just mark down' or 'what arrived this week' in one call. The list is live and moves with the shop's campaigns; `facets` always has the current one with counts. [one of: While Supplies Last, Overstock, New Lower Price, Back In Stock, Best Sellers, Newly Arrived, Featured Products, Rentable, Back To School]
- `gear_group` (array, optional) — KEH's coarse shop-grid grouping — the quickest way to split the catalogue into bodies vs lenses vs accessories without learning the 135-node category tree. The complete live vocabulary with its 2026-10-08 counts. [one of: Lenses, Other Accessories, Filters, Camera Bodies, Other Filters, Tripod Accessories, Flashes & Lights, Bags & Cases, Finders, Lens Converters, UV Filters, Grips, Backs, Extension Tubes, Polarizing Filters, Memory & Readers, Straps, Mics, Film]
- `in_stock` (enum, optional, default "true") — Whether to return gear KEH actually has. DEFAULTS TO TRUE, deliberately: 46,946 of the 54,499 indexed products are sold out, and on a sold-out record the price left in the index is STALE and the grade is gone (measured on pid 386988: indexed $1,266.00 with no grade while KEH's own page still showed a Bargain copy at $3,200.00). Pass 'any' or 'false' to see the sold-out records anyway — they are useful as a price history and a what-KEH-handles list — and read `price_is_live_offer` on every row, which is false exactly there. [one of: true, false, any]
- `price_min` (number, optional) — Lowest price to return, in US dollars as a decimal (e.g. 249.99). KEH's live band on 2026-10-08 ran from $1.00 to $24,242.00. Measured: 'Price:[100 TO 200]' returned 3,542 of 54,499.
- `price_max` (number, optional) — Highest price to return, in US dollars. ⚠️ It filters on the CHEAPEST grade's price, because that is the only price the catalogue index carries — see `price`.
- `focal_length_min` (number, optional) — Only lenses that reach at least this focal length (mm) at the wide end. KEH's live range is 1-1,200 mm at the short end and 3.2-1,300 mm at the long end, on the 15,868 products that publish a focal length at all.
- `focal_length_max` (number, optional) — Only lenses whose long end is at most this focal length (mm).
- `sort` (enum, optional, default "relevance") — Result order. Measured on the same Canon result set: price_asc first row $1.00, price_desc first row $13,010.00, so the ends are real. An unsupported sort value is REFUSED here on purpose — the source silently ignores one and hands back the unsorted order, which reads like a sort that worked. [one of: relevance, price_asc, price_desc, title_asc, title_desc]
- `page` (integer, optional, default 1) — Result page, 1-based. ⚠️ Paging is HARD-CAPPED by KEH's search service, which says so itself: at most 200 rows per call and a start offset of at most 10,000, so no single query can be walked past 10,200 rows. `meta.pagination` reports `depth_limit` and `depth_limit_reached`; to go deeper, split the query with a filter (by category, brand or price band) instead of paging on.
- `page_size` (integer, optional, default 24) — Rows per page, 1-200 (default 24). 200 is the service's own ceiling — it refuses 250 with 'Pagination limit exceeded ... Max start 10000, rows 200'.
- `include_pii` (boolean, optional, default false) — Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.

**Returns:** products[]{pid, title, title_tokens[], brand, url, image, price, price_from, currency, units_in_stock, in_stock, price_is_live_offer, description, relevance_score} + meta{total_results, currency, page, page_size, pagination, filters_applied, search_page_url, did_you_mean[], notes}}

**Example request body:**
```json
{
  "query": "canon eos r6",
  "sort": "price_asc"
}
```

### POST https://api.reefapi.com/keh/v1/product — 2 credits
The complete record of ONE product by its `pid` (or by its keh.com `url`). Adds everything a search row cannot carry: WHICH of KEH's grades it currently holds of this model, ranked best to worst; its full spec sheet as KEH's own catalogue describes it (system, gear type, coverage format, lens mount, megapixels, film type, filter thread and type, prime/zoom, focus type, maximum aperture, focal length range, memory-card types, special optical design, TTL flash system, intended uses); its category breadcrumb; KEH's merchandising tags; the unit count; and the cleaned description. Honest about its one real gap: KEH's per-grade prices live only on the product page, which answers a Cloudflare challenge to everything, so `per_grade_prices_available` is false and the index's own `price_range` is republished as `price_range_index` beside `price_range_is_grade_blind: true` rather than passed off as a grade ladder. A pid KEH does not index answers NOT_FOUND.

**Parameters:**
- `pid` (string, optional) — KEH's own product id, returned as `pid` by `search`. Pass this OR `url`. A pid that is not in the index answers NOT_FOUND, never an empty success.
- `url` (string, optional) — A keh.com product URL instead of a `pid` — paste the link straight from the shop. The index cannot be filtered by URL, so the engine resolves it through KEH's own keyword search over the slug and costs one extra upstream request; `pid` is the cheaper and exact way in.
- `include_pii` (boolean, optional, default false) — Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.

**Returns:** product{pid, title, title_tokens[], brand, url, image, price, price_from, currency, units_in_stock, in_stock, price_is_live_offer, description, relevance_score, grades_available[], grades_available_labels[], category_path[], tags[], stock_label, specs{}, price_range_index[], price_range_is_grade_blind, per_grade_prices_available} + meta{currency, grade_count, warnings}

**Example request body:**
```json
{
  "pid": "384010"
}
```

### POST https://api.reefapi.com/keh/v1/facets — 1 credit
The live filter taxonomy of KEH's catalogue: every brand, grade, category, system, gear type, lens mount, format, aperture, filter size and type, card type, flash system and intended use that actually has stock right now, each with KEH's own count — plus the price and focal-length ranges as real numeric spans. This is how you discover the exact value to pass to `search` instead of guessing it, and the counts alone answer questions a listing cannot ('how many Canon EF lenses does KEH hold today', 'how much of the shop is Bargain grade'). Takes every filter `search` takes, so you can ask for the taxonomy INSIDE a scope — the lens mounts available under Fujifilm, say.

**Parameters:**
- `facets` (array, optional) — Which filter taxonomies to return with their live counts. Left out, you get all 25 the index publishes. Every value here is a filter you can then pass to `search`, which is the point: discover the exact spelling instead of guessing it. `price`, `focal_length_min` and `focal_length_max` come back as a numeric `min`/`max` span rather than a value list, and `price` is the span the `price_min` / `price_max` filters work on. [one of: brand, category, film_type, filter_size, filter_type, flash_system, focal_length_max, focal_length_min, focus_type, format, gear_group, grade, in_stock, lens_design, lens_mount, lens_type, max_aperture, megapixels, memory_card, photography_type, price, product_type, system, tag, zoom_or_prime]
- `query` (string, optional) — Free-text keyword over KEH's catalogue (model, brand, lens, accessory). Leave it out to browse the whole catalogue and filter instead. ⚠️ MEASURED 2026-10-08: KEH's search RELAXES rather than answering empty, so a keyword that matches nothing still returns rows — 'zzqqxxnotathingqq' returned 1,217, 'qwertyasdfzxcv' 870, 'xyzzy plugh frobnitz' 4, 'gibberishwordhere' 1. The relevance score does not separate a real hit from that fallback (520.9 vs 505.3), so judge a long-tail keyword by the row titles, not by the fact that rows came back. A precise model name is exact: 'canon eos r6' 157 rows, 'canon eos r6 mark ii black body' 13, 'hasselblad 503cw' 293.
- `brand` (array, optional) — One or more brands as KEH spells them. 577 are live; the largest on 2026-10-08 are Nikon 3,782, Miscellaneous 3,163, Canon 2,983, Leica 2,850, Sigma 1,848, Pentax 1,629, Sony 1,366, Fuji 1,311, Olympus 1,301, Vivitar 1,231, Minolta 1,174, Hasselblad 1,134. Several values are OR-ed (measured: Canon 2,983 + Nikon 3,782 = 6,765). Call `facets` for the live list with counts.
- `category` (array, optional) — One or more of KEH's own category IDS (not names — the index filters on the id). 135 are live: 8226 Used Camera Lenses (15,795), 8231 Accessories (18,390), 8258 Used Cameras (9,248), 8227 Used SLR & DSLR Lenses (9,939), 8373 Used Film Cameras (4,948), 8369 Used Digital Cameras (4,323), 8240 Tripods & Supports (4,692)… A parent id includes its children. The `categories` action returns the whole tree with ids, parents, breadcrumbs and counts.
- `grade` (array, optional) — KEH's OWN cosmetic grade — the field that makes a used-gear listing. KEH inspects and grades every item itself: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is (its short forms LN, LN-, EX+, EX, BGN, UG are accepted too). Several values are OR-ed. ⚠️ A grade only exists on a product KEH actually has in stock: with `in_stock=false` the grade facet comes back EMPTY (measured), so combining `grade` with out-of-stock stock returns nothing, honestly. [one of: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is]
- `system` (array, optional) — KEH's own system family, which is how photographers actually shop a used catalogue: Tripods 3,481, Filters 3,138, Large Format 2,915, Nikon Manual Focus 2,443, Canon EOS 1,787, Nikon Autofocus 1,582, Sony E System 1,527, Leica M 1,485, Nikon Digital 1,415, Canon Digital 1,409, Canon Manual Focus 1,307… 139 live values; `facets` has the list.
- `product_type` (array, optional) — KEH's own gear class, a finer cut than `category`: 'Fixed Focal Length Lenses, Mfg' 5,646, 'Fixed Focal Length Lenses, Non-Mfg' 4,967, Filters 4,188, 'Point & Shoots' 3,529, Bodies 3,494, 'Zoom Lenses, Non-Mfg' 3,370, 'Tripod Accessories' 1,749, 'Lens Shades' 1,497, Flashes 1,317… 91 live values.
- `format` (array, optional) — Sensor or film coverage, in KEH's own spelling: 'Full Frame 35mm (24x36mm)' 14,010, 'APS-C & DX' 1,993, '4x5"' 968, 'Four Thirds' 763, '6x6 (56x56mm) & 2-1/4x2-1/4"' 688, '645 (56x42mm)' 367, '8x10"' 146… 75 live values.
- `lens_mount` (array, optional) — The lens bayonet, as KEH names it — 257 live values, which is the point of a catalogue this old: 'Canon EF' 1,629, 'Sony E Mount' 964, 'Sony A & Minolta A' 898, 'Leica M' 882, 'Canon FD' 848, 'Nikon F Mount Ai' 818, 'M42 - Pentax Screw' 744, 'Micro Four Thirds' 742, 'Minolta MD' 663 … down to 'Agfa Agfaflex III,IV,V & Ambiflex I,II,III' with exactly 1. Pass the spelling `facets` gives you; it is long and exact.
- `megapixels` (array, optional) — Sensor resolution as KEH buckets it, including the unit: '16 MP' 794, '12 MP' 632, '10 MP' 388, '14 MP' 343, '24 MP' 314, '20 MP' 313, '45 MP', '60MP'… 49 live values, only set on digital bodies (4,098 products carry one).
- `film_type` (array, optional) — Which film the camera takes, with its 2026-10-08 counts. Only film gear carries it (3,507 products). Two values KEH's own taxonomy lists are left out of this list on purpose - 'Instax Mini' (37) and '70mm roll' (9) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured), so they are refused with that reason instead of answered with an empty success. [one of: 35mm roll, 120 roll, 220 roll, 4x5 sheet, 5x7 sheet, 8x10 sheet, 11x14 sheet, Instax Wide, Instax Square, APS cartridge, 110 cartridge, 126 cartridge, 127 roll, 116 roll, 620 roll, 8mm roll, 16mm roll, Super 8 cartridge, Polaroid Spectra cartridge, Polaroid Type 80 cartridge]
- `filter_size` (array, optional) — Filter thread / series size with its unit: '52mm' 1,977, '55mm' 1,554, '77mm' 1,441, '58mm' 1,374, '72mm' 1,369, '67mm' 1,252, '62mm' 1,241, '49mm' 1,025, '82mm' 627, '40.5mm (.5 pitch)' 299… 80 live values.
- `filter_type` (array, optional) — What an optical filter does, with its 2026-10-08 counts. KEH holds 4,189 filters, which is a real part of why people shop used. Two of KEH's own values are left out - 'ND - Variable Neutral Density' (58) and 'Cross-Screen / Star' (23) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured). [one of: UV / Haze / Skylight, Black & White Contrast, Polarizing - Circular Polarizers, ND - Fixed Neutral Density, Clear & Protective, Polarizing - Linear Polarizers, Diffuser / Soft Focus, ND - Graduated Neutral Density, Enhancing / Warming, IR - Infrared, Close-Up, Special Effects & Other, Color Conversion, ND - Center Neutral Density, Color Compensating, Scientific / Astronomy]
- `zoom_or_prime` (enum, optional) — Prime or zoom. The complete live vocabulary (two values) with its counts. [one of: prime, zoom]
- `focus_type` (enum, optional) — How the lens focuses — the complete live vocabulary with its counts. The camera-motor vs lens-motor split is the one that decides whether an old autofocus lens will actually focus on a modern body. [one of: manual_only, autofocus_lens_motor, autofocus_camera_motor, fixed_focus, manual_option]
- `lens_type` (array, optional) — Angle-of-view class — the complete live vocabulary with its 2026-10-08 counts. Several values are OR-ed. [one of: Telephoto / Long, Wide-Angle, Standard / Normal, Short Tele / Portrait, All-In-One, Ultrawide]
- `max_aperture` (array, optional) — Maximum aperture in KEH's own notation, zooms included: 'f/2.8' 3,178, 'f/3.5' 1,585, 'f/4' 1,068, 'f/5.6' 1,057, 'f/4.5' 1,035, 'f/2' 956, 'f/1.4' 772, 'f/3.5-4.5' 588, 'f/4-5.6' 577, 'f/1.8' 528, and cine 'T1.5'… 258 live values.
- `memory_card` (array, optional) — Which card the body takes: SDHC 1,698, SD 1,644, SDXC 1,478, 'SDXC UHS-I' 876, 'SDHC UHS-I' 815, 'Compact Flash (Type I)' 370, 'SDXC UHS-II' 292, 'CFxpress Type B' 58, 'CFast 2.0' 33… 32 live values. Two flaws in KEH's own data here, both reported rather than hidden: one value is the literal string '2931' (4 products), and 'Sony Memory Stick PRO Duo' (194) carries a stray trailing space that makes it unfilterable — that one is refused with the reason instead of answered with an empty success.
- `lens_design` (array, optional) — Special optical design — the complete live vocabulary with its counts. Several values are OR-ed. [one of: Macro Feature, Macro, Fisheye, Pancake, Tilt / Shift / Perspective Control, Mirror / Catadioptric, Soft Focus, Pinhole, Defocus Control, Stereo]
- `flash_system` (array, optional) — Which TTL flash protocol the gear speaks, which is exactly what an old flash needs matching: 'Canon E-TTL' 318, 'Canon E-TTL II' 271, 'Olympus/Panasonic TTL' 236, 'Nikon i-TTL' 190, 'Minolta/Sony TTL (Pre-Flash)' 184, 'Canon TTL (Film Cameras)' 181… 22 live values, all of them in `facets`.
- `photography_type` (array, optional) — KEH's own 'what is this for' tag — the complete live vocabulary with its 2026-10-08 counts. Multi-valued per product, several values are OR-ed. [one of: Travel Photography, Portraiture / People Photography, Street Photography, Landscape Photography, Sports Photography, Wedding Photography, Family Photography, Concert / Music Photography, Wildlife Photography, Vlogging Photography, Astrophotography, Underwater Photography, Aerial Photography]
- `tag` (array, optional) — KEH's own merchandising shelves — this is how you ask 'what did KEH just mark down' or 'what arrived this week' in one call. The list is live and moves with the shop's campaigns; `facets` always has the current one with counts. [one of: While Supplies Last, Overstock, New Lower Price, Back In Stock, Best Sellers, Newly Arrived, Featured Products, Rentable, Back To School]
- `gear_group` (array, optional) — KEH's coarse shop-grid grouping — the quickest way to split the catalogue into bodies vs lenses vs accessories without learning the 135-node category tree. The complete live vocabulary with its 2026-10-08 counts. [one of: Lenses, Other Accessories, Filters, Camera Bodies, Other Filters, Tripod Accessories, Flashes & Lights, Bags & Cases, Finders, Lens Converters, UV Filters, Grips, Backs, Extension Tubes, Polarizing Filters, Memory & Readers, Straps, Mics, Film]
- `in_stock` (enum, optional, default "true") — Whether to return gear KEH actually has. DEFAULTS TO TRUE, deliberately: 46,946 of the 54,499 indexed products are sold out, and on a sold-out record the price left in the index is STALE and the grade is gone (measured on pid 386988: indexed $1,266.00 with no grade while KEH's own page still showed a Bargain copy at $3,200.00). Pass 'any' or 'false' to see the sold-out records anyway — they are useful as a price history and a what-KEH-handles list — and read `price_is_live_offer` on every row, which is false exactly there. [one of: true, false, any]
- `price_min` (number, optional) — Lowest price to return, in US dollars as a decimal (e.g. 249.99). KEH's live band on 2026-10-08 ran from $1.00 to $24,242.00. Measured: 'Price:[100 TO 200]' returned 3,542 of 54,499.
- `price_max` (number, optional) — Highest price to return, in US dollars. ⚠️ It filters on the CHEAPEST grade's price, because that is the only price the catalogue index carries — see `price`.
- `focal_length_min` (number, optional) — Only lenses that reach at least this focal length (mm) at the wide end. KEH's live range is 1-1,200 mm at the short end and 3.2-1,300 mm at the long end, on the 15,868 products that publish a focal length at all.
- `focal_length_max` (number, optional) — Only lenses whose long end is at most this focal length (mm).
- `include_pii` (boolean, optional, default false) — Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.

**Returns:** facets[]{filter, index_field, label, type, value_count, values[]{value, label, count, param_value, rank, parent_id}, min, max, product_count} + meta{total_results, currency, filters_applied}

**Example request body:**
```json
{
  "facets": "brand,grade,lens_mount"
}
```

### POST https://api.reefapi.com/keh/v1/categories — 1 credit
KEH's own category tree — 135 nodes with their id, name, parent, readable breadcrumb and live product count, deepest counts first. Pass it any `search` filter to get the tree WITHIN a scope (which categories hold Leica gear, which hold something in Bargain grade). The ids it returns are exactly what the `category` filter takes.

**Parameters:**
- `query` (string, optional) — Free-text keyword over KEH's catalogue (model, brand, lens, accessory). Leave it out to browse the whole catalogue and filter instead. ⚠️ MEASURED 2026-10-08: KEH's search RELAXES rather than answering empty, so a keyword that matches nothing still returns rows — 'zzqqxxnotathingqq' returned 1,217, 'qwertyasdfzxcv' 870, 'xyzzy plugh frobnitz' 4, 'gibberishwordhere' 1. The relevance score does not separate a real hit from that fallback (520.9 vs 505.3), so judge a long-tail keyword by the row titles, not by the fact that rows came back. A precise model name is exact: 'canon eos r6' 157 rows, 'canon eos r6 mark ii black body' 13, 'hasselblad 503cw' 293.
- `brand` (array, optional) — One or more brands as KEH spells them. 577 are live; the largest on 2026-10-08 are Nikon 3,782, Miscellaneous 3,163, Canon 2,983, Leica 2,850, Sigma 1,848, Pentax 1,629, Sony 1,366, Fuji 1,311, Olympus 1,301, Vivitar 1,231, Minolta 1,174, Hasselblad 1,134. Several values are OR-ed (measured: Canon 2,983 + Nikon 3,782 = 6,765). Call `facets` for the live list with counts.
- `category` (array, optional) — One or more of KEH's own category IDS (not names — the index filters on the id). 135 are live: 8226 Used Camera Lenses (15,795), 8231 Accessories (18,390), 8258 Used Cameras (9,248), 8227 Used SLR & DSLR Lenses (9,939), 8373 Used Film Cameras (4,948), 8369 Used Digital Cameras (4,323), 8240 Tripods & Supports (4,692)… A parent id includes its children. The `categories` action returns the whole tree with ids, parents, breadcrumbs and counts.
- `grade` (array, optional) — KEH's OWN cosmetic grade — the field that makes a used-gear listing. KEH inspects and grades every item itself: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is (its short forms LN, LN-, EX+, EX, BGN, UG are accepted too). Several values are OR-ed. ⚠️ A grade only exists on a product KEH actually has in stock: with `in_stock=false` the grade facet comes back EMPTY (measured), so combining `grade` with out-of-stock stock returns nothing, honestly. [one of: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is]
- `system` (array, optional) — KEH's own system family, which is how photographers actually shop a used catalogue: Tripods 3,481, Filters 3,138, Large Format 2,915, Nikon Manual Focus 2,443, Canon EOS 1,787, Nikon Autofocus 1,582, Sony E System 1,527, Leica M 1,485, Nikon Digital 1,415, Canon Digital 1,409, Canon Manual Focus 1,307… 139 live values; `facets` has the list.
- `product_type` (array, optional) — KEH's own gear class, a finer cut than `category`: 'Fixed Focal Length Lenses, Mfg' 5,646, 'Fixed Focal Length Lenses, Non-Mfg' 4,967, Filters 4,188, 'Point & Shoots' 3,529, Bodies 3,494, 'Zoom Lenses, Non-Mfg' 3,370, 'Tripod Accessories' 1,749, 'Lens Shades' 1,497, Flashes 1,317… 91 live values.
- `format` (array, optional) — Sensor or film coverage, in KEH's own spelling: 'Full Frame 35mm (24x36mm)' 14,010, 'APS-C & DX' 1,993, '4x5"' 968, 'Four Thirds' 763, '6x6 (56x56mm) & 2-1/4x2-1/4"' 688, '645 (56x42mm)' 367, '8x10"' 146… 75 live values.
- `lens_mount` (array, optional) — The lens bayonet, as KEH names it — 257 live values, which is the point of a catalogue this old: 'Canon EF' 1,629, 'Sony E Mount' 964, 'Sony A & Minolta A' 898, 'Leica M' 882, 'Canon FD' 848, 'Nikon F Mount Ai' 818, 'M42 - Pentax Screw' 744, 'Micro Four Thirds' 742, 'Minolta MD' 663 … down to 'Agfa Agfaflex III,IV,V & Ambiflex I,II,III' with exactly 1. Pass the spelling `facets` gives you; it is long and exact.
- `megapixels` (array, optional) — Sensor resolution as KEH buckets it, including the unit: '16 MP' 794, '12 MP' 632, '10 MP' 388, '14 MP' 343, '24 MP' 314, '20 MP' 313, '45 MP', '60MP'… 49 live values, only set on digital bodies (4,098 products carry one).
- `film_type` (array, optional) — Which film the camera takes, with its 2026-10-08 counts. Only film gear carries it (3,507 products). Two values KEH's own taxonomy lists are left out of this list on purpose - 'Instax Mini' (37) and '70mm roll' (9) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured), so they are refused with that reason instead of answered with an empty success. [one of: 35mm roll, 120 roll, 220 roll, 4x5 sheet, 5x7 sheet, 8x10 sheet, 11x14 sheet, Instax Wide, Instax Square, APS cartridge, 110 cartridge, 126 cartridge, 127 roll, 116 roll, 620 roll, 8mm roll, 16mm roll, Super 8 cartridge, Polaroid Spectra cartridge, Polaroid Type 80 cartridge]
- `filter_size` (array, optional) — Filter thread / series size with its unit: '52mm' 1,977, '55mm' 1,554, '77mm' 1,441, '58mm' 1,374, '72mm' 1,369, '67mm' 1,252, '62mm' 1,241, '49mm' 1,025, '82mm' 627, '40.5mm (.5 pitch)' 299… 80 live values.
- `filter_type` (array, optional) — What an optical filter does, with its 2026-10-08 counts. KEH holds 4,189 filters, which is a real part of why people shop used. Two of KEH's own values are left out - 'ND - Variable Neutral Density' (58) and 'Cross-Screen / Star' (23) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured). [one of: UV / Haze / Skylight, Black & White Contrast, Polarizing - Circular Polarizers, ND - Fixed Neutral Density, Clear & Protective, Polarizing - Linear Polarizers, Diffuser / Soft Focus, ND - Graduated Neutral Density, Enhancing / Warming, IR - Infrared, Close-Up, Special Effects & Other, Color Conversion, ND - Center Neutral Density, Color Compensating, Scientific / Astronomy]
- `zoom_or_prime` (enum, optional) — Prime or zoom. The complete live vocabulary (two values) with its counts. [one of: prime, zoom]
- `focus_type` (enum, optional) — How the lens focuses — the complete live vocabulary with its counts. The camera-motor vs lens-motor split is the one that decides whether an old autofocus lens will actually focus on a modern body. [one of: manual_only, autofocus_lens_motor, autofocus_camera_motor, fixed_focus, manual_option]
- `lens_type` (array, optional) — Angle-of-view class — the complete live vocabulary with its 2026-10-08 counts. Several values are OR-ed. [one of: Telephoto / Long, Wide-Angle, Standard / Normal, Short Tele / Portrait, All-In-One, Ultrawide]
- `max_aperture` (array, optional) — Maximum aperture in KEH's own notation, zooms included: 'f/2.8' 3,178, 'f/3.5' 1,585, 'f/4' 1,068, 'f/5.6' 1,057, 'f/4.5' 1,035, 'f/2' 956, 'f/1.4' 772, 'f/3.5-4.5' 588, 'f/4-5.6' 577, 'f/1.8' 528, and cine 'T1.5'… 258 live values.
- `memory_card` (array, optional) — Which card the body takes: SDHC 1,698, SD 1,644, SDXC 1,478, 'SDXC UHS-I' 876, 'SDHC UHS-I' 815, 'Compact Flash (Type I)' 370, 'SDXC UHS-II' 292, 'CFxpress Type B' 58, 'CFast 2.0' 33… 32 live values. Two flaws in KEH's own data here, both reported rather than hidden: one value is the literal string '2931' (4 products), and 'Sony Memory Stick PRO Duo' (194) carries a stray trailing space that makes it unfilterable — that one is refused with the reason instead of answered with an empty success.
- `lens_design` (array, optional) — Special optical design — the complete live vocabulary with its counts. Several values are OR-ed. [one of: Macro Feature, Macro, Fisheye, Pancake, Tilt / Shift / Perspective Control, Mirror / Catadioptric, Soft Focus, Pinhole, Defocus Control, Stereo]
- `flash_system` (array, optional) — Which TTL flash protocol the gear speaks, which is exactly what an old flash needs matching: 'Canon E-TTL' 318, 'Canon E-TTL II' 271, 'Olympus/Panasonic TTL' 236, 'Nikon i-TTL' 190, 'Minolta/Sony TTL (Pre-Flash)' 184, 'Canon TTL (Film Cameras)' 181… 22 live values, all of them in `facets`.
- `photography_type` (array, optional) — KEH's own 'what is this for' tag — the complete live vocabulary with its 2026-10-08 counts. Multi-valued per product, several values are OR-ed. [one of: Travel Photography, Portraiture / People Photography, Street Photography, Landscape Photography, Sports Photography, Wedding Photography, Family Photography, Concert / Music Photography, Wildlife Photography, Vlogging Photography, Astrophotography, Underwater Photography, Aerial Photography]
- `tag` (array, optional) — KEH's own merchandising shelves — this is how you ask 'what did KEH just mark down' or 'what arrived this week' in one call. The list is live and moves with the shop's campaigns; `facets` always has the current one with counts. [one of: While Supplies Last, Overstock, New Lower Price, Back In Stock, Best Sellers, Newly Arrived, Featured Products, Rentable, Back To School]
- `gear_group` (array, optional) — KEH's coarse shop-grid grouping — the quickest way to split the catalogue into bodies vs lenses vs accessories without learning the 135-node category tree. The complete live vocabulary with its 2026-10-08 counts. [one of: Lenses, Other Accessories, Filters, Camera Bodies, Other Filters, Tripod Accessories, Flashes & Lights, Bags & Cases, Finders, Lens Converters, UV Filters, Grips, Backs, Extension Tubes, Polarizing Filters, Memory & Readers, Straps, Mics, Film]
- `in_stock` (enum, optional, default "true") — Whether to return gear KEH actually has. DEFAULTS TO TRUE, deliberately: 46,946 of the 54,499 indexed products are sold out, and on a sold-out record the price left in the index is STALE and the grade is gone (measured on pid 386988: indexed $1,266.00 with no grade while KEH's own page still showed a Bargain copy at $3,200.00). Pass 'any' or 'false' to see the sold-out records anyway — they are useful as a price history and a what-KEH-handles list — and read `price_is_live_offer` on every row, which is false exactly there. [one of: true, false, any]
- `price_min` (number, optional) — Lowest price to return, in US dollars as a decimal (e.g. 249.99). KEH's live band on 2026-10-08 ran from $1.00 to $24,242.00. Measured: 'Price:[100 TO 200]' returned 3,542 of 54,499.
- `price_max` (number, optional) — Highest price to return, in US dollars. ⚠️ It filters on the CHEAPEST grade's price, because that is the only price the catalogue index carries — see `price`.
- `focal_length_min` (number, optional) — Only lenses that reach at least this focal length (mm) at the wide end. KEH's live range is 1-1,200 mm at the short end and 3.2-1,300 mm at the long end, on the 15,868 products that publish a focal length at all.
- `focal_length_max` (number, optional) — Only lenses whose long end is at most this focal length (mm).
- `include_pii` (boolean, optional, default false) — Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.

**Returns:** categories[]{category_id, name, parent_id, parent_name, crumb, path[], product_count} + meta{total_results, filters_applied}

**Example request body:**
```json
{
  "query": "canon eos r6"
}
```

### POST https://api.reefapi.com/keh/v1/suggest — 1 credit
KEH's own search autocomplete: turn a half-typed camera or lens name into the queries KEH actually resolves. One small request (under 5 KB measured), meant to be called before `search` so a keyword lands on real gear — which matters here, because KEH's search never answers empty and will relax a miss into a catalogue slice instead.

**Parameters:**
- `query` (string, required) — A partial model or brand name — KEH's own search box resolves it the same way. At least three characters (KEH's own widget waits for three).
- `count` (integer, optional, default 10) — How many suggestions to return (1-20, default 10). KEH's service returns a fixed group and this trims it, so asking for more than it holds is not an error.
- `include_pii` (boolean, optional, default false) — Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.

**Returns:** suggestions[]{term, display_text} + meta{query, count}

**Example request body:**
```json
{
  "query": "canon eos",
  "count": 10
}
```

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