API documentation
Amazon (US, UK, DE, CA, AU) & Walmart product data — single-ASIN lookups, multi-seller offers, curated product search, and warehouse filtering. Served from cache in milliseconds or scraped live. Interactive reference →
Base URL & auth
https://api.logimu.com
Send your key in the X-API-KEY header. Get one with 2,500 free credits at
sign up.
curl "https://api.logimu.com/v1/product?asin=B0BDHQSZCV" \ -H "X-API-KEY: sk_live_..."
Credits
| Call | Credits |
|---|---|
| Curated product search (/v1/shopping) | 2 per query |
| Curated search, detailed (/v1/shopping?detail=true) — per-product intelligence attached | 5 per query |
| Product (/v1/product) — cached, everything included snapshot + all intelligence blocks: full price-change timeline + 30-day events, bought-past-month, every current offer with seller IDs, brand stats | 1 |
| ↳ snapshot only — charged when the product has no intelligence to attach (not a selectable option) | 0.5 |
| ↳ + BSR rank history (bsr_history=true, back to Oct 2023) | +0.5 when returned |
| ↳ + buy-box timeline & per-seller prices (offer_history=true) | +0.5 when returned |
| ↳ live scrape instead of cache | +0.5 |
| ↳ Walmart (no live scrape available) | 1 |
| Warehouse filter search (/v1/search) | 1 per 25 results, every marketplace |
| Partial scrape, not found, empty, failed, or rate-limited you are never charged for a request that did not return what you asked for, and credits are valid 12 months | 0 — never billed |
Every marketplace costs the same. Cache vs live is chosen per request with
mode and max_age_days (below).
GET /v1/shopping curated search
Keyword in, ranked product recommendations out — in under 100 ms. Broad queries come back grouped by product category; specific ones by Budget / Mid-range / Premium price tier. Within each group our ranking selects the strongest products using Amazon-reported sales, ratings, review counts, and seller and brand signals.
| Param | Notes |
|---|---|
| q | required — the search query. A bare ASIN (or numeric Walmart item ID) returns exactly that product (mode: "asin"). |
| country | us (default), uk, de, ca, au, fr, it, es, jp, mx, br — 11 Amazon marketplaces — plus walmart (Walmart US, numeric item ID) |
| category | optional — keyword filter on the product-category path. Matched against the full path including all parent categories, with singular/plural folding (and German inflection on de). q=coffee maker&category=machine keeps only categories whose path mentions Machine(s); multiple words must all appear. Matching uses word-stem folding (powered ↔ power), max 200 characters. An unmatchable value returns total: 0 — never billed. Prefer broad category words: a filter that excludes every strong match can surface weaker description-level matches rather than an empty set. |
| group | optional — force category, price, or none; default auto |
| q | required — keywords, a bare ASIN, or a bare barcode (UPC/EAN/GTIN, 8–14 digits). An ASIN or barcode returns the product(s) it identifies rather than a keyword search. A barcode can map to several ASINs: gtin_matches lists every ASIN we have mapped to it and gtin_match_count counts them, while results carries the ones we hold current data for — so a 3-match barcode can legitimately return fewer than 3 products. Barcodes are not accepted for country=walmart, where a numeric query is an item ID. |
| sort | optional — relevance (default), price, rating. When grouping is active (the default), results is a concatenation of the per-group lists — each group is sorted internally, but the flat array is not globally sorted. Pass group=none for a globally sorted flat list. |
| detail | optional — true attaches the /v1/product intelligence blocks (30-day price change events, current sellers) to every product. 5 credits per query instead of 2; response takes a few seconds. bought_past_month needs no flag — it is included on every product in every response. |
curl "https://api.logimu.com/v1/shopping?q=toothbrush&country=us" \\ -H "X-API-KEY: sk_live_..."
{
"query": "toothbrush", "country": "us", "currency": "USD",
"total": 1549, "mode": "category",
"groups": [ { "category": "\u2026 > Powered Toothbrushes", "count": 110,
"products": [ { "asin": "B072YVWBXH", "product_id": "B072YVWBXH",
"product_url": "https://www.amazon.com/dp/B072YVWBXH",
"title": "Aquasonic \u2026", "brand": "Aquasonic",
"price": 35.95, "rating": 4.6, "review_count": 136657, "in_stock": true,
"bought_past_month": 7000,
"image_url": "https://\u2026", "amazon_url": "https://www.amazon.com/dp/B072YVWBXH",
"observed_at": "2026-07-22T16:03:48Z" } ] } ],
"facets": { "brands": [ {"value":"Oral-B","count":102,"avg_rating":4.56,"est_monthly_sold":14109} ] },
"credits_charged": 2, "credits_remaining": 2498
}
Demand signal. Every product carries
bought_past_month — the floor of Amazon’s “N+ bought in past
month” badge (e.g. 7000 for “7K+”), measured buyer behavior as
Amazon reports it, null where Amazon shows no badge. Included in every
response — no detail flag required.
Identifiers. Every product carries
product_id and product_url. product_id is the ASIN on
Amazon and the numeric item ID on Walmart; product_url points at the right
storefront (amazon.<tld>/dp/… or walmart.com/ip/…).
Pass product_id straight to /v1/product for that
item’s full history. The older asin and amazon_url keys are still
returned unchanged for compatibility, but note both are misnamed on Walmart (they carry the
item ID and a walmart.com URL) — prefer the product_* pair.
Results are scoped to the product category the query resolves to, so a search for graphics card returns graphics cards rather than whatever unrelated best-seller happens to share a word with the query.
Every product carries observed_at (UTC), the age of the snapshot; stale products (older than ~14 days) are pruned, so it is always recent. Coverage is Amazon best-seller (BSR) products; media (books, music, video)
excluded for now. Same engine as the
product search demo.
GET /v1/product product + intelligence
The single-ASIN product endpoint. One call returns the current snapshot (price, BSR,
rating, reviews, buy-box seller, seller count, FBA, image, sales estimate — cache or live) and
the intelligence blocks: a freshness stamp, the full price-change timeline (price_history, every buy-box price move we ever observed, seller-stamped) plus a 30-day convenience view, the Amazon-reported “bought in past month” badge (measured, not modeled — parsed integer + raw text; Amazon marketplaces only), the current
all-seller snapshot, and brand stats. Cached responses return in under 100 ms.
| Param | Notes |
|---|---|
| asin | 10-char ASIN, or a numeric Walmart item ID with country=walmart. Provide either asin or gtin (not both). |
| gtin | optional anchor — a barcode (UPC-12, EAN-13 or GTIN-14) instead of an ASIN. Punctuation and leading zeros are tolerated, so 012345678905, 12345678905 and 0012345678905 all resolve to the same product.
|
| country | us (default), uk, de, ca, au, fr, it, es, jp, mx, br — 11 Amazon marketplaces — plus walmart (Walmart US, numeric item ID) |
| mode | auto (default) · cache · live — snapshot freshness (live scrape: all Amazon marketplaces; not Walmart) |
| bsr_history | optional — true adds per-category BSR rank history: one daily point per category, each tagged with its era.
|
| bsr_leaf / bsr_leaf_category | always present. Many products (media, books, niche items) never receive an overall best-seller rank — Amazon's own page shows only a category rank there. When bsr is null, bsr_leaf carries the product's best category rank and bsr_leaf_category names the category (e.g. 18 in “Blank Media”). Both are null when the overall rank exists. |
| offer_history | optional — true attaches the buy-box owner timeline (who held the buy box, as observed ownership segments) and per-seller price series (daily points per seller, buy-box price wins the day; top 10 sellers by coverage) from our multi-seller offer stream. US buy-box depth reaches Dec 2024; full multi-seller depth Aug 2025+. +0.5 credits when returned. Amazon only. |
| full_offers | optional — true returns the complete seller list instead of the buy box plus the first page (~10 offers). Only affects a live scrape (mode=live, or mode=auto when the cache is stale); cached responses already carry the full list from our continuous crawl. Adds roughly 15–20s to the call and is not billed extra — still one call.
|
| max_age_days | cache freshness window for the snapshot (default 30) |
Look a product up by barcode instead of ASIN:
curl "https://api.logimu.com/v1/product?gtin=012345678905&country=us" -H "x-api-key: $KEY"
curl "https://api.logimu.com/v1/product?asin=B0BDHQSZCV&country=us&bsr_history=true&offer_history=true" \\ -H "X-API-KEY: sk_live_..."
{
"source": "cache", "credits_charged": 2, "credits_remaining": 2498, // 1 product + 0.5 bsr + 0.5 offers
"asin": "B0BDHQSZCV", "marketplace": "amazon-us", "currency": "USD",
"data_source": "amazon US marketplace — observed listings",
"title": "GuruNanda Butter On Gums Toothbrush \u2026", "brand": "GuruNanda", "price": 5.99,
"price_source": "aod", "price_observed_at": "2026-08-04 19:35:30",
"bsr": 721, "bsr_leaf": null, "bsr_leaf_category": null, // bsr null? bsr_leaf carries the best category rank
"rating": 4.8, "reviews_count": 11091, "review_count": 11091, // same value under both names
"buybox_seller": "Amazon.com", "buybox_seller_id": "legacy_syn:d70108ebb82120a6",
"seller_count": 3, "fba": false, // snapshot_status: live scrapes only
"image_url": "https://m.media-amazon.com/images/I/810lGTtTF-L._AC_SY355_.jpg",
"image": "https://m.media-amazon.com/images/I/810lGTtTF-L._AC_SY355_.jpg", // legacy alias of image_url
"description": null, // listing description when captured (string); null = never observed for this ASIN
"sales_estimate": 1000, "upc": "810051082760", "parent_asin": "B0F19JBV7W",
"as_of": "2026-08-02 23:40:36", "observed_at": "2026-08-04T17:35:30Z",
"product_url": "https://www.amazon.com/dp/B0BDHQSZCV", "history_available": true,
"price_changes_30d": [ { "at": "2026-07-19T16:03:44Z", "from": 5.09, "to": 5.07,
"seller": "Amazon.com", "seller_id": null }, … 3 more ],
"price_history": [ { "at": "2026-06-24T06:53:26Z", "from": 5.97, "to": 5.09, "seller": "Amazon.com", "seller_id": null },
…
{ "at": "2026-08-04T17:35:26Z", "from": 5.07, "to": 5.99, "seller": "Amazon.com", "seller_id": null } ],
"stock_changes_30d": [], "stock_history": [], // empty is normal — see the stock note above
"stock_state": "in_stock", "stock_observed_since": "2026-05-12T18:43:13Z",
"bought_past_month": 10000, "bought_past_month_raw": "10K+ bought in past month",
"bought_past_month_observed_at": "2026-08-04T17:35:26Z",
"current_sellers": { "as_of": "2026-08-04T17:35:30Z", "offer_count": 3, "buybox_seller": "Amazon.com",
"sellers": [ { "seller": "Amazon.com", "seller_id": null, "price": 5.99, "is_buybox": true,
"is_fba": false, "is_prime": true, "seller_positive_pct": null, "seller_feedback_count": null,
"buybox_days_30d": 9 } ] },
"bsr_history": { // bsr_history=true
"observed_from": "2023-10-24", "observed_to": "2026-08-06",
"series": [
{ "category_id": 43, "category_name": "Health & Household", "is_root": true,
"first_date": "2026-05-12", "last_date": "2026-08-04", "n_points": 23,
"points": [ { "date": "2026-05-12", "rank": 893, "era": "current" }, … ] },
{ "category_id": 37904, "category_name": "Manual Toothbrushes", "is_root": false,
"first_date": "2023-10-24", "last_date": "2026-08-06", "n_points": 673,
"legacy_censored_at_100": true, "legacy_category_ids": [ 4255, 15257 ],
"points": [ { "date": "2023-10-24", "rank": 24, "era": "legacy" },
…
{ "date": "2026-08-06", "rank": 2, "era": "current" } ] }
… 7 more series; unmapped legacy categories carry "unmapped_legacy": true
], "notes": "…" },
"offer_history": { // offer_history=true
"observed_from": "2024-12-28", "observed_to": "2026-08-04", "sellers_total": 7,
"buybox_timeline": [
{ "seller": "amazon.com", "seller_id": null, "from": "2025-08-05", "to": "2025-10-01", "days_observed": 9 },
{ "seller": "gurunanda llc", "seller_id": null, "from": "2025-10-10", "to": "2025-10-26", "days_observed": 4 },
{ "seller": "amazon.com", "seller_id": null, "from": "2025-11-08", "to": "2026-08-04", "days_observed": 38 }
],
"sellers": [ { "seller": "amazon.com", "seller_id": "AZHG42YVCIQFR", "first_seen": "2025-08-05",
"last_seen": "2026-08-04", "days_observed": 48, "buybox_days": 47,
"points": [ { "date": "2025-08-05", "price": 5.99, "buybox": true }, … ] } … 6 more ],
"notes": "Gaps between segments are unobserved, not proven ownership changes." },
"brand_stats": { "brand": "GuruNanda", "products_tracked": 69, "avg_rating": 4.53,
"total_ratings": 194317, "in_stock_pct": 100.0, "distinct_buybox_sellers": 2,
"top_buybox_sellers": [ { "seller": "Amazon.com", "products": 40 },
{ "seller": "GuruNanda LLC", "products": 24 } ] }
}
Description & image. description is returned on
both cached and live responses, and image_url on live scrapes as well as cache.
About the stock fields. stock_state, stock_changes_30d and stock_history are still returned, but do not build on them. Our crawl follows best-seller rank, and a product that goes out of stock generally drops out of that walk — so we stop seeing it rather than observing it go out of stock. Measured: out-of-stock appears on 0.24% of availability-bearing observations, well below the true rate for a catalogue this size. Treat these fields as "in stock when last seen", not as a reliable availability timeline.
Credits: a cached call with everything attached is 1 credit. Drop the intelligence blocks and it is 0.5; force a live scrape and it is +0.5; an intelligence-only answer (or Walmart) is 1. A partial live
scrape (identity but no price) sets snapshot_status: "partial" and is
never billed for the snapshot half. snapshot_status is
returned on live scrapes only — it reports the completeness of that
scrape, so cached responses omit it. Change events are transitions from
our 30-day observation stream — one observation per calendar day (the richest scrape pass of that day), so multiple same-day passes never fabricate changes; a price that moved and moved back between two observations is not seen — while price_history and stock_history extend the same transition streams back to the first time we observed the product (stock_observed_since; stock_state is the latest derived state),
each stamped with the buy-box seller at that time. buybox_days_30d = days a seller held the
buy box. Amazon US/UK/DE/CA/AU, plus Walmart (numeric item ID; Walmart returns the intelligence blocks
only). Not billed if the product is untracked.
GET /v1/search
Search our warehouse of 17M+ tracked products across Amazon US/UK/DE/CA/AU + Walmart (not a live SERP scrape). Answers in under 100 ms.
| Param | Notes |
|---|---|
| q | keyword (title/description). An anchor. |
| brand | exact brand. An anchor. |
| seller, category | refinements — combine with q or brand |
| price_min/max, rating_min/max, reviews_min, bsr_min/max, fba, seller_count_min/max | filters |
| sort | bsr(default) · rating · reviews · price · sales_estimate · seller_count |
| max_per_category, limit | result caps (limit ≤ 100, default 50) |
| marketplace | amazon-us(default) · amazon-uk · amazon-de · amazon-ca · amazon-au · walmart |
{
"marketplace": "amazon-us", "limit": 2, "returned": 2, "total_matched": 118,
"products": [ { "asin": "B0CT43D46H", "product_id": "B0CT43D46H",
"product_url": "https://www.amazon.com/dp/B0CT43D46H",
"marketplace": "amazon-us", "title": "Keurig K-Express \u2026", "brand": "Keurig",
"price": 70.39, "currency": "USD", "bsr": 412, "rating": 4.5, "reviews_count": 28104,
"seller_count": 6, "buybox_seller": "Amazon.com", "fba": true, "in_stock": true,
"as_of": "2026-07-29T11:20:04Z" } ],
"credits_charged": 1, "credits_remaining": 2497
}
Provide at least q or brand. Coverage is deep on tracked
brands, not the full Amazon catalog.
Identifiers. As with
/v1/shopping, every row carries product_id
(ASIN on Amazon, numeric item ID on Walmart) and a marketplace-correct
product_url; asin is retained for compatibility and is misnamed on
Walmart.
GET /v1/account free
Your balance, plan and recent usage — so a script can check what it has left before it spends. Never billed.
curl "https://api.logimu.com/v1/account" -H "x-api-key: $KEY"
| Field | Notes |
|---|---|
| credits_remaining | credits left on the key (null on unmetered internal keys) |
| plan | metered or internal |
| suspended | true when the account is suspended — calls will be refused |
| usage_30d | calls and credits over the last 30 days, plus a per-endpoint breakdown |
Batch bulk product data
Submit a list of ASINs (or numeric item IDs for country=walmart), get an
exact cache/live split and credit price before anything runs or bills,
then run it and stream results as JSONL or CSV — partials included, mid-run. Rows are served
through the same path as /v1/product. Also available as a
dashboard UI.
Freshness — on every row, by default
Not opt-in: every result row (JSONL and default CSV columns) carries
| Field | Notes |
|---|---|
| observed_at | when the row's data was observed (UTC) |
| age_days | age of that observation in days — 0 on a live scrape |
| source | cache or live — where this row came from |
Row states
Every submitted line comes back as a result row — nothing is silently dropped from a billed batch.
| status | Meaning | Billed |
|---|---|---|
| ok | served, with product data | 0.5 (cached) / 1.0 (live) |
| stale_skipped | tracked, but older than max_age_days in cache mode | 0 — never |
| not_tracked | not in the warehouse (coverage is best-seller-scoped, not the full catalog) | 0 — never |
| failed | invalid ID, or the live scrape did not return the product | 0 — never |
Duplicate lines are served in the output but billed once. Unknown request
fields are a loud 422 before anything bills.
Modes
| mode | Behaviour |
|---|---|
| cache | warehouse only — rows older than max_age_days come back stale_skipped, disclosed and unbilled |
| live | scrape every row — Walmart has no live scrape, so country=walmart + mode=live is rejected with a 422 |
| auto | default — warehouse when fresher than max_age_days (default 30), scrape the rest |
Endpoints
| Endpoint | Notes |
|---|---|
| POST /v1/batch-estimate | price a list before running it — free, always; returns tracked / not-tracked / fresh / stale counts, an age histogram and the credit upper bound |
| POST /v1/batches | create a named, re-runnable batch — body: name, country, mode, max_age_days, asins[] |
| GET /v1/batches | list your batches, newest first, with each batch's last run |
| GET /v1/batches/{id} | batch detail: line stats + recent runs |
| DELETE /v1/batches/{id} | soft delete — in-flight runs are cancelled; existing results stay downloadable until retention collects them |
| POST /v1/batches/{id}/estimate | fresh estimate for a saved batch against the current warehouse state — free; the cache/live split moves as the nightly walk refreshes rows, so re-estimate before re-running |
| POST /v1/batches/{id}/schedule | recurring runs: daily / weekly / monthly / none, plus enabled, an optional per-firing credit_ceiling and an optional webhook_url — see below |
| POST /v1/batches/{id}/runs | queue a run — stores the estimate it launched under and refuses with 402 when your balance is below it; nothing bills until rows serve. Runs are serialized per marketplace, FIFO by creation — the response carries queue_position |
| GET /v1/batches/{id}/runs/{run_id} | progress: per-state counters, credits charged so far, the stored estimate; queued runs carry queue_position |
| POST /v1/batches/{id}/runs/{run_id}/resume | resume a run that paused at the credit floor — it re-queues on its marketplace and pending rows continue; nothing already served is re-billed |
| GET /v1/batches/{id}/runs/{run_id}/result.jsonl | streaming JSONL — downloadable mid-run with every row completed so far |
| GET /v1/batches/{id}/runs/{run_id}/result.csv | streaming CSV (22 summary columns incl. the freshness fields) — downloadable mid-run |
Result formats
CSV — 22 summary columns, in order:
line_no, asin, status, source, observed_at, age_days, credits, title, brand, price,
currency, in_stock, bsr, rating, review_count, bought_past_month, buybox_seller, seller_count,
lowest_offer_price, current_sellers, image_url, description.
JSONL — each row carries the complete /v1/product
payload: full per-seller offer list, 30-day price & stock change events, brand stats.
| Column | Notes |
|---|---|
| current_sellers | compact JSON of the full per-seller offer list, in the cell — parse it as JSON; per-seller price / fba / prime / feedback / buybox_days_30d |
| lowest_offer_price | minimum per-seller price; empty when the row has no priced offer list |
| bought_past_month | the Amazon “N+ bought in past month” badge as an integer; empty when the product shows no badge |
| description | last column — may be multi-line and quoted; empty when the source never showed one |
Caps: 10,000 rows per batch. Results are retained for 30 days
(410 after). A run that hits your credit floor pauses — rows stay
pending, partials stay downloadable, and it resumes after a top-up; it never bills into a negative
balance. A live row typically takes ~28 s (measured at the current operating point); rows run
concurrently, and the estimate returns estimated_live_duration_seconds for your list.
Schedules & webhooks
A schedule fires at most once per period (server date:
daily after midnight, weekly on Monday, monthly on the 1st). Each firing computes a
fresh estimate and refuses to run — recording a cancelled run and emailing
you — when that estimate exceeds the credit_ceiling (default: 2× the
estimate at schedule-set time) or your balance. A schedule never surprises you with a bill.
Setting webhook_url returns the signing secret
once — store it. We POST the run summary to your URL on completion and on
pause, signed X-Logimu-Signature: sha256=<hex HMAC-SHA256(secret, raw body)>,
with 3 retries on failure.
curl -X POST "https://api.logimu.com/v1/batch-estimate" \
-H "X-API-KEY: sk_live_..." -H "Content-Type: application/json" \
-d '{"asins":["B0BDHQSZCV","B072YVWBXH"],"country":"us","mode":"auto"}'
{
"country": "us", "mode": "auto", "max_age_days": 30,
"rows_submitted": 2, "rows_valid": 2, "rows_invalid": 0, "rows_duplicate": 0,
"tracked": 2, "not_tracked": 0, "fresh_within_max_age": 2, "stale": 0,
"estimated_credits_max": 1.0, "estimated_usd_max": 0.0,
"billing_note": "Upper bound: failed, not-found and not-tracked rows are never billed. Cached rows 0.5 credits, live rows 1.0.",
"age_histogram_days": { "3": 1, "11": 1 }, "estimate_valid_minutes": 60
}
# create the batch, then run it
curl -X POST "https://api.logimu.com/v1/batches" \
-H "X-API-KEY: sk_live_..." -H "Content-Type: application/json" \
-d '{"name":"my-skus","country":"us","mode":"auto","max_age_days":30,
"asins":["B0BDHQSZCV","B072YVWBXH"]}'
# => {"id": 12, ...}
curl -X POST "https://api.logimu.com/v1/batches/12/runs" -H "X-API-KEY: sk_live_..."
# => {"id": 34, "status": "queued", "estimate": { ... }}
curl "https://api.logimu.com/v1/batches/12/runs/34" -H "X-API-KEY: sk_live_..."
curl -o out.csv "https://api.logimu.com/v1/batches/12/runs/34/result.csv" -H "X-API-KEY: sk_live_..."
Rate limits, errors & honesty
- Per-key rate limit ~10 req/s (burst 20) →
429withRetry-After. Credits are the volume limit. 401missing/invalid key ·402out of credits ·404not found (unbilled; the body may carryfound_on+ ahint— e.g. the ASIN is tracked on another marketplace, or a US live scrape can be requested withmode=live) ·422bad params.- Every record carries an
as_oftimestamp — data is observed, not real-time. Sales figures are estimates.