Logimu

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

CallCredits
Curated product search (/v1/shopping)2 per query
Curated search, detailed (/v1/shopping?detail=true) — per-product intelligence attached5 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.

ParamNotes
qrequired — the search query. A bare ASIN (or numeric Walmart item ID) returns exactly that product (mode: "asin").
countryus (default), uk, de, ca, au, fr, it, es, jp, mx, br — 11 Amazon marketplaces — plus walmart (Walmart US, numeric item ID)
categoryoptional — 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.
groupoptional — force category, price, or none; default auto
qrequired — 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.
sortoptional — 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.
detailoptional — 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.

ParamNotes
asin10-char ASIN, or a numeric Walmart item ID with country=walmart. Provide either asin or gtin (not both).
gtinoptional 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.
  • Resolved within the requested marketplace — the same barcode can be a different listing in us and uk.
  • A barcode legitimately maps to more than one ASIN (variations, re-listings, bundles). We return the best match — priced first, then most recently observed — and list every match in gtin_matches with gtin_match_count, so you can pick a different one rather than trusting ours.
  • We resolve barcodes from observed listings, so a perfectly valid barcode can still be unknown to us if that product has not been seen in that marketplace. That answer is a 404 and is never billed.
  • Billing is identical to an asin lookup once resolved.
countryus (default), uk, de, ca, au, fr, it, es, jp, mx, br — 11 Amazon marketplaces — plus walmart (Walmart US, numeric item ID)
modeauto (default) · cache · live — snapshot freshness (live scrape: all Amazon marketplaces; not Walmart)
bsr_historyoptional — true adds per-category BSR rank history: one daily point per category, each tagged with its era.
  • Amazon US reaches Oct 2023 (~33 months). Other marketplaces start when tracking began there.
  • Before Apr 2026 the source is top-100 best-seller lists: leaf categories only, ranks censored at 100. Those segments carry legacy_censored_at_100, and a gap means "outside the top 100 or not scraped" — not a rank of zero.
  • From Apr 2026: full rank values, including the root category.
  • Legacy categories we could not map to a current name are kept and flagged unmapped_legacy rather than dropped.
  • +0.5 credits, only when history is actually returned. Amazon only — Walmart has no BSR and is never charged for it.
  • History reads a very large archive, so it is the slowest part of this call. If it exceeds its budget we drop only the history block and still return the rest of the response, flagged history_degraded: true and charged accordingly (no +0.5). The snapshot and intelligence data in that response are complete — just retry the history request later.
bsr_leaf / bsr_leaf_categoryalways 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_historyoptional — 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_offersoptional — 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.
  • Use it for unauthorized-seller, MAP and hijacker work: sellers deeper than the top 10 are exactly the ones those use cases are looking for.
  • Leave it off for repricing and sourcing, where the buy box and top offers are enough and latency matters.
  • Roughly 1 in 125 ASINs carries more than 10 offers, so on most products the two modes return the same list.
  • Without it, offer_count from a live scrape is a floor, not a total.
max_age_dayscache 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/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"
FieldNotes
credits_remainingcredits left on the key (null on unmetered internal keys)
planmetered or internal
suspendedtrue when the account is suspended — calls will be refused
usage_30dcalls 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

FieldNotes
observed_atwhen the row's data was observed (UTC)
age_daysage of that observation in days — 0 on a live scrape
sourcecache 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.

statusMeaningBilled
okserved, with product data0.5 (cached) / 1.0 (live)
stale_skippedtracked, but older than max_age_days in cache mode0 — never
not_trackednot in the warehouse (coverage is best-seller-scoped, not the full catalog)0 — never
failedinvalid ID, or the live scrape did not return the product0 — never

Duplicate lines are served in the output but billed once. Unknown request fields are a loud 422 before anything bills.

Modes

modeBehaviour
cachewarehouse only — rows older than max_age_days come back stale_skipped, disclosed and unbilled
livescrape every row — Walmart has no live scrape, so country=walmart + mode=live is rejected with a 422
autodefault — warehouse when fresher than max_age_days (default 30), scrape the rest

Endpoints

EndpointNotes
POST /v1/batch-estimateprice a list before running it — free, always; returns tracked / not-tracked / fresh / stale counts, an age histogram and the credit upper bound
POST /v1/batchescreate a named, re-runnable batch — body: name, country, mode, max_age_days, asins[]
GET /v1/batcheslist 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}/estimatefresh 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}/schedulerecurring runs: daily / weekly / monthly / none, plus enabled, an optional per-firing credit_ceiling and an optional webhook_url — see below
POST /v1/batches/{id}/runsqueue 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}/resumeresume 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.jsonlstreaming JSONL — downloadable mid-run with every row completed so far
GET /v1/batches/{id}/runs/{run_id}/result.csvstreaming 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.

ColumnNotes
current_sellerscompact 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_priceminimum per-seller price; empty when the row has no priced offer list
bought_past_monththe Amazon “N+ bought in past month” badge as an integer; empty when the product shows no badge
descriptionlast 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) → 429 with Retry-After. Credits are the volume limit.
  • 401 missing/invalid key · 402 out of credits · 404 not found (unbilled; the body may carry found_on + a hint — e.g. the ASIN is tracked on another marketplace, or a US live scrape can be requested with mode=live) · 422 bad params.
  • Every record carries an as_of timestamp — data is observed, not real-time. Sales figures are estimates.