retailerapi / docs

GET /v1/products/{id}

The primary product-lookup endpoint. Resolves any UPC, EAN, ISBN, GTIN, ASIN, Walmart item_id, or Best Buy SKU / product id and returns the full normalized product including price history, marketplace fees, and Bucket-1 facts.

Request

GET https://api.retailerapi.com/v1/products/{id}
Authorization: Bearer rk_live_...

Path parameters

NameRequiredDescription
idyesUPC-12, EAN-13, ISBN-10/13, GTIN-14, Amazon ASIN (B0XXXXXXXX), Walmart item_id (6-12 digits), Best Buy SKU (7-8 digits) or Best Buy product id (10 characters, e.g. JXJVXGFQKQ), or any retailer PDP URL. URLs must be URL-encoded when passed in the path. Cost is 1 token regardless of identifier type.

Best Buy identifiers. A Best Buy product id is unambiguous and resolves directly. A Best Buy SKU is 7-8 digits, which overlaps the Walmart item_id space, so it is tried only after the Walmart catalog returns nothing — a numeric identifier that Walmart carries always resolves as Walmart. Both come back with _meta.source: "bestbuy" or with Best Buy named as the price source in _meta. Pass them bare: Best Buy identifiers are not accepted alongside ?retailer=, and since force_refresh is only valid with ?retailer=, they cannot be force-refreshed either. Use a Best Buy PDP URL if you need ?retailer=bestbuy&force_refresh=true.

URL submission works on any retailer that ships Product structured data. The 7 vetted retailers (Amazon, Walmart, Target, Home Depot, Lowe's, Best Buy, eBay) have dedicated by-URL parsers and return the richest shape. The ~2 million Shopify-hosted stores work via Shopify's public /products/<handle>.json endpoint. Any other retailer with Product JSON-LD or OpenGraph product tags in its initial HTML works through the generic-URL path.

Examples:
  • amazon.com/dp/B07ABC1234 — Amazon ASIN extracted, full canonical shape
  • walmart.com/ip/Some-Item/19667262713 — Walmart item_id extracted, full canonical shape (also /p/, /grocery/ip/)
  • target.com/p/.../A-89377627 — Target TCIN-based PDP via Target's RedSky JSON endpoint
  • bestbuy.com/product/.../JXJ62C6654 — Best Buy SKU-based PDP, title + price from JSON-LD + embedded GraphQL
  • homedepot.com/p/.../204287095 — Home Depot PDP with JSON-LD inline
  • lowes.com/pd/.../1000318555 — Lowe's PDP with JSON-LD inline
  • ebay.com/itm/322204481859 — eBay listing
  • any-shopify-store.com/products/some-handle — Shopify's universal .json endpoint
  • patagonia.com/product/.../25528.html — generic JSON-LD parser path
Variant query params + fragments are preserved. Bare URLs of known retailers extract to the underlying identifier (fast path, cache-friendly). URLs with query strings or fragments are fetched directly so variant selectors aren't stripped silently.

Query parameters

NameTypeDefaultDescription
formatstringauto-detectOne of UPC, EAN, ISBN, GTIN, ASIN, item_id. Set when input could be ambiguous. ASIN routes through Amazon-first; include_offers_reviews returns the full Amazon per-seller offer list (AOD) for ASIN / ?retailer=amazon. include_offers_history stays Walmart-only. On an ASIN lookup, read asin_match before pricing against the response — see below.
include_offers_reviewsbooleanfalseLive marketplace sellers + review summary (rating, sentiment, verified-purchase counts) + a monthly review trend. Individual review bodies (reviews.top_reviews) are included when the source exposes them — Walmart currently returns aggregates only. +5 tokens.
include_offersbooleanfalseLive marketplace sellers ONLY (no separate reviews block — the review summary already rides the base call for free). Use this instead of include_offers_reviews when you only need the seller list. +5 tokens.
include_cross_retailerbooleanfalseInclude the cross_retailer block — a map keyed by retailer slug of cached per-retailer cells (price, in_stock, Bucket-1 fields). +2 tokens. Read-only over our cache; never triggers fresh scrapes. Cells with status='indexing' mean we haven't fetched that retailer yet — call again in a few seconds.
include_seller_contextbooleanfalseLive seller-side state under cross_retailer.<retailer>.seller_context.restricted and .wfs_eligibility, plus top-level seller_context.restricted aggregation. +3 tokens. Marketplace fees (referral_fee_usd, wfs_fee_usd) are FREE in the base call — this flag adds the live-state fields only. Applies to marketplace retailers; first-party retailers emit seller_context: null.
include_offers_historybooleanfalseHistorical marketplace offers — the price/seller archive for this item, each entry stamped with an observed_at snapshot time (plus was_price). +5 tokens. Walmart only for now. Distinct from the free include_history (price-history shape control) — this is the Keepa-style marketplace-offers archive. Returns an empty array when we have no archived offers for the item yet.
include_price_seriesbooleanfalseThe raw day-by-day price series under price_history.series — one bar per day carrying open, close, low, high. +10 tokens. Walmart only. The 30/60/90/180-day aggregates under stats.windows are FREE in the base call; this flag buys the daily bars underneath them. Charged only when we actually hold bars — an item with no history costs nothing extra.
identifier_matchany | confirmedanyExact-match filter over the cross_retailer block. Free — it filters data include_cross_retailer already paid for. any returns every cached retailer row, each labelled with how it was matched under cross_retailer.<retailer>.identity. confirmed returns ONLY rows the retailer's own record ties to the identifier you searched — rows we matched by a title/keyword guess, and rows where the retailer publishes a different barcode, are dropped. An empty cross_retailer object is a real answer: we hold nothing for that product we can vouch for. Any other value returns 400.
retailerstring(unified)Anchor the response to a specific retailer's data. Slug format: lowercase alphanumeric only, 2-30 chars, no TLD or separators (homedepot not home-depot). Vetted retailers have custom parsers; other slugs route through a self-extending WebFetch waterfall. Cost: 1 token flat.
force_refreshbooleanfalseBypass cache and force a fresh scrape of the retailer specified by ?retailer=<retailer>. Only valid with ?retailer=<retailer> — passing force_refresh alone returns 400. No additional token cost beyond the retailer surcharge. This is the ONLY way to force fresh data from the API.

Cost summary

Call shapeTokensWhat you get
Base lookup1title, brand, image, price, identifiers, weight, dimensions, MSRP, description, categories, 30/60/90/180-day price aggregates, retailer_links, Bucket-1 facts (sold_tag, estimated_sales, is_best_seller, pack_count, hazmat), computed marketplace fees (referral_fee_usd, wfs_fee_usd)
+ include_cross_retailer3+ cross_retailer block (cached cells for every retailer we have for this UPC, read-only)
+ include_seller_context4+ live restriction + WFS eligibility state
+ include_offers_reviews6+ live marketplace sellers + review summary (sentiment + monthly trend)
+ include_offers_history6+ historical marketplace offers (price/seller archive, Walmart)
+ include_price_series11+ the raw day-by-day price bars under price_history.series (Walmart). The aggregates are already free in the base call.
All three flags11Full reseller view (cross_retailer + seller_context + offers_reviews)
?retailer=<r>1Anchor to a specific retailer (replaces base call shape)
?retailer=<r>&force_refresh=true1Same as above but bypasses cache + scrapes fresh. Only way to force fresh data from the API.

Marketplace fees (referral_fee_usd, wfs_fee_usd) are computed from public rate cards and are always free in the base call — same model as Keepa's referralFeePercentage. include_seller_context only pays for the live-state fields (restricted, wfs_eligibility).

Response

200 OK with a JSON body. Fields below show a UPC lookup with all opt-in flags enabled.

{
  "item_id": "19667262713",
  "upc": "086279195869",
  "ean": null,
  "isbn": null,
  "gtin": "00086279195869",
  "asin": null,
  "mpn": "EP-PC8",
  "model": "EP-PC8",
  "title": "12-in-1 Electric Pressure Cooker 6 QT...",
  "brand": "Cooks Essentials",
  "image_url": "https://i5.walmartimages.com/...",
  "description": "Cook everything from rice to roast...",
  "current_price": 100.56,
  "buybox_price": 100.56,
  "secondary_offer_price": 99.50,
  "msrp": 149.99,
  "weight_lbs": 12.5,
  "weight_assembled_lbs": 12.5,
  "weight_package_lbs": 14.2,
  "dimensions": { "height_in": 13.2, "width_in": 13.0, "length_in": 12.8 },
  "dimensions_assembled": { "height_in": 13.2, "width_in": 13.0, "length_in": 12.8 },
  "dimensions_package": { "height_in": 15.0, "width_in": 14.5, "length_in": 14.0 },
  "offers_count": 4,
  "total_offers": 6,
  "delivery_date": "2026-06-23",
  "fulfillment": {
    "shipping": { "available": true, "cost": 0, "free": true, "date": "2026-06-23" },
    "delivery": { "available": false, "cost": null, "date": null },
    "pickup": { "available": true, "cost": 0, "date": "2026-06-21" }
  },
  "seller_name": "Walmart",
  "seller_id": "F55CDC31AB754BB68FE0B39041159D63",
  "average_rating": 4.3,
  "review_count": 1247,
  "categories": ["Home", "Appliances", "Pressure Cookers"],
  "specs": [
    { "name": "Model", "value": "EP-PC8" },
    { "name": "Capacity", "value": "6 quart" },
    { "name": "Color", "value": "Stainless Steel" }
  ],
  "walmart_url": "https://www.walmart.com/ip/...",
  "in_stock": true,
  "condition": "new",
  "seller_type": "first_party",
  "seller_rating": null,

  /* Walmart marketplace economics — FREE in the base call (Keepa parity), derived
     from the record. Platform/item-wide, not seller-specific. */
  "referral_fee_usd": 15.08,
  "wfs_fee_usd": 11.95,
  "restriction": { "flag": false, "reason": null },
  "wfs_eligibility": { "enabled": true, "reason": null },

  /* top-level UPC-scoped restriction view — present when include_seller_context=true */
  "seller_context": {
    "restricted": { "any": false, "retailers": [], "primary_reason": null }
  },

  /* Price history, from our daily-bar archive — one bar per day.
     days_covered is how many days we actually hold for this item, so every
     figure below can be read against the evidence behind it. */
  "price_history": {
    "first_observed_date": "2026-07-01",
    "last_observed_date": "2026-08-02",
    "days_covered": 29,

    /* series is present only with include_price_series=true (+10). */
    "series": [
      { "date": "2026-08-02", "open": 99.99, "close": 99.99, "low": 99.99, "high": 99.99, "observations": 1 },
      { "date": "2026-08-01", "open": 104.99, "close": 99.99, "low": 99.99, "high": 104.99, "observations": 3 }
    ]
  },

  /* Aggregated price stats — FREE in the base call. One entry per window.
     A window we hold no bars for is null, never a fabricated number, and
     days_covered states the real depth behind each row. */
  "stats": {
    "current_price": 99.99,
    "windows": {
      "30d":  { "low": 89.99, "high": 119.99, "average": 101.42, "days_covered": 28, "observation_count": 28 },
      "60d":  { "low": 89.99, "high": 124.99, "average": 103.10, "days_covered": 29, "observation_count": 29 },
      "90d":  { "low": 89.99, "high": 124.99, "average": 103.10, "days_covered": 29, "observation_count": 29 },
      "180d": { "low": 89.99, "high": 124.99, "average": 103.10, "days_covered": 29, "observation_count": 29 }
    }
  },

  /* free for barcode lookups; absent for item_id */
  "retailer_links": [
    { "retailer": "walmart", "url": "https://walmart.com/ip/...", "found_via": "native_catalog" },
    { "retailer": "amazon",  "url": "https://amazon.com/dp/B0...", "found_via": "amazon_catalog" }
  ],

  /* Map keyed by retailer slug. Only present when include_cross_retailer=true.
     Read-only over our cache — to refresh a specific retailer's data,
     use ?retailer=<retailer>&force_refresh=true. */
  "cross_retailer": {
    "walmart": {
      "retailer": "walmart",
      "status": "ok",
      "price": 100.56,
      "url": "https://www.walmart.com/ip/...",
      "in_stock": true,
      "unavailable": false,
      "sold_tag": "100+ bought",
      "estimated_sales": 1200,
      "is_best_seller": true,
      "pack_count": 1,
      "hazmat": false,
      "seller_context": {
        "referral_fee_usd": 15.08,
        "wfs_fee_usd": 11.95,
        "restricted": { "flag": false, "reason": null },
        "wfs_eligibility": { "enabled": true, "reason": null }
      },
      "_source": "primary",
      "_freshness": { "refreshed_at": "2026-05-16T10:00:00Z" },
      /* HOW this row was tied to the identifier you searched — and nothing else.
         It is not a claim that the price is current or the variant is right;
         freshness is _freshness, stock is in_stock.
           state:  "confirmed"   the retailer's own record published the barcode
                                 you searched.
                   "unconfirmed" no barcode we could read, so the match rests on
                                 a title/keyword guess. Never treat as confirmed.
                   "mismatch"    the retailer's record published a DIFFERENT
                                 barcode; the product was re-filed under the code
                                 it actually carries, so price and url are null.
           method: "catalog_key"  the retailer's catalog was keyed by this
                                  identifier and its record echoes it back.
                   "page_barcode" the retailer's product page published a barcode
                                  in its own markup and we compared it.
                   null           nothing resolved (always with "unconfirmed").
         identity itself is null on rows written before the check existed.
         Ask for only the confirmed rows with ?identifier_match=confirmed. */
      "identity": {
        "state": "confirmed",
        "method": "catalog_key",
        "page_barcode": "194629116676",
        "checked_at": "2026-05-16T10:00:00Z"
      }
    },
    "amazon": {
      "retailer": "amazon",
      "status": "ok",
      "price": 105.99,
      "url": "https://www.amazon.com/dp/...",
      "in_stock": true,
      "unavailable": false,
      "sold_tag": null,
      "estimated_sales": null,
      "is_best_seller": null,
      "pack_count": null,
      "hazmat": null,
      "seller_context": {
        "referral_fee_usd": 15.90,
        "wfs_fee_usd": null,
        "restricted": null,
        "wfs_eligibility": null
      },
      "_source": "secondary",
      "_freshness": { "refreshed_at": "2026-05-16T09:00:00Z" },
      "identity": {
        "state": "unconfirmed",
        "method": null,
        "page_barcode": null,
        "checked_at": "2026-05-16T09:00:00Z"
      }
    }
    /* + ebay, lowes, target, bestbuy, homedepot */
  },

  /* present when include_offers_reviews=true. offers[] is the full live per-seller
     list (every competing seller), and offers_count reflects its length. Available
     for Walmart (item_id) AND Amazon (ASIN or ?retailer=amazon, via the AOD panel).
     Every offer carries a cross-retailer fulfilled_by_marketplace flag (Walmart
     "wfs" / Amazon "fba"); Amazon offers also carry "fba", and seller_type is "1p"
     (sold by the retailer itself) or "3p" (a marketplace seller), independent of
     fulfillment. condition is a canonical enum shared across retailers. */
  "offers": [
    { "seller_id": "101030561", "seller_id_hex": "C4E1FFE689DE4B388E0EDABC848B3078", "seller_name": "iTech361", "price": 100.56, "is_buy_box": true, "in_stock": true, "wfs": false, "fulfilled_by_marketplace": false, "pro_seller": true, "shipping_cost": 0, "delivery_date": "2026-07-06", "seller_type": "3p", "offer_id": "AB376F76122C494CBE9C13C605A1ADAD", "max_delivery_date": "2026-07-09", "max_order_quantity": 12, "fulfillment_type": "marketplace", "returnable": true, "return_window_days": 30, "free_returns": true, "condition": "new", "quantity_available": 12 },
    /* Amazon (ASIN / ?retailer=amazon) offer shape — the AOD all-sellers list: */
    { "seller_id": "A1JD8CBFFS2JH6", "seller_id_hex": null, "seller_name": "Prime National Distribution", "price": 12.00, "is_buy_box": false, "in_stock": true, "wfs": null, "fba": false, "fulfilled_by_marketplace": false, "seller_type": "3p", "shipping_cost": 0, "delivery_date": "2026-07-08", "condition": "new", "quantity_available": null }
  ],
  "review_summary": {
    "average_rating": 4.3,
    "total_reviews": 1247,
    "rating_distribution": { "5": 812, "4": 234, "3": 98, "2": 53, "1": 50 }
  },
  "reviews": {
    "summary": { "average_rating": 4.3, "total_reviews": 1247, "sentiment": { "positive": 1040, "neutral": 110, "negative": 97 }, "verified_purchases": 1180 },
    "monthly_breakdown": [
      { "month": "2026-05", "total_reviews": 41, "average_rating": 4.4, "sentiment": { "positive": 34, "neutral": 4, "negative": 3 } }
    ],
    "top_reviews": []  /* individual review bodies, when the source exposes them. Walmart currently returns aggregates only, so this is typically empty. */
  },

  /* present when include_offers_history=true (Walmart). offers_history[] is the
     price/seller archive — same per-offer field names as offers[], plus
     observed_at (the snapshot time) and was_price. offers_history_count is the
     total archived rows. Empty array when we have no archive for the item yet. */
  "offers_history_count": 248,
  "offers_history": [
    { "observed_at": "2026-06-21T14:02:00Z", "seller_id": "101030561", "seller_id_hex": "C4E1FFE689DE4B388E0EDABC848B3078", "seller_name": "iTech361", "seller_type": "3p", "price": 104.99, "was_price": 119.99, "shipping_cost": 0, "wfs": false, "pro_seller": true, "condition": "new", "quantity_available": 12, "fulfillment_type": "marketplace", "delivery_date": "2026-06-27", "offer_id": "AB376F76122C494CBE9C13C605A1ADAD", "returnable": true, "return_window_days": 30, "free_returns": true, "seller_rating": 4.6, "seller_review_count": 1820 }
  ],

  "_meta": {
    "title_source": "walmart",
    "weight_lbs_source": "amazon",
    "dimensions_source": "amazon",
    "data_quality_score": 1.0
  },

  "tokens_consumed": 11,
  "tokens_remaining": 856249
}

Field types

  • Identifiers: always strings. item_id is Walmart-internal; upc is the GTIN equivalent.
  • Prices: USD floats with 2 decimal places. null when out of stock.
  • Timestamps: ISO 8601 UTC.
  • in_stock: true when at least one retailer reports the product is in stock; false only when every retailer with a known signal reports out-of-stock; null when no retailer has reported yet.
  • cross_retailer.<retailer>.status: ok | stale | indexing | not_found | blocked | error
  • cross_retailer.<retailer>.seller_context: null permanently for first-party retailers (target, bestbuy, lowes, homedepot) — they don't have a marketplace.
  • retailer_links: where the product is found across retailers (URL only). Free on every barcode lookup.

Cross-retailer field semantics

Bucket-1 facts (sold_tag, estimated_sales, is_best_seller, pack_count, hazmat) populate where each retailer supports the concept. Most are populated for Walmart today; other retailers backfill as we add per-retailer parsers. Null doesn't mean "we forgot to fetch" — it means "this retailer doesn't expose this concept".

Top-level weight_lbs, dimensions, description, mpn, model use the best source we have across retailers. When one retailer's payload is missing weight or dimensions, another retailer's value backfills it automatically (Amazon's catalog tends to be most reliable for physical specs because FBA forces sellers to declare them). _meta.weight_lbs_source records which retailer the value came from on every response.

Package vs assembled. Retailers that distinguish the boxed-for-shipping weight from the product's own weight expose both as weight_assembled_lbs + weight_package_lbs (and the parallel dimensions_assembled + dimensions_package). Top-level weight_lbs / dimensions are the derived "best available": assembled wins (it's what the product actually is); package fills in when no assembled value is known. Retailers that only expose one weight populate weight_lbs and leave the explicit pair as null — call weight_assembled_lbs ?? weight_lbs when you need the product weight and don't care about the source.

Diagnostic _meta block

Every barcode lookup includes a _meta object describing which source each top-level field came from and how strongly sources agreed on identity. Safe to ignore for most uses.

{
  "_meta": {
    "title_source": "amazon",
    "brand_source": "walmart",
    "weight_lbs_source": "amazon",
    "dimensions_source": "amazon",
    "data_quality_score": 0.667,
    "disagreements": [
      {
        "retailer": "target",
        "reason": "title-mismatch",
        "similarity": 0.21,
        "their_title": "Different product entirely",
        "consensus_title": "12-in-1 Electric Pressure Cooker 6 QT..."
      }
    ]
  }
}

Errors

  • 404 when the identifier doesn't resolve (multiple format fallbacks are attempted before returning 404)
  • 400 when the identifier doesn't match any expected format
  • 429 when you exceed your throttle or monthly quota
  • 503 (offers_unavailable) when live offers are momentarily unavailable for a Walmart item. Returned only for live-offers requests (include_offers_reviews=true) so you never receive non-live offer data. Honor the Retry-After header (seconds) and retry; the request is not billed.

Examples

Walmart item_id

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/19667262713"

UPC with cross-retailer

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/194629116676?include_cross_retailer=true"

Exact matches only (no fuzzy cross-retailer rows)

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/194629116676?include_cross_retailer=true&identifier_match=confirmed"

Returns only the retailers whose own record carries the barcode you sent. Same price as the unfiltered call. If cross_retailer comes back {}, that is the honest answer — we hold nothing for that product we can vouch for, and you should treat it as a miss rather than fall back to a guess. Leave the parameter off (or send identifier_match=any) to get every row plus the identity label on each, and decide per row yourself.

What identity does and does not claim. It reports how the row was matched to your identifier — nothing more. A confirmed row can still be stale or out of stock: freshness is _freshness.refreshed_at and availability is in_stock. It is not a guarantee about the price, the variant, or the condition.

asin_match — did an ASIN lookup return the product you asked for?

Present on ASIN lookups only, and separate from identity above — that field describes barcode matching inside cross_retailer; this one describes the top-level body of an ASIN lookup.

The asin field in the response is echoed from your request. We resolve an ASIN by reading that ASIN's own product page. For a product with size or colour variants, Amazon sometimes serves a sibling variant on that URL — a different sellable unit, with its own price and its own availability. asin_match is how you tell the two apart.

stateWhat it means
exactThe listing we read is the ASIN you asked for.
substitutedAmazon served a different product. This never appears on a 200. A substitution is refused at the source and by the cache gate alike, so it reaches you only as 404 identity_mismatch, whose body carries this same asin_match object naming what was served. Branch on the code, not on a 200 body.
unknownThe source carried no ASIN, so we never checked. Not a pass.

matched_asin names the listing we actually read, or null when state is unknown.

So on a 200, state is exact or unknown. Do not write a state === 'substituted' branch and expect it to fire — two gates make it unreachable on a success: the live fetch refuses a page whose own ASIN differs, and the cache refuses to serve a stored row whose payload names a different ASIN. The substitution reaches you as the 404 below. unknown is the one to guard against on a 200: it means the source carried no ASIN, so nothing was checked.

404 identity_mismatch — not the same as 404 not_found

An ASIN lookup has two distinct 404s, and the code is what separates them. If you refresh prices or stock from this endpoint, treat them differently.

codeWhat happenedWhat to do
not_foundAmazon serves its own 404 for this ASIN. The listing is gone.A real verdict. Safe to mark the item unavailable.
identity_mismatchThe page exists but resolves to a different product (asin_match.matched_asin). We know nothing about the ASIN you sent.Not a stock verdict. Keep your last known good price and stock. Retrying will not change it.

This is not a rare branch: on a 50-ASIN sample of real supplier catalogue data, 8 resolved to a sibling. A refresh job that reads any 404 as "delisted" would wrongly deactivate roughly one item in six.

Which retailers can be confirmed, and why

This differs by retailer because the underlying lookups differ, and a retailer that cannot currently be confirmed will be absent from a identifier_match=confirmed response. Read this table before you switch the filter on.

RetailerCan be confirmed?How we look it up
WalmartYes — catalog_keyOur catalog is queried by your identifier and the record it returns echoes it back.
eBayYes — catalog_keyeBay's catalog is queried by barcode, so a hit is an identifier match by construction. eBay's secondary search-page path is unconfirmed.
Best BuyYes — page_barcodeThe product page publishes its own barcode and we compare it.
Lowe'sYes — page_barcodeSame — the page publishes a barcode.
Home DepotYes — page_barcodeSame, where the page publishes one.
AmazonNo — always unconfirmedAmazon is reached by a keyword search that accepts a barcode as the search text. Amazon never tells us the listing carries that code, so we will not claim it does. Amazon rows are dropped by identifier_match=confirmed.
TargetNo — always unconfirmedTarget is reached through a search engine, and the product page does not publish a barcode we can read. Target rows are dropped by identifier_match=confirmed.

If you need Amazon or Target rows, use the default (identifier_match=any) and read each row's identity yourself — you will get the row plus an honest label, rather than silence.

Coverage is still filling in. The identity check began recording in September 2026, and cached rows written before then carry identity: null until they are next refreshed. Treat identifier_match=confirmed as a high-precision filter that is still low recall: what it returns is trustworthy, but it does not yet return everything we hold.

Reseller full view (cross-retailer + seller context)

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/194629116676?include_cross_retailer=true&include_seller_context=true"

EAN-13 (international)

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/5060214160102"

ISBN-13 (book)

curl -H "Authorization: Bearer rk_live_..." \
  "https://api.retailerapi.com/v1/products/9780553213119?format=ISBN"