Aisles Inventory API: read-only JSON search API (v1)
Read-only search over the same listings and freshness rules as the public pages, for apps and AI assistants. No key needed. Assistants can also use the MCP server at https://aislesinventory.com/mcp; an OpenAPI description is at /openapi.json.
Try it: /api/v1/search?q=running+shoes&city=chicago&per_page=3
GET /api/v1/search
| Parameter | Description |
|---|---|
q | Free text matched against brand, title, category and color (all words must match). |
brand | Exact brand (case-insensitive). |
city | zip | lat+lng | Search origin. city is a city slug (chicago, new-york, los-angeles, houston, phoenix, philadelphia, san-antonio, san-diego, dallas, fort-worth, charlotte, columbus, indianapolis, seattle, south-bend, orlando, atlanta, boston, fort-lauderdale, baltimore, detroit, danbury, tampa, oakland, denver, las-vegas, akron, riverside, trenton, pittsburgh, st-louis, norfolk, milwaukee, little-rock, tucson, west-palm-beach, miami, aurora, louisville, minneapolis, memphis, omaha, cincinnati, lancaster, myrtle-beach, austin, cypress, fredericksburg, rogers, modesto, daytona-beach, jacksonville, savannah, michigan-city, kansas-city, albuquerque, albany, buffalo, middletown, rochester, niles, tulsa, scranton, charleston, nashville, allen, el-paso, mcallen, puyallup, birmingham, mobile, fort-smith, camarillo, bakersfield, fairfield, escondido, fresno, salinas, sacramento, victorville, colorado-springs, grand-junction, pueblo, wilmington, hartford, fort-myers, destin, jensen-beach, ocala, panama-city, pensacola, sarasota, tallahassee, commerce, columbus-ga, augusta, coralville, davenport, sioux-city, boise, champaign, normal, rockford, springfield, evansville, fort-wayne, kokomo, lafayette, peoria, ashland, wichita, bowling-green, lexington, elizabethtown, paducah, alexandria, baton-rouge, worcester, hyannis, hagerstown, salisbury, flint, portage, duluth, columbia, st-cloud, springfield-mo, jackson, tupelo, missoula, asheville, greensboro, raleigh, fargo, wilmington-nc, manchester, rockaway, gallup, reno, syracuse, dayton, sandusky, st-clairsville, toledo, oklahoma-city, erie, allentown, columbia-sc, greenville, florence, sioux-falls, clarksville, knoxville, chattanooga, abilene, beaumont, college-station, corpus-christi, killeen, longview, laredo, lubbock, midland, san-angelo, san-marcos, texas-city, victoria, waco, richmond, lynchburg, roanoke, kennewick, portland, union-gap, green-bay, johnson-creek, madison, bridgeport, mount-hope, vienna, huntsville, florence-al, dothan, chico, yuba-city, palm-desert, palmdale, fort-collins, macon, gainesville-ga, eugene, grand-rapids) or name; defaults to Chicago, IL. Only these cities have published inventory. Errors: unknown_location, outside_pilot_geography. |
radius | Miles, 0.1–50. Default: every store Aisles lists for the city (city searches), or 10 miles (ZIP or lat/lng). |
size, size_system | Exact size (e.g. 11) and optional system (US_MENS, US_WOMENS, US_YOUTH). |
color, width | Color substring; width code (D, 2E) or alias (regular, wide, extra_wide, narrow). |
min_price, max_price | Dollars. |
availability | available (default: in stock or low stock), out_of_stock, unknown, any. Uses the current effective status, so expired listings are unknown. |
fulfillment | Comma list: pickup_today, store_pickup, curbside_pickup, ship_to_store, in_store_shopping, same_day_delivery, local_delivery. |
retailer | Retailer id (e.g. bestbuy). |
page, per_page | 1-based page; per_page 1–50 (default 20). |
Response
{
"api_version": "1",
"generated_at": "ISO-8601",
"query": { ...normalized parameters },
"pagination": { "page": 1, "per_page": 20, "total": 3, "total_pages": 1 },
"results": [{
"retailer": { "id", "name" },
"product": { "slug", "brand", "title", "category", "gtin" },
"variant": { "sku", "size", "size_system", "color", "width", "gtin", "description" },
"store": { "slug", "name", "address", "address_text", "lat", "lng", "timezone", "distance_miles" },
"offer": { "availability", "reported_stock_status", "quantity", "price": { "amount", "currency", "scope" },
"fulfillment": [{ "type", "status", "same_day", "ready_within_minutes" }], "pickup_today", "pickup_today_basis",
"last_checked_at", "source_updated_at", "expires_at", "stale", "freshness_label" },
"links": { "aisles_offer_url", "aisles_product_url", "aisles_store_url", "retailer_source_url",
"purchase_url", "purchase_link_monetized", "disclosure" },
"provenance": { "data_origin", "source_method", "collection_run_id", "statement" },
"summary": "Quotable sentence"
}]
}
Reading and citing a result
offer.availabilityis the current effective status: a listing past its freshness window (offer.expires_at) isunknown, never "in stock".- Say how long ago Aisles checked from
offer.last_checked_at, and name the retailer (provenance.statement). - Cite
links.aisles_offer_urlfor a stock claim; send shoppers tolinks.purchase_url(the retailer's page, or an affiliate link only whenpurchase_link_monetizedis true).summaryis a ready-to-quote sentence.
Page representations
Any public page URL followed by .json (e.g. https://aislesinventory.com/products/<slug>.json) returns the view model behind that page, and .md returns Markdown.
Rate limits
60 requests per minute per client. Headers: RateLimit-Policy and RateLimit (the IETF form), and X-RateLimit-Limit, X-RateLimit-Remaining. When exceeded: HTTP 429 with Retry-After.
Errors
Every error is JSON with a stable code (the Error schema in openapi.json):
HTTP 400 { "error": { "code": "invalid_parameter" | "unknown_location" | "outside_pilot_geography", "message": "..." } }
HTTP 404 { "error": { "code": "not_found", "message": "..." } }
HTTP 405 { "error": { "code": "method_not_allowed", "message": "..." } }
HTTP 429 { "error": { "code": "rate_limited", "message": "..." } }
HTTP 503 { "error": { "code": "unavailable", "message": "..." } }
Batch, jobs, cursors, idempotency and sandbox
POST /api/v1/search/batch (up to 10 searches), POST /api/v1/jobs then GET /api/v1/jobs/<id>, pagination.next_cursor with cursor=, an Idempotency-Key header on POST requests, and GET /api/v1/sandbox/search for synthetic test data. See Developers.
Versioning and deprecation
The major version is in the path (/api/v1/). Within v1, fields are only added, never removed or renamed, so ignore fields you do not use. A change that would break callers gets a new path (/api/v2/); v1 then keeps working for at least 6 months, and its responses carry Deprecation and Sunset headers with the date it stops, announced here first. Full policy: /api/deprecation-policy.