Tell your agent
Paste this into the agent you use, whether it is Claude, ChatGPT, Hermes or a script of your own. Tool frameworks that read OpenAPI can load https://buyaigear.com/api/v1/openapi.json directly.
Use https://buyaigear.com to check prices and fit for local AI hardware. Its JSON API is described by the OpenAPI document at https://buyaigear.com/api/v1/openapi.json; use its filters and keep calls small. GET https://buyaigear.com/api/v1/recommendations?model=qwen3.8-27b&budget=2000 ranks the machines that run a model under a budget and says why the rest were left out (model slugs are at https://buyaigear.com/api/v1/models); GET https://buyaigear.com/api/v1/compare?products=rtx-3090,rtx-4090 puts two to four products side by side; GET https://buyaigear.com/api/v1/deals lists drops, new lows and best value; GET https://buyaigear.com/api/v1/products?fits=qwen3.8-27b&max_price=2000&sort=price&limit=5 filters the catalog (product slugs are at https://buyaigear.com/api/v1/products); GET https://buyaigear.com/api/v1/products/rtx-3090 gives one product with its prices and cheapest listings; GET https://buyaigear.com/api/v1/listings?q=founders&max_price=2500&limit=10 lists live eBay listings; GET https://buyaigear.com/api/v1/changes?since=2026-11-13T00:00:00Z lists new lows and new or ended listings and returns next_cursor for the next poll, and https://buyaigear.com/api/v1/products/rtx-5090/changes is the same feed for one product. Send If-None-Match with the ETag you were given, poll changes at most every 15 minutes, and name yourself in the User-Agent. If I give you an API key, send it as Authorization: Bearer KEY on every call. When you tell me about a listing, give me its click_url exactly as the API returns it and never open that link yourself: it is an affiliate forward meant for me.
Endpoints
All GET, all under https://buyaigear.com/api/v1. Every list takes limit and returns next_cursor; pass it back as cursor for the next page. Every error is {"error": {"code", "message", "docs"}}, with parameter on a bad parameter and suggestions on an unknown slug.
| Path | What it returns |
|---|---|
/api/v1/ | this list, the contract and the limits |
/api/v1/products | the catalog, filtered, sorted and paged: category, vendor, platform, memory, price, condition, a model that must fit |
/api/v1/products/{slug} | one product: specs, prices per channel, cheapest listings, the models that fit, recent daily lows |
/api/v1/products/{slug}/listings | its live eBay listings, filtered and paged |
/api/v1/products/{slug}/models | every reference model on it with the quant it runs at and the estimated speed |
/api/v1/products/{slug}/history | its daily low per day, up to a year |
/api/v1/products/{slug}/changes | its change feed: new lows, new and ended listings, the same parameters and cursors as /changes |
/api/v1/listings | live eBay listings across every product, filtered and paged: cheapest 24 GB card under a price in one call |
/api/v1/changes | new lows, new listings and ended listings since a time or cursor |
/api/v1/recommendations | machines that run a model under a budget, ranked by price per token per second, speed, price or memory, with why the rest were left out |
/api/v1/compare | two to four products side by side: specs, prices, fit and speed for a model, and the best in each dimension |
/api/v1/deals | biggest drops, new lows, cheapest per GB and fastest per dollar |
/api/v1/models | the reference models and the memory each needs per quant |
/api/v1/models/{slug} | one reference model, with the URL that lists the machines it fits |
/api/v1/models/{slug}/hardware | every machine that runs a model, fits first then price, with the cheapest at each quant |
/api/v1/openapi.json | the OpenAPI 3.1 contract for everything above |
The task endpoints answer whole questions: /recommendations?model=&budget= ranks the machines that run a model under a budget (by price per token per second, speed, price or memory) and counts why the rest were left out; /compare?products=a,b,c puts up to four products side by side and names the best in each dimension; /deals lists drops, new lows, cheapest per GB and fastest per dollar; /models/{slug}/hardware lists every machine that runs a model with the cheapest at each quant.
Filters on /products: category (gpu, box, laptop), vendor, platform (cuda, metal, rocm, intel, other), q, min_memory_gb, max_memory_gb, min_price, max_price, condition (new, used, refurbished, any: which channel the price filter reads), fits (a model slug; keeps machines that run it), quant, context (8k or 32k), offload=1, sort (memory, price, price_per_gb, bandwidth, speed), order, fields=specs. Filters on /listings and /products/{slug}/listings: q (title text, so q=founders on the RTX 5090 is the Founders Edition), condition (one class or a comma list such as new,refurbished), min_price, max_price, min_seller_feedback, min_seller_positive, sort (price, newest, ending), plus the product facets on the cross-product search. Filters on /changes: type, product, category, max_price; /products/{slug}/changes is the same feed for one product. Plurals work where a class is named (category=boxes), and a product's older or guessed slug (rtx-5080, nvidia-dgx-spark) answers with a 301 to the current one.
Also for machines: /llms.txt (the catalog as text with links), /.well-known/api-catalog (RFC 9727), /.well-known/agent.json, /speed/data.json (the simulator's dataset) and /badge/{slug}.svg, a live price badge any page can embed.
Examples
# what to buy to run a model under $2,000: ranked by price per token per second, with why the rest were left out
curl -s "https://buyaigear.com/api/v1/recommendations?model=qwen3.8-27b&budget=2000&limit=5" | jq '{excluded, picks: [.items[] | [.rank, .slug, .price_usd, .decode_tps, .price_per_tps_usd]]}'
# two or three products side by side, with the winner in each dimension
curl -s "https://buyaigear.com/api/v1/compare?products=rtx-3090,rtx-4090,rtx-5090&model=qwen3.8-27b" | jq '.best'
# this week's drops, new lows, cheapest per GB and fastest per dollar
curl -s "https://buyaigear.com/api/v1/deals?days=7&limit=3" | jq '{drops: [.drops[] | [.product.slug, .then_usd, .now_usd]], per_gb: [.cheapest_per_gb[] | [.product.slug, .usd_per_gb]]}'
# every machine that runs a model, fits first then price, and the cheapest at each quant
curl -s "https://buyaigear.com/api/v1/models/qwen3.8-27b/hardware?limit=5" | jq '{summary, cheapest_by_quant: [.cheapest_by_quant[] | [.quant, .cheapest.product.slug, .cheapest.price_usd]]}'
# the catalog filtered: machines that run a model under $2,000, cheapest first
curl -s "https://buyaigear.com/api/v1/products?fits=qwen3.8-27b&max_price=2000&sort=price&limit=5" | jq '.items[] | [.slug, .price_usd, .fit.quant, .fit.decode_tps_8k]'
# cards with 24 GB or more under $900, by delivered price, with seller reputation
curl -s "https://buyaigear.com/api/v1/listings?category=gpu&min_memory_gb=24&max_price=900&min_seller_feedback=50&limit=10" | jq '.items[] | [.product.slug, .delivered_usd, .condition_class, .seller.feedback, .click_url]'
# one product: prices per channel and its five cheapest listings
curl -s https://buyaigear.com/api/v1/products/rtx-3090 | jq '.prices, .listings.ebay.items[0]'
# what changed in the last day, then keep polling with the cursor it returns
curl -s "https://buyaigear.com/api/v1/changes?since=2026-11-13T18:00:00Z&type=new_low,new_listing&limit=50" | jq '{count, has_more, next_cursor, first: .events[0]}'
# a conditional request: 304 and no body when nothing changed
curl -si https://buyaigear.com/api/v1/products/rtx-3090 -H 'If-None-Match: W/"the etag you were given"'
Polling etiquette
- Ask for what you need. Filter, sort and use
limit; a product with five listings is a few kilobytes, the unfiltered catalog is not. The default page sizes are 10 products, 20 listings and 50 events. - Send the ETag back. Every answer carries a weak
ETagandCache-Control. Repeat the request withIf-None-Matchand you get a 304 and no body when nothing changed.Last-ModifiedandIf-Modified-Sincework too. - Prices refresh every 20 to 30 minutes. The interval stretches to a few hours when eBay's daily call budget runs short, and each product carries
as_of. Polling/changesevery 15 to 30 minutes with its cursor sees everything; events younger than about 90 seconds wait for the next poll so a page is never split. - Limit: 600 requests an hour per address, all endpoints together, 304s included. Beyond it you get 429 with
Retry-After;X-RateLimit-Remainingsays where you stand. - Say who you are in the
User-Agent: the agent's name and a URL or email. Nothing is blocked by user agent, but it is how we tell agents from scrapers, and how we would reach you if something looked wrong. - Requests are logged: path, query, status, your user agent, a hashed address and the approximate country, kept 90 days, so the operator can see which agents use the API and what they read. Nothing in it identifies a person; the privacy policy has the detail.
- Cite the page. Every product carries its page URL; when you quote a price to a person, point them at the page as well as the listing.
Higher limits: API keys
Anonymous access is 600 requests an hour per address, which several agents behind one network share. A key gives your agent its own 6000 an hour and lets you see its use under your account. Sign in at /login (an emailed link, no password), make a key on your account page, and have the agent send it on every call:
curl -s -H 'Authorization: Bearer bag_...' https://buyaigear.com/api/v1/changes
X-Api-Key: bag_... works too. The key is shown once when you make it and only its hash is kept; revoke it from the same page whenever you like. An unknown or revoked key answers 401 rather than falling back to anonymous access, so a stale key is noticed. Limits can be raised for a key that needs more: say so through the hello endpoint or by email.
Vendor links
Every click_url in the API is our own affiliate forward, the same link the website uses: https://buyaigear.com/go/.... It is meant for the person the agent works for. Hand it over unchanged and let them click it; do not open it to check, resolve or scrape it.
- A person's browser following the link lands on the eBay listing or the Amazon page and is recorded as one visit, whether or not they ever loaded a page here. Since Nov 13 2026 the link answers a browser with a very short page of ours first, which sends the browser on by itself within a moment; a person sees a flash at most, and a Continue button if scripts are off.
- An automated client fetching the link gets a 403 and is recorded as refused, and a client that fetches the short page without running it gets no further; nothing is forwarded either way, so our vendor partners never see automated clicks under our ids. An agent driving a real browser is still an agent: the link is for the person.
- The API hands out no plain vendor URLs and, since Nov 8 2026, no vendor item numbers either: a listing's
idis our own token, the same one itsclick_urlcarries, so recognise a listing by that and send people to it through the link. (The formeritem_idfield is gone.) Untagged traffic is how a free service like this stops paying for itself.
Affiliate disclosure
buyaigear earns a commission when someone buys through one of these links, through the eBay Partner Network and the Amazon Services LLC Associates Program; as an Amazon Associate we earn from qualifying purchases. The price the buyer pays does not change, and rankings are by the numbers in the data, never by commission. The full text is on the affiliate disclosure page. Prices and availability are the vendor's, accurate as of the observed_at or as_of time in each answer, and can change at any time.
Reading the numbers
- Prices are USD and delivered: item price plus the shipping eBay quotes to a US address (Portland, Oregon).
shipping_usdis null when eBay gave no quote; such a listing ranks on its item price. Amazon prices are not tracked yet; the Amazon entry is a forward to the product page. - Only listings that passed our filters appear: no brackets, cables, lots or broken cards, a seller reputation bar on expensive products, and no auctions (fixed price and best offer only).
buying_optionsandends_atcome from eBay and are null on rows the price job has not refreshed since they were added. - Speeds are estimates from the spec sheet, rounded to two significant figures, for one user at 8K of context (and 32K);
fitis fits, fits_short_context, runs_with_ram_offload or does_not_fit. The method is on the methodology page. price_historyand/products/{slug}/historygive the daily low across the product's offers;reconstructedmarks days rebuilt from listings we tracked before this site launched.
Talk to us
Agents can say hello at /agent/hello; a human reads and answers in a thread (details in /agents.txt). People can write to support@buyaigear.com. Missing a filter or a field you need? Say so. This API exists because agents were already reading the HTML.