Public Surplus API

Government and school surplus auctions, with the agency, the bids and the real end time

Public Surplus is where US and Canadian cities, counties, school districts, universities, transit agencies and utilities auction what they no longer need: pickups and buses, forklifts and loaders, laptops and monitors, lab and medical instruments, desks and chairs, scrap, even land.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a Public Surplus endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
P
/publicsurplus/v1

4 active endpoints. Every call is 2 credits.

  • POST/publicsurplus/v1/search
  • POST/publicsurplus/v1/detail
  • POST/publicsurplus/v1/seller_listings
  • POST/publicsurplus/v1/categories

What Public Surplus endpoints does ReefAPI ship?

4 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

4 endpoints

search

2 cr

Search LIVE Public Surplus auctions.

required
—
optional
query, category_id, state, zip, radius_miles, min_price, max_price, closing_within_hours, listed_within_hours, sort, page

detail

2 cr

Everything Public Surplus publishes about one live auction.

required
auction_id
optional
—

seller_listings

2 cr

Every live auction one selling agency currently has open, 50 per page.

required
seller_id
optional
page

categories

2 cr

The Public Surplus category tree with the live lot count on every sub-category, as the site's…

required
—
optional
flat

Every parameter, every allowed value →

Public Surplus API

4 of 4 endpoints, ready to run

View docs ↗

Live auctions, closing first

2 credits0 required · 4 optional
POST/publicsurplus/v1/search
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the Public Surplus API works

Public Surplus is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 438 engines.

02
Call
POST /publicsurplus/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
2 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Catch a school-district pickup before it closes

Find what closes today near you, check whether anyone has bid, then watch the agency.

01search?category_id=4&zip=85718&radius_miles=200&closing_within_hours=24
POSTsearch?category_id=4&zip=85718&radius_miles=200&closing_within_hours=24

Motor Pool lots within 200 miles that close in the next 24 hours; ends_at is already UTC.

02detail?auction_id=4098212
POSTdetail?auction_id=4098212

Bid count, whether the price is still the opening price, minimum next bid, pick-up address, buyer's premium and the agency's terms.

03seller_listings?seller_id=20876
POSTseller_listings?seller_id=20876

Everything else that agency has open right now.

A shortlist of nearby lots with the exact second each one closes, how contested it is, and what the agency will charge on top.

request
curl -X POST https://api.reefapi.com/publicsurplus/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"truck","sort":"ending_soonest"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "publicsurplus",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

What one search row carries

Measured on 250 rows: 25 per category across ten categories (Motor Pool, Computers, Heavy Equipment, Furniture, Medical, Industrial Equipment, Electronics, Outdoor Equipment, Office Equipment, Marine).

FieldFillWhat it is
item_id / auction_id250/250The auction number detail takes. Same id, same type, on every round trip.
title250/250The lot title as the agency wrote it.
current_bid + price_display250/250The price as a number and the source's own string. The number matched the printed string on 250 of 250 rows.
ends_at250/250ISO-8601 UTC, read from the page's own countdown, not from the Mountain-time label.
seconds_remaining + source_time_left250/250Seconds left by Public Surplus's own clock, and its own human countdown string beside it.
state250/250Two-letter state or province of the selling agency. It matched the pick-up address state on every round trip where the address had one.
image_url250/250The lead photo.
title_matches_queryevery row when query is givenWhether every query word is in the title. The source also matches the description, so this tells the two apart.

The search page does not name the selling agency or the bid count, and it does not say whether the price is a standing bid or still the opening price. detail returns all three. Closed auctions are not public on Public Surplus — they ask for a login — so this API covers live auctions only.

Measured coverage

Live cohorts on 2026-10-07; the call counts per cohort are in the engine's build log.

Live auctions

About 6,650: a full browse reported 6,655 and the category tree's own counts summed to 6,646 on the same day.

Categories

28 top-level and 211 sub-categories, each with its live count. Computers 1,240, Electronics 709, Office Equipment 698, Industrial Equipment 682, Furniture 664, Motor Pool 544.

Geography

68 US state, territory and Canadian province codes accepted. Truck lots in Texas 10 and California 24 when measured; desks in Texas 88.

Page shape

25 rows per search page and 50 per agency page, fixed by the source. 245 truck lots gave 20 rows on page 10 and an empty page beyond it, reported as page_beyond_last.

Values checked

16 search-to-detail round trips: same id, same title, same end second and the same price on 16 of 16. The parsed price matched the source's printed string on 250 of 250 search rows.

Timestamps

ISO-8601 UTC from the page's own countdown. The printed label is Mountain time for every agency; the label plus six hours equalled ends_at on 16 of 16 lots.

Not published

No agency name or bid count on search rows (detail has both). No closed auctions, final prices, bid history, Q&A or agency contact person: Public Surplus puts all of them behind a login.

What people build with Public Surplus

The jobs this data is most often used for.

4

endpoints

2

credits per call

01

Fleet and equipment buyers watching school-district and county surplus by state, distance and closing window.

02

Refurbishers sourcing laptops, monitors and networking gear in bulk from universities and agencies.

03

Bid-timing and alert tools that need a real UTC end time instead of a Mountain-time label.

04

Lab and medical equipment resellers tracking instruments released by hospitals and research universities.

What Public Surplus data costs

The cheapest call here is 2 credits, so $15/mo (Pro) buys 5,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 →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 438 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
curl -X POST https://api.reefapi.com/publicsurplus/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"truck","sort":"ending_soonest"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/publicsurplus/v1/search",
    headers={"x-api-key": REEF_KEY},
    json={
  "query": "truck",
  "sort": "ending_soonest"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Public Surplus.

Get a free key →
What timezone are the end times in?▾

Public Surplus prints every end time with a Mountain-time label (MDT when measured), whatever state the agency is in — a Connecticut hospital, a Texas county and an Arizona school district all said MDT. ends_at is therefore built from the exact instant inside the page's own countdown and returned as UTC, and ends_at_local, ends_at_zone_label and ends_at_offset_hours ship beside it. On every lot checked, the printed time plus six hours equalled ends_at to the minute.

How do I know if anyone has bid?▾

Call detail. A lot nobody has bid on shows an opening price, an empty bid count and no high bidder; detail returns price_basis opening_price and bid_count 0 for it, and price_basis current_bid with the real count otherwise. The source's own arithmetic checks out: the minimum next bid equalled current price plus increment on every bid-on lot and equalled the opening price on every unbid lot, 16 of 16 round trips.

Why does a keyword search return items without that word in the title?▾

Public Surplus matches the description too, including the agency's standard terms. Searching forklift returned 663 lots, but only 4 of the first 25 titles mentioned a forklift — the rest were lots whose terms mention loading by forklift. Each row carries title_matches_query, so you can keep title hits without a second call.

Which filters work?▾

Keyword, category or sub-category, state or province, ZIP plus radius, minimum and maximum price, closing within 1, 6, 24, 120 or 240 hours, and listed within 1, 24, 48 or 168 hours. Each was measured against two control searches in the same run. On 245 truck lots: Texas 10, California 24, Motor Pool 47, at least $1,000 89, at most $100 84, within 200 miles of 85718 13, closing within 24 hours 25. Price, state and closing-window filters were also checked row by row and no row broke them.

How deep can I page?▾

25 rows per page, fixed by the source. Paging is honest to the end: 245 truck lots gave 20 rows on page 10 and nothing past it, and last_page, has_more and page_beyond_last tell an overrun apart from a search that found nothing.

Can I follow one agency?▾

Yes. detail returns seller.seller_id, and seller_listings returns every live lot that agency has open, 50 per page. Harris County Purchasing had 12 pages when measured, the City of Roanoke 17 lots on one page.

What is not available?▾

Closed auctions and their final prices, the bid history, the question-and-answer thread and the agency contact person all require a Public Surplus login, so none of them is here. Everything this API returns is what a visitor sees without signing in.

What do the categories look like?▾

28 top-level categories and 211 sub-categories with live counts. Largest when measured: Computers 1,240, Electronics 709, Office Equipment 698, Industrial Equipment 682, Furniture 664, Motor Pool 544. Any id works as search's category_id, top-level or sub-category.

What is the Public Surplus API?▾

Public Surplus API is a ReefAPI endpoint group for city, county, school and university surplus auctions with the agency, the bid count and the end time in real utc. It returns live JSON through POST requests under /publicsurplus/v1.

Is the Public Surplus API free to try?▾

Yes. ReefAPI starts with 1,000 free credits, no card required. Public Surplus calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Public Surplus login or account?▾

No login to Public Surplus 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 Public Surplus 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 Public Surplus API use?▾

Public Surplus actions currently cost 2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.

Can I call Public Surplus from an AI assistant or MCP client?▾

Yes. Connect ReefAPI once through MCP and your assistant can call publicsurplus actions with the same key, credit pool and JSON envelope used by normal REST requests.

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.

0/4000

No account needed · we reply from [email protected]

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 437 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-10-07.