US local classifieds as JSON, scoped to the metro you actually want
The OfferUp API returns the large US local classifieds marketplace as clean JSON, in two actions: search and product/detail.
2 active endpoints. Every call is 1 credit.
- POST/offerup/v1/search
- POST/offerup/v1/product/detail
What OfferUp endpoints does ReefAPI ship?
2 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
OfferUp API
2 of 2 endpoints, ready to run
The OfferUp feed near a US location: listing id and URL, title, the price as a number in USD with OfferUp's own formatted string, the town, the photo and the tile flags — about 44 to 50 rows, plus a cursor for the next page.
{ "ok": true, "meta": { "api": "offerup", "endpoint": "search", "mode": "live", "latency_ms": 1045.9, "record_count": 44, "cache_hit": false }, "data": { "results": [ { "listing_id": "758a280b-44d6-343f-9604-04cff565d22b", "title": "Modular Sectional Sofa Couch", "price": 1350, "price_display": "$1,350", "currency": "USD", "call_for_price": false, "is_firm_price": null, "condition": null, "location": { "name": "South Gate, CA", "latitude": null, "longitude": null }, "image": { "url": "https://images.offerup.com/WZiRf0hh3ZKxyp0yQxY_uiEHnt4=/250x250/339c/339cbc0403bc4506bf99fc9eb9ab945e.jpg", "width": 250, "height": 250 }, "vehicle_miles": null, "flags": [ "LOCAL_PICKUP" ], "url": "https://offerup.com/item/detail/758a280b-44d6-343f-9604-04cff565d22b", "rating": null, "review_count": null, "rating_scale": null, "position": 1 }, { "listing_id": "8840afca-7efc-329c-b3ce-f716548fb181", "title": "Sofa couch, firm on price", "price": 140, "price_display": "$140", "currency": "USD", "call_for_price": false, "is_firm_price": null, "condition": null, "location": { "name": "Rosemead, CA", "latitude": null, "longitude": null }, "image": { "url": "https://images.offerup.com/lcMUYZ7FhtI1hUkCRZzlS8ByY2I=/250x333/855e/855e090e8b424cb29ffbbf716913ae0c.jpg", "width": 250, "height": 333 }, "vehicle_miles": null, "flags": [ "LOCAL_PICKUP" ], "url": "https://offerup.com/item/detail/8840afca-7efc-329c-b3ce-f716548fb181", "rating": null, "review_count": null, "rating_scale": null, "position": 2 }, { "listing_id": "4a9cae74-d161-3806-b101-4e53743759b2", "title": "Love seat and sofa", "price": 0, "price_display": "$0", "currency": "USD", "call_for_price": false, "is_firm_price": null, "condition": null, "location": { "name": "Garden Grove, CA", "latitude": null, "longitude": null }, "image": { "url": "https://images.offerup.com/vCksVrKDX6E8l0y5YVHBU7fqZzc=/333x250/56ba/56ba6abcf1054e569fda47d47b3f4381.jpg", "width": 333, "height": 250 }, "vehicle_miles": null, "flags": [ "LOCAL_PICKUP" ], "url": "https://offerup.com/item/detail/4a9cae74-d161-3806-b101-4e53743759b2", "rating": null, "review_count": null, "rating_scale": null, "position": 3 } ], "count": 44, "next_cursor": "H4sIAAAAAAAAAI1W244ctxH9lWCeVQCvRXLfjFViCJAtIXYeDEtYFFnF1cDrncn0TGzF2H_34WidGIZh6GV3uru6yHMr9i-7zeQ0Pnxj27Y_PL7S3c1uw3UctbWpUpPkxL3V0Jlzc7jDoRfbvXh-8R9mens5bYcT3vzl3e4w52bnd7ublJ5QNPH4m7Oczrub7F7sjif7z_5w2d7Kvb3eb-f94_0r3XY33-9KrhKq65SSMsUUJzV2iVwac2bOGkJHv1qTkzmEis1BMbRBPQ6jWTznVGf31aMsSRtiJZF69hSrY-reeUqWY0mx5NYDyoqvObBH2WiTYtZJ3ThTSWEGdRxj51WWrWvxk4afKHONSUIu1NSHObyYhIQy1s6epVOMMeMPWtaujiQXLpVdbroWzcZDXSskrEqxi1CdI1Ewb9lKaVHiWlRqt-IL8NWwCIkkRRJVrdkpNpZHRZmbro4xInF06JZcRreZyOOmzdTzczfWUUeuFGbFBqtV6qOgNllV6UlUHcpU0Z2LEoN2itMCgXFPRSMXq6Ghz-pWUwkhCHUXCwgJlWRqIINtopbusiyxUgJLngepywsCZBORSXkyD25s3S1CzCzOooNCcJGiVA8IwjRGdxIG5OWlqTiwnaKjOjo0jZCiDs-Uy5hjqvbm2lIB_KVQPEHARLHBSFIGcESVyV00xLU3czpj4kkak1H0tUHTUJb-RS0F7HMuCBzbgL4kCX_iYKU2ADcWk-YZm-iLt5GdM00CkLb8pkYt1LIsVSzMPlK50ltD7d6wqEz_yW9NB5CGUnOKLelY9Ga16S02ApsOJvdKvaVAzo2QZmxhWkZZTOrijIF0VkDgoAukEXsFA0t9WbwF0-Z8auQFTo_ZGfUE8oqpCpoj4vG6aKtceqfWO6QvvsF5XLFVS8PVHKsvSwVw4L3p6gEjTR-xaHHEuboxo3mka-2tShq5JWo5Is6SkVObWFnUVQa_7Sq9b4krT1TMtCLTkQXOnZD2ab5NrLqQAo93MXuyYXAI97SShZbSpwQ_CibHEiswQHSkUzyk6CFSaxWGYXUCgjFJlqYRMcK6StN6WfQiBhZgP3F5pJnYzauR8NNNVFjwoHfp3zsGic9ADT2k1LEmkuU2Q4RnO2hAZADSY_L4DNvlEUHfImRiPAWEBtuqQOoR7Kpg0FobLtXmnS5bDu9dnR45lQxWGhSrFgEGLsRsqSBrQSiqGYKBi87QdHKAbOvXwNzmGJIFWSbPsXFF7EwM05KxqOQm5AyTDEqkrtcy4TYX7XNEaOoYZaFjDGLYjuKKclkqNEwtRn6or3jFWdds8kjWSN1CaUHzddTALTw7KBsLLjfQ6wDBAiTLLrt-dQjjMZfmSXpeQSlM8LhgVghG9NBSdWVhymyjiNJIABndqFQLuqmUmRNszbbKYIIowWEidYQqptmoIS7EmDS5NTeirUmOrSZe801yXuQJzNHZkQulN5w_M8iyJfAMJLLgMHLQ1BiWgssJI1dgTNWZ5-49wqDb3WYPD3b6Qrffn4KP9vP57ohD7m5c7-I8fLfzb1G1Tr7b53sv3l0PxM8r_EPNGFzDgHVxPjdKHgHDOZAB2AVz4BCT6PriX_VdJ_TCgN3a6VEePgfFl4fD_YO93G_HB_mIF56_HK5rid492vmnw-mH5zc2vIJG939459Pdz286DpfH9U3hcbl_VPvZVovv3funJ9y5Px0ux7vjaX847c8fP_WOR_xv7ek3hOPwuF1-NP3775Cupqvn7t8XO328lbPdo8N_5YyV0WR3_ng0EPH2n29e_uv227s3X7_-bn32HG3s535gKTy8ffPVV29evvr2-uTSV6e9XT9osOfx4W_jsn1Y7V48Xx_3Dw-Hn7b_XeNb6f-_D1N275_-dD-vD4cfLscvzmf78XiG42_Op4s9_Qq9w3g7vgkAAA", "total_results": null, "location": { "latitude": 34.0522, "longitude": -118.2437, "zip_code": null, "city": null, "state": null, "source": "coordinates", "radius_miles": 30 }, "query": "couch", "category": null, "sort": "best_match", "ad_tiles_dropped": 6, "duplicate_rows_dropped": 0 } }
How the OfferUp API works
OfferUp is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 192 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Search one metro, then read the listings that matter in full
The only thing that scopes an OfferUp search is the location you send with it. Get that right and the rest is two flat calls: the feed, then the record.
{"query": "couch", "zip_code": "98101", "radius": 30}One flat credit, about 44 rows at 24 KB. The response reports the coordinates it actually resolved and where they came from, so you can see the scope took. Take results[].listing_id.
{"query": "couch", "zip_code": "98101", "cursor": "…"}Pass the next_cursor from the previous response back as cursor. Measured over 4 pages: 184 rows, 184 distinct ids, zero overlap. The cursor belongs to the query that made it, so changing a filter starts a fresh walk.
{"listing_id": "…"}One flat credit, 3 KB. The description, the condition, the full gallery, the pickup terms and the seller's public sold count, join date and badges — plus the real price on the dealer rows where the tile hides it.
Three flat credits for a scoped local feed, its second page and a listing in full — and both actions are one upstream request each, so a sweep costs what you can count in advance.
curl -X POST https://api.reefapi.com/offerup/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"couch","latitude":34.0522,"longitude":-118.2437}'{
"ok": true,
"data": { … },
"meta": {
"api": "offerup",
"endpoint": "search",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}What scopes a search is the coordinates you send - not your IP, and not a URL parameter
This is the single most important thing to know before you build against OfferUp, and it is the thing most callers get wrong first. OfferUp assigns EVERY exit the geographic centre of the United States as a fallback location, so an un-scoped search returns Kansas no matter where the call comes from. All five rows below were measured from ONE exit inside ONE minute on 2026-09-06 - the only thing that changed was the location sent with the query.
| Location sent with the query | Towns that came back |
|---|---|
| nothing | Wichita KS, Pretty Praire KS - OfferUp's default US centre, not your location |
| 40.7484 / -73.9857 (New York) | Parlin NJ, Edison NJ, Union Beach NJ, Matawan NJ, New York NY |
| 34.0522 / -118.2437 (Los Angeles) | South Gate CA, Rosemead CA, South Pasadena CA, Garden Grove CA |
| 25.7617 / -80.1918 (Miami) | Miami FL, Ind Crk Vlg FL, Fort Lauderdale FL |
| 47.6062 / -122.3321 (Seattle) | Burien WA, Everett WA, Lynnwood WA, Fall City WA |
A ZIP code works too and is resolved by OfferUp's own geocoder rather than by a table of ours, at the cost of one extra request - a live call on 98101 came back scoped to 47.6067 / -122.3354, Seattle WA, with 16 of 44 rows in Seattle itself. The response always reports which of the three happened, so you are never guessing whether your location took: the location block names the coordinates actually used and a source of zip_code, coordinates, or offerup_default_us_centre. Free-text place names are deliberately NOT offered, because OfferUp's geocoder refuses that arm without a bias position - it would have been a parameter that silently did nothing.
Which country, what scopes a search, which cursor pages, and what OfferUp does not publish
offerup.com only — one country, one currency, and a location that travels in the request rather than in your proxy. Measured on 2026-09-06 across 128 live engine calls in three runs with 0 unexpected failures, 704 search rows counted by value, 24 detail records and a 1,409-row regression. Four of these lines go against us.
OfferUp is a US marketplace and there is no country parameter because there is no other market. A request from outside the US is answered with a 403 page titled "Geolocation Unavailable", identically from every kind of exit — that is a country gate on the marketplace, not anti-bot behaviour, and the engine types it as MARKET_UNAVAILABLE so you know there is nothing to retry and no setting that opens it. Everything else about the surface is unusually open: OfferUp's own robots.txt names the data endpoint as allowed, and a call needs no cookie, no token, no account, no login and no browser.
OfferUp assigns EVERY exit the geographic centre of the United States as a fallback location, so an un-scoped search returns Pretty Prairie and Wichita, Kansas — no matter where the call comes from. The lat and lon parameters on OfferUp's own search URL are ignored too. What works is the location sent with the query, and it was verified from one exit inside one minute: New York coordinates returned Parlin, Edison, Union Beach, Matawan and New York; Los Angeles returned South Gate, Rosemead, South Pasadena and Garden Grove; Miami returned Miami, Ind Crk Vlg and Fort Lauderdale; Seattle returned Burien, Everett, Lynnwood and Fall City. This is the practical upside as well as the trap: you sweep several metros from ONE exit, without buying an IP in each of them.
Pass a ZIP and OfferUp's own geocoder turns it into coordinates at the cost of one extra request — a live call on 98101 came back scoped to 47.6067 / -122.3354, Seattle WA, with 16 of 44 rows in Seattle itself. The response always names the coordinates actually used and reports a source of zip_code, coordinates, or offerup_default_us_centre, so a mis-scoped search shows up in the payload rather than in the towns three days later. Free-text place names are deliberately not offered: OfferUp's geocoder refuses that arm without a bias position, so it would have been a parameter that silently did nothing.
Pass the next_cursor from one response back as the cursor on the next call: 4 pages of one query gave 44 + 44 + 49 + 47 = 184 rows and 184 DISTINCT listing ids, with zero overlap against everything already seen. There is no page NUMBER — this feed is cursor-paged only — and no result total, so total_results is null rather than a guess. Two things not to assume: the page size is OfferUp's rather than yours, which is why a rows-per-call parameter is not offered at all (5, 10, 20, 50 and 100 all returned the same roughly 50-tile page upstream, so it would have been a parameter that does nothing), and the cursor belongs to the query that produced it, so changing a filter starts a fresh walk.
search is one upstream request at 23.7 to 24.7 KB, median 24.2 KB, with a median 875 ms; add a ZIP and it is two requests and about 1.7 seconds because of the geocode. product/detail is one request at 2.2 to 3.8 KB, median 3.0 KB, median 685 ms. Across 128 live engine calls in three runs there were 0 unexpected failures, p90 between 820 and 985 ms depending on the run, and 9 deliberate negative cases all returned the right error code. Both actions are flat-rated at one credit. The HTML page carries the same rows at 315 KB — thirteen times the bytes — and is deliberately not what this engine reads.
Fourteen listings were fetched twice, once through the engine and once as the page, and compared against the page's own structured-data price: 14 match, 0 mismatch, and no listing where the page carried no price. The set deliberately included a genuine 0.00 listing, kept as 0 rather than treated as missing, because a free item is a real thing on a classifieds site. Across 1,501 search rows, 24 detail payloads and a 1,409-row regression, the scan for raw HTML tags and HTML entities in any string found zero of each.
A dealer can ask OfferUp to hide the price on the feed tile, and OfferUp then sends an empty string rather than a number. Rather than shrug at the gap: the rows with no price are exactly the rows flagged CALL_FOR_PRICE — 7 of 1,062 in one run and 10 of 1,409 in the regression, and in BOTH runs the count of missing prices equalled the flag count exactly, so there are zero unexplained nulls. Every one was an auto-dealer vehicle. Those rows return price null with call_for_price true, never a misleading 0, and product/detail on the same ids returns the real numbers — 12,790, 22,290, 17,999 and 25,477 among them. OfferUp hides the figure on the tile, not on the listing.
OfferUp's schema has a reviews object on a user profile and it measured null on 12 of 12 profiles — including a furniture seller with 10,769 items sold, and one whose own display name is "5 Star Seller". So the seller rating, the review count and the rating scale are all null rather than an invented number, and nothing on the surface states a rating maximum either. What OfferUp does publish is returned instead, and it is arguably the better reputation signal: items sold, items purchased, the join date, the stated response time, and the badge strip — "95% reply rate", "Confirmed phone", "Confirmed email" — as LABELS only, never as contact details.
A feed tile has no owner field at all, so the seller is null on a search row and is filled by product/detail. The condition and the is-the-price-firm flag behave the same way: both measured 0 of 704 on search rows and both filled 24 of 24 on detail — the tile fields exist and OfferUp does not fill them, which is a source gap rather than a parse fault. And there is no result total anywhere on the feed, so total_results is null rather than a guess; the cursor is how you find out how much there is.
OfferUp's own filter drawer names condition values, and three separate spellings of the parameter were tried against them. Not one changed a single row over 44, so condition is not published as a search filter at all — a parameter that is accepted and ignored is worse than no parameter. The filters that ARE offered were each proved to bite: a 100-to-200 price band returned 44 of 44 rows inside it; radius 5 kept 41 of 44 rows in Los Angeles itself across 4 towns while radius 50 spread over 30 towns; the descending price sort led with 1,000,000 and 999,999 where ascending led with five zero-priced rows; and each category id was verified by fetching the returned listing's own category back from product/detail. One interaction is documented on the parameter rather than hidden: a category plus a keyword lets the category win where the keyword has no local supply, so a phone keyword inside the vehicles category returns cars.
Public listings only, logged out, with no account and no captcha anywhere in the path. What comes back about a seller is what the public listing page shows anyone: their public display name, their public town, their join date, their sold and bought counts and their badge labels. The phone-number fields that exist on OfferUp's schema are never requested by this engine, so they cannot appear in a response even if OfferUp starts filling them.
What people build with OfferUp
The jobs this data is most often used for.
endpoints
credit per call
Local-market pricing tools scope a search to a metro with coordinates or a ZIP and read the whole 44-row feed at 24 KB a call.
Resale and arbitrage teams sweep a category across several US metros from one exit, since the location travels in the request rather than in the proxy.
Auto-listing aggregators pull dealer inventory from the vehicles categories and call product/detail for the mileage, transmission, title status and the real price on the rows where the tile hides it.
Marketplace research teams walk a query with the cursor - 184 distinct listings over 4 pages with zero overlap - and enrich each id with the seller's public sold count, join date and badges.
What OfferUp data costs
The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 192 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
curl -X POST https://api.reefapi.com/offerup/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"couch","latitude":34.0522,"longitude":-118.2437}'import requests
r = requests.post(
"https://api.reefapi.com/offerup/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "couch",
"latitude": 34.0522,
"longitude": -118.2437
},
)
print(r.json()["data"])Have a question? We got answers.
The questions people actually ask before wiring up OfferUp.
Get a free key →Why is my search returning results from Kansas?▾
Because you did not send a location, and OfferUp's fallback is the geographic centre of the United States - Pretty Prairie, Kansas. It applies that fallback to every exit, so the IP the call comes from does not scope anything, and neither do the lat and lon parameters on OfferUp's own search URL, which are ignored. Send zip_code, or latitude and longitude, on the search action. The response tells you which it used and what coordinates it resolved to, so a mis-scoped search is visible in the payload rather than something you discover from the towns three days later.
Does pagination actually return new listings?▾
Yes, and it was checked by comparing id sets rather than by trusting the cursor. Pass the next_cursor from one response back as the cursor on the next call: 4 pages of one query returned 44 + 44 + 49 + 47 = 184 rows and 184 DISTINCT listing ids, with zero overlap against everything already seen. There is no page NUMBER - OfferUp pages this feed by cursor only - and there is no result total either, so total_results is null rather than a guess. Two things not to assume: the page size is OfferUp's, not yours (a rows-per-call parameter is not offered because it does nothing upstream - 5, 10, 20, 50 and 100 all returned the same roughly 50-tile page), so read count; and the cursor belongs to the query that produced it, so change a filter and start a fresh walk.
Can I get a seller's rating or reviews?▾
No, and this one is worth stating plainly because it is the field people expect. OfferUp's schema has a reviews object on a user profile and it measured null on 12 of 12 profiles, including one furniture seller with 10,769 items sold and another whose own display name is "5 Star Seller". So the seller rating, the review count and the rating scale are all null rather than a fabricated number. What OfferUp does publish comes back instead, and it is a better reputation signal than an absent rating: items sold, items purchased, the join date, the stated response time, and the verification badge strip - "95% reply rate", "Confirmed phone", "Confirmed email" - as labels only, never as contact details.
Why do some vehicle listings have no price?▾
Because a dealer asked OfferUp to hide it on the tile, and OfferUp sends an empty string rather than a number. That was chased to the mechanism rather than shrugged off: the rows with no price are exactly the rows whose flags contain CALL_FOR_PRICE - 7 of 1,062 rows in one run and 10 of 1,409 in the regression, and in BOTH runs the count of missing prices equalled the flag count exactly, so there are zero unexplained nulls. Every one was an auto-dealer vehicle. Those rows come back with the price as null and call_for_price set to true, never as a misleading 0, and product/detail on the SAME listing ids returns the real numbers - 12,790, 22,290, 17,999 and 25,477 among them. OfferUp hides the figure on the tile, not on the listing.
Is the price the same number the page shows?▾
It was checked directly rather than assumed. Fourteen listings were fetched twice - once through the API and once as the listing page - and compared against the page's own structured-data price: 14 match, 0 mismatch, and no listing where the page had no price at all. The set deliberately included a genuine 0.00 listing, which is returned as 0 rather than being treated as missing, because a free item is a real thing on a classifieds site. Across 1,501 search rows, 24 detail payloads and a 1,409-row regression, the scan for raw HTML tags and HTML entities in any string found zero of each.
Which filters actually work?▾
The ones that were measured to change the result set, and only those. Price bounds bite exactly - a 100 to 200 band returned 44 of 44 rows inside it. Radius bites: at 5 miles a Los Angeles search kept 41 of 44 rows in Los Angeles across 4 towns, at 50 miles it spread over 30 towns. Sorting bites hard - a descending price sort led with 1,000,000 and 999,999 while ascending led with five zero-priced listings, and the distance and newest orderings shared 0 and 15 rows respectively with the default. Category ids bite, verified by fetching each returned listing's own category back from product/detail. Three condition parameter spellings were tried against OfferUp's own filter drawer and not one changed a single row over 44, so condition is NOT offered as a search filter - it is on product/detail instead. One interaction is worth knowing: a category plus a keyword lets the category win where the keyword has no local supply, so a phone keyword inside the vehicles category returns cars.
Does it work outside the United States?▾
No, and the failure is typed as a market limit rather than dressed up as a block. OfferUp is a US marketplace and answers a non-US request with a 403 page titled "Geolocation Unavailable", identically from every kind of exit, so it is a country gate rather than anti-bot behaviour. The engine returns MARKET_UNAVAILABLE for that, which tells you the truth: there is nothing to retry and no configuration that opens it. Everything else about the surface is unusually open - OfferUp's robots.txt names the data endpoint as allowed, and the call needs no cookie, no token, no account and no browser.
What does OfferUp NOT publish?▾
No seller rating, review count or rating scale anywhere. No total result count - the feed is cursor-paged and publishes no total, so total_results is null rather than an estimate. No seller at all on a search ROW: the feed tile has no owner field, so the seller comes back null there and is filled by product/detail. No condition and no is-the-price-firm flag on a search row either - both measured absent on 704 rows and both filled 24 of 24 on detail. And no per-listing rating or review count, because OfferUp has no product reviews: every listing is one second-hand object. The tile flag vocabulary observed over 1,062 rows was just two values, and one of them appeared on all 1,062 rows, so it is passed through verbatim rather than re-published as a boolean that would tell you nothing.
What is the OfferUp API?▾
OfferUp API is a ReefAPI endpoint group for us local classifieds: listings, prices and seller profiles near any zip. It returns live JSON through POST requests under /offerup/v1.
Is the OfferUp API free to try?▾
Yes. ReefAPI starts with 1,000 free credits, no card required. OfferUp calls use the same shared credit balance as every other ReefAPI engine.
Do I need an OfferUp login or account?▾
No login to OfferUp 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 OfferUp 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 OfferUp API use?▾
OfferUp actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call OfferUp from an AI assistant or MCP client?▾
Yes. Connect ReefAPI once through MCP and your assistant can call offerup actions with the same key, credit pool and JSON envelope used by normal REST requests.
43 E-commerce & Marketplaces APIs on the same key
One key, one credit pool, one response envelope. If you are pulling OfferUp, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 191 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-09-06.