Enjoei API & Scraper
The Enjoei API returns Brazil's largest second-hand marketplace as clean JSON in eight actions: search, product/detail, product/similar, seller/listings, seller/sold, seller/profile, filters and suggest.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
search takes a Portuguese keyword or browses a department, sub-category or brand, and filters by price range, condition (used or new), clothing/shoe/waist size, discount percentage, seller location and how recently the item was listed, sorted by relevance, cheapest, dearest or biggest discount. Every row carries the listing id, slug and URL, the title, the asking price in BRL, the seller's struck-through price when the item is reduced, a computed discount percentage, condition, size and the available size variants, brand, department, category and sub-category, the photo, whether shipping is free, and the seller's shop handle, display name and shop URL. product/detail adds the full description, every photo, the item's weight in kilograms, the category breadcrumb, Google's product category, whether the listing is still on sale, and the offer range the seller has said they will consider — Enjoei is a haggling marketplace, so that band is published. seller/sold is the one most marketplaces do not give you: a shop's completed sales with both the price the item was listed at and the price it actually sold for. Measured on 2026-09-23: 86 of 86 live calls returned data; a 30-row search answered in a median 0.88 s and a listing in 1.9 s; on 14 listings across 8 categories the price product/detail returns matched the price on the item's own page 14 times out of 14. No Enjoei account is involved. One ReefAPI key, one shared credit pool, the standard { ok, data, meta, error } envelope.
What a live call returns — 400 rows across eight categories, counted not assumed
Fifty search rows were taken from each of eight categories on 2026-09-23 (sportswear, electronics, womenswear, bags, toys, books, footwear, watches) and every field counted. Two of these lines go against us; they are the ones worth reading.
| Field | Filled (of 400) | Why it is not always filled |
|---|---|---|
| listing id, URL, title, price, currency, discount percentage | 400 | — |
| condition (used or new), brand, department, category | 400 | — |
| photo, free shipping, shipping type | 400 | — |
| seller handle, display name, shop URL, avatar | 400 | — |
| sub-category | 347 | shallow on books (7 of 50); department and category are still complete there |
| struck-through price and promotion tag | 215 | only on a reduced listing — 54% of rows, steady across all eight categories |
| size and size variants | 155 | a clothing field: ~100% on womenswear and footwear, 47 of 50 on sportswear, and 0-4% on bags, watches, electronics and toys, which have no size on Enjoei |
| like count, view count, listing date, sold date, colour, seller rating | 0 | Enjoei does not publish any of them on a listing — see the coverage table |
Speed and size, 2026-09-23, 86 consecutive live calls, all returning data: search 40 calls, median 877 ms, about 36 KB for 30 rows; product/detail 10 calls, median 1.9 s, about 4 KB; seller/profile 27 calls, median 1.7 s, about 1 KB; seller/listings 2 calls, median 2.2 s; seller/sold 3 calls, median 1.5 s, 40 rows; product/similar median 1.7 s; filters 2 calls, median 779 ms; suggest median 943 ms.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/enjoei/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "nike",
"per_page": 30
}
}{
"ok": true,
"meta": {
"api": "enjoei",
"endpoint": "search",
"mode": "live",
"latency_ms": 666.5,
"record_count": 30,
"bytes": 36437,
"cache_hit": false,
"pagination": {
"page_size": 30,
"next_cursor": "167687559023008922:1",
"has_more": true
},
"upstream_requests": 1,
"charged_credits": 1,
"version": "0.1.0"
},
"data": {
"results": [
{
"listing_id": "151454979",
"slug": "tenis-nike-lebron-xviii-low-space-jam-42-43-us-10-5-151454979",
"url": "https://www.enjoei.com.br/p/tenis-nike-lebron-xviii-low-space-jam-42-43-us-10-5-151454979",
"title": "tênis nike lebron xviii low space jam 42/43 us 10.5",
"price": 2000,
"original_price": null,
"discount_percent": 0,
"currency": "BRL",
"condition": "new",
"condition_label": "novo",
"size": "42",
"sizes": [
"42"
],
"size_slug": "42",
"variants": [
{
"name": "[trimmed-depth]",
"slug": "[trimmed-depth]",
"available": "[trimmed-depth]"
}
],
"brand": "nike",
"department": "rapazes",
"category": "rapazes-calcados",
"subcategory": "rapazes-calcados-tenis",
"image": "https://photos.enjoei.com.br/public/800x800/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy8yMzA1MjQ0My8xYzk5M2ZkZDFiNWQ1OTc1YzQyODk2MGM2OWM0YjQ2MC5qcGc",
"image_id": "czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy8yMzA1MjQ0My8xYzk5M2ZkZDFiNWQ1OTc1YzQyODk2MGM2OWM0YjQ2MC5qcGc",
"free_shipping": false,
"shipping_type": "charge_by_weight",
"bundle_allowed": true,
"promo_tags": null,
"seller": {
"username": "bruno-f9d16e",
"display_name": "Bruno",
"url": "https://www.enjoei.com.br/@bruno-f9d16e",
"avatar": "https://photos.enjoei.com.br/public/200x200/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9hdmF0YXJzLzIzMDUyNDQzLzUxY2IyY2MwYjUyYzZhYjcyYjg5YTQ0Yjg0YThiYmNmLmpwZw"
}
},
{
"listing_id": "151454963",
"slug": "bermuda-nike-racing-club-preta-151454963",
"url": "https://www.enjoei.com.br/p/bermuda-nike-racing-club-preta-151454963",
"title": "bermuda nike racing club preta",
"price": 390,
"original_price": null,
"discount_percent": 0,
"currency": "BRL",
"condition": "used",
"condition_label": "usado",
"size": "G",
"sizes": [
"G"
],
"size_slug": "g",
"variants": [
{
"name": "[trimmed-depth]",
"slug": "[trimmed-depth]",
"available": "[trimmed-depth]"
}
],
"brand": "nike",
"department": "rapazes",
"category": "rapazes-roupas",
"subcategory": "rapazes-roupas-bermudas",
"image": "https://photos.enjoei.com.br/public/800x800/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy84NTExMTg4LzE4NTU1MzUxZDhjODZjZWY5NjMzMWIxZGMzN2QyYzllLmpwZw",
"image_id": "czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy84NTExMTg4LzE4NTU1MzUxZDhjODZjZWY5NjMzMWIxZGMzN2QyYzllLmpwZw",
"free_shipping": false,
"shipping_type": "charge_by_weight",
"bundle_allowed": true,
"promo_tags": null,
"seller": {
"username": "felipe-03d5b7",
"display_name": "felipe",
"url": "https://www.enjoei.com.br/@felipe-03d5b7",
"avatar": "https://photos.enjoei.com.br/public/200x200/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9kZWZhdWx0aW1hZ2VzL3VzZXIvZGRhMGY2MWU4ODIxODgwYmMyZjliYzQ3NDViZWY2MmUuanBn"
}
},
{
"listing_id": "151379064",
"slug": "tenis-nike-grandstand-2-camurca-br-43-us-11-151379064",
"url": "https://www.enjoei.com.br/p/tenis-nike-grandstand-2-camurca-br-43-us-11-151379064",
"title": "tênis nike grandstand 2 camurça br 43 us 11",
"price": 350,
"original_price": null,
"discount_percent": 0,
"currency": "BRL",
"condition": "new",
"condition_label": "novo",
"size": "43",
"sizes": [
"43"
],
"size_slug": "43",
"variants": [
{
"name": "[trimmed-depth]",
"slug": "[trimmed-depth]",
"available": "[trimmed-depth]"
}
],
"brand": "nike",
"department": "rapazes",
"category": "rapazes-calcados",
"subcategory": "rapazes-calcados-tenis",
"image": "https://photos.enjoei.com.br/public/800x800/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy80MzI4NDc0NC9hNjQxYjkwOGYzMmQ2ZWFiNmFiZmIxNmM0ZjAzM2YwMS5qcGc",
"image_id": "czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9wcm9kdWN0cy80MzI4NDc0NC9hNjQxYjkwOGYzMmQ2ZWFiNmFiZmIxNmM0ZjAzM2YwMS5qcGc",
"free_shipping": false,
"shipping_type": "charge_by_weight",
"bundle_allowed": true,
"promo_tags": null,
"seller": {
"username": "t3store",
"display_name": "Ramon",
"url": "https://www.enjoei.com.br/@t3store",
"avatar": "https://photos.enjoei.com.br/public/200x200/czM6Ly9waG90b3MuZW5qb2VpLmNvbS5ici9hdmF0YXJzLzQzMjg0NzQ0L2NhODNiM2M3NmFjYzgzNmIwZmQ5ZWEzYTg0YzEzZDk1LmpwZw"
}
}
],
"count": 30,
"total_results": 10000,
"total_results_capped": true,
"next_cursor": "167687559023008922:1",
"has_more": true,
"tiles_dropped": 0,
"filters": {
"sort": "relevance"
},
"query": "nike"
}
}What the Enjoei API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search Enjoei's live second-hand catalogue by keyword, brand, department, size, price, condition, discount or seller location. Returns the asking price and the seller's struck-through reference price on every row. | Pricing teams call search to search Enjoei's live second-hand catalogue by keyword, brand, department, size, price, condit…. | query, department, subcategory, brand, price_min, ... |
| product/detail | One listing in full: the LIVE price (read from Enjoei's own pricing route, not the search index), description, every photo, weight, size, brand, category path, the offer range the seller will consider, and whether it is still on sale. | Marketplace operators call product/detail to get one listing in full. | listing, max_rotations |
| product/similar | Listings comparable to a given one — same sub-category, same brand and a price band around it, which is the recipe Enjoei's own page uses. Useful for pricing a second-hand item against live competition. | Catalog enrichment teams call product/similar to get listings comparable to a given one. | listing, per_page, sort, condition, max_rotations |
| seller/listings | Everything a shop currently has for sale, with the same row shape as search and the same filters. | Retail analysts call seller/listings to get everything a shop currently has for sale, with the same row shape as search and the same filt…. | seller, seller_id, query, brand, subcategory, ... |
| seller/sold | A shop's completed sales: what the item was listed at AND what it actually sold for. Enjoei publishes both, which makes this the price-comparison surface for second-hand goods in Brazil. | Pricing teams call seller/sold to get a shop's completed sales. | seller, page, max_rotations |
| seller/profile | A shop's public page: handle, display name, city/state, bio, avatar, the date it joined, and its public counters — items for sale, items sold, likes received, followers and following. | Marketplace operators call seller/profile to get a shop's public page. | seller, max_rotations |
| filters | The brand and sub-category facets Enjoei itself offers for a query, each with its live listing count — the slugs you feed back into `search`. | Catalog enrichment teams call filters to get the brand and sub-category facets Enjoei itself offers for a query, each with its live listin…. | query, department, subcategory, brand, price_min, ... |
| suggest | Enjoei's own search typeahead: completed search terms and matching shops. | Retail analysts call suggest to get enjoei's own search typeahead. | term, max_rotations |
Call search from your stack
curl -X POST https://api.reefapi.com/enjoei/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"nike","per_page":30}'import requests
r = requests.post(
"https://api.reefapi.com/enjoei/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "nike",
"per_page": 30
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/enjoei/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "nike",
"per_page": 30
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.enjoei.search with {"query":"nike","per_page":30}.Who uses this API and why
- Price a second-hand item for the Brazilian market: search comparable listings, then read what a shop's equivalents actually sold for with seller/sold.
- Track resale value of a brand or model over time by polling search with a fixed brand and sub-category and recording the price distribution.
- Find under-priced stock for resale: sort by biggest discount, or filter discount_min with a price ceiling, and check the offer range on each candidate.
- Build a Brazilian second-hand feed for a fashion or sneaker app, filtered by department, size and condition.
- Research a shop before buying or partnering: seller/profile for its public counters and joining date, seller/listings for what it stocks, seller/sold for what it has shifted.
Questions developers ask before integrating
What did the item actually sell for?
seller/sold answers that, and it is the reason to use this API for second-hand pricing in Brazil. Each row of a shop's completed sales carries both numbers: price, what the seller was asking, and sold_price, what a buyer actually paid. A measured example: a Nike t-shirt listed at R$65 sold for R$41. Enjoei publishes this per shop, 40 rows a page, newest first. There is no marketplace-wide sold search, and no sale date.
Is original_price a real discount?
Yes, and it is only there when it is real. Enjoei sends the reference price and the current price on every row, and on an undiscounted listing the two are the same number. Returning that as a struck-through price would invent a discount on every item, so original_price is returned only when it is genuinely higher than the price you pay. It was filled on 215 of 400 rows measured; on the other 185 it is null and discount_percent is 0.
Why can the price on a search row differ from the price on product/detail?
Because Enjoei's search index keeps its own copy of the price and it can lag behind a re-pricing. On 14 listings checked against their own product pages, product/detail matched the page 14 times out of 14, while the search-index copy differed on 5 of them, by as much as a third — one item indexed at R$160 was really R$238. Use search rows to find and rank items, and product/detail for the number you are going to quote or transact on.
What is the offer range on a listing?
Enjoei is a haggling marketplace: buyers make offers and sellers publish the band they will consider. product/detail returns it as offer, with accepted, min_price and max_price — for example a R$150 listing accepting offers between R$90 and R$149. It is a negotiating band, not a price anything sold at; for real sale prices use seller/sold.
Does the API tell me when a listing was posted or sold?
No, and no approximation is invented. Enjoei does not publish a listing date, a sold date, a like count, a view count, a colour or a per-listing seller rating anywhere a logged-out visitor can see, so none of them are returned. What you can do is filter by recency: published_within accepts 24h, 7d, 14d or 30d and Enjoei applies it server-side — on one measured query it cut 10,000+ matches to 302.
How many results can I page through?
Fifty rows per page, by cursor. Enjoei clamps the page size at 50 and silently ignores anything larger, so the API caps it too rather than promising a page it will not deliver. A 4-page walk returned 200 listings with no repeats. total_results is Enjoei's own count and stops at 10,000; when it does, total_results_capped comes back true, so you never mistake a ceiling for a total.
Can I sort by newest?
No. Enjoei's own ordering choices are relevance, cheapest, dearest and biggest discount, and those four are what the API offers. Other sort words are accepted by the source and then quietly ignored, which would look like a working filter and be a lie, so they are rejected with INVALID_PARAM instead. For recency use the published_within filter.
Whose data is in the seller block?
The public storefront only: the shop's @handle, its display name, shop URL, avatar and cover image, the date it joined, and its public counters — items for sale, items sold, likes received, followers and following. Sellers on Enjoei are private individuals running a shop page, so nothing beyond the shop page itself is read or returned.
What is the Enjoei API?
Enjoei API is a ReefAPI endpoint group for brazil's biggest second-hand marketplace: asking price, struck price and what items actually sold for. It returns live JSON through POST requests under /enjoei/v1.
Is the Enjoei API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Enjoei calls use the same shared credit balance as every other ReefAPI engine.
Do I need an Enjoei login or account?
No login to Enjoei is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Enjoei data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Enjoei API use?
Enjoei actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Enjoei from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call enjoei actions with the same key, credit pool and JSON envelope used by normal REST requests.