# ZooData API Quick Reference > Concise field reference for the currently documented Amazon commerce and keyword-intelligence endpoints. Load when you need exact parameter/field names. > > **OpenAPI Spec (live)**: https://zoodata.ai/api/v1/openapi-spec Base URL: `https://api.zoodata.ai/openapi/v2` Auth: `Bearer $ZOODATA_API_KEY` Method: All POST with JSON body --- ## 1. categories | Parameter | Type | Note | |-----------|------|------| | categoryKeyword | String | Search by keyword | | categoryPath | List\ | Exact path lookup, e.g. `["Electronics", "Computers"]` | | parentCategoryPath | List\ | Return all direct children of the exact parent path | | _(no params)_ | — | Returns root categories | Response: `data: list[Category]`; every row includes `categoryId`, `categoryName`, `categoryPath`, `hasChildren`, `isRoot`, `level`, `productCount`, and `link`. A `parentCategoryPath` request returns the complete direct-child list in one response. CLI `categories --parent` requires a nonempty JSON string array. Other category-path flags accept a JSON array or `>`-separated names, but reject a comma-bearing string without an explicit separator as ambiguous. The CLI fails before the API call instead of guessing path boundaries. --- ## 2. markets/search The market contract follows the current MCP descriptions, inputSchema and outputSchema. Inspect the connected service's tools/list before live MCP use; cached tool definitions and another deployment's documentation may describe a different version. Use the configured service for verification. All 14 market endpoints use SPU (parent-product / Amazon Listing) grain: variants of the same product are merged. Only US is supported. Money is already USD; rates are fractions. Public floating metrics are rounded to two decimals, midpoint away from zero; integers and null remain unchanged. Filtering and sorting use these same rounded values. A returned zero is a value, not missingness. `avgReviewCount` is unavailable; rating count is not written-review count. ### Search request and response `resolvedDate` records the actual business date of returned market data. Keep it distinct from the requested `date`, which selects data and can resolve to a different business date. Launch composition instead uses its returned first-launch periods; its contract does not require an additional data-date field. `markets/search` accepts nested `category.ids` (1–100 exact IDs), `category.path` (1–10 hierarchy names, matching a path prefix), or `category.name` (exact name), mutually exclusive. Top-level `categoryIds` is an alternative to nested locators. `categoryKeyword` is a literal case-insensitive substring at any categoryPath level. Top-level `includeDescendantCategoryProducts` controls product coverage inside each market, independently of market-row selection; omitted/null means descendant-inclusive. Parent and child markets can overlap. Other market requests require a real boolean, default true. Search uses optional `date` as a cutoff: omit for the latest common published snapshot, or select the most recent common snapshot on or before the supplied valid YYYY-MM-DD. Historical snapshots start at 2026-02 and are month ends; the cutoff need not be a month end. If none is available before the cutoff, data is empty. Read actual `resolvedDate`. The current inputSchema has no `dateRange`. This cutoff differs from the exact-date contract of profile/distribution/concentration routes. `sampleType=unitSalesTop100|revenueTop100` selects up to 100 Listings. `topN=3|5|10|20` (default 10) and `newProductPeriod=1|3|6|12` (default 3) select dynamic metric aliases; fixed cutoffs/windows remain returned. Page starts at 1, pageSize is 1–100 (default 20). Filters and ordering apply before pagination; meta.total counts matching markets, not products. `filters` has 28 numeric Min/Max pairs, expressed as flat fields, for example `{"avgPriceMin":10,"avgPriceMax":50}`. Bounds are inclusive and finite, either side may be omitted, and min must not exceed max. Nested `{min,max}` metric objects are not the canonical public schema. `sellerCountryCodes` is a list of 1–100 codes (OR); other conditions combine with AND. Sort supports 192 numeric response metrics, independently of the smaller filter set; default avgMonthlyRevenue descending. A sortable metric is not necessarily filterable. Response `data[]` contains flat fields: `totalProductCount`, `totalMonthlySales`, `totalMonthlyRevenue` for the full market; `sampleProductCount`, `sampleMonthlySales`, `sampleMonthlyRevenue` for the sample; `avgMonthlySales`, `avgMonthlyRevenue`, prices, ratings and seller/content metrics. Fixed `top3/5/10/20*`, `totalMonth1/3/6/12NewProduct*`, `sampleMonth1/3/6/12NewProduct*` and selected dynamic aliases remain distinct. Identity is categoryId/name/path, categoryIdPath, includeDescendantCategoryProducts, sampleType, site, currency and `resolvedDate`. Preserve missing paths. No productGrain response field is required. ### Profile, distributions and concentration The eleven profile/distribution/concentration routes accept categoryIds (1–100), includeDescendantCategoryProducts (strict boolean, default true), sampleType (default unitSalesTop100), marketplace=US and optional `date`. Omit date for the latest common publication; an explicit date requires an exact common snapshot, with empty data on an unpublished date. There is no yesterday fallback. Each ID selects an independent market in data[]. Category IDs are nonempty and at most 128 characters; the service deduplicates them. Detail/history/launch inputSchema has no categoryScope or nested scope. Search alone normalizes legacy inputs; such compatibility does not add CLI options or restore old responses. Use current MCP inputSchema when constructing MCP arguments. `profile` returns `marketSize` (full-market productCount, monthlySales, monthlyRevenue and newProductProfile) and `sampleProfile` (sample productCount, monthlySales, monthlyRevenue, avgMonthlySales, avgMonthlyRevenue, price, rating, seller/content measures, newProductProfile and concentrationProfile). Profile has no top-level sample totals. Windows use windowMonths; concentrationProfile arrays are topnProductMetrics, topnBrandMetrics, topnSellerMetrics and topnSellerCountryMetrics, with topN identities. The seven distributions use `priceDistribution`, `ratingDistribution`, `ratingCountDistribution`, `listingAgeDistribution`, `fulfillmentDistribution`, `sellerCountryDistribution` or `contentDistribution`. Each market also returns sampleProductCount, sampleMonthlySales, sampleMonthlyRevenue and `sampleAvgPrice`, `sampleAvgMonthlySales`, `sampleAvgMonthlyRevenue`, `sampleAvgRating`, `sampleAvgRatingCount` at the root. Bucket fields are `bucketProductCount`, `bucketProductRate`, `monthlySales`, `monthlySalesRate`, `monthlyRevenue`, `monthlyRevenueRate`, `avgPrice`, `avgMonthlySales`, `avgMonthlyRevenue`, `avgRating`, `avgRatingCount`. Dimensions have different identifiers/bounds; do not expect a universal buckets object. No bucket new-product or brand-concentration block is provided. Content and seller-country memberships overlap; fulfillment uses the representative bucket with unknowns retained in its denominator. `top-product-concentrations` and `seller-concentrations` use `topnMetrics`; brand also uses `topnMetrics`. Entity arrays are topProductList, topSellerList and topBrandList, at most 20 leading entities. Root sample totals and means use the same sample-prefixed fields as distributions. Top N rows contain productCount, concentrationRate, monthlySales, monthlyRevenue, per-product price/sales/rating means and newProductProfile. All four cutoffs return both sales totals. New-product windows have windowMonths, productCount, monthlySales, monthlyRevenue, monthlySalesRate/monthlyRevenueRate and per-product means. Entity shares use monthlySalesRate/monthlyRevenueRate, named consistently with distribution shares; retain the entity or bucket population when interpreting them. Entity rank follows sampleType; seller-country distributionRank is display order, not a sales rank. concentrationRate follows the sample's ranking metric. Root and nested warehouse fields are optional and nullable. A nested array can be null; an empty data array, a null metric and a real zero are distinct results. ### Listing launch composition `listing-launch-trend` accepts the common market identity and `granularity=month|year` (default month), plus optional `dateFrom` and `dateTo`. These inclusive bounds filter first-launch dates before grouping, not sample snapshot dates; if both are provided, dateFrom must not exceed dateTo. The sample always comes from the latest available snapshot. The request has no `date` property, even date=null is rejected. Response data[] contains site, categoryId, categoryPath/idPath, includeDescendantCategoryProducts, sampleType, granularity and `points[]`. Each point has `date` (YYYY-MM or YYYY) and productCount. There is no returned resolvedDate, snapshotDate or currency. Missing periods are not filled. These are current-sample launch cohorts, not historical market growth or all products launched in those months. `markets/structure-profile` is retired: HTTP 410 with migration guidance, no charge and absent from active discovery. There is no bundled market-structure-profile command. `markets/overview` is absent. ### History `markets/history` takes categoryIds, includeDescendantCategoryProducts, sampleType, marketplace=US and required `dateFrom/dateTo` (valid ordered YYYY-MM-DD). Query boundaries need not be month ends. Only published month-end snapshots inside the range are returned in ascending order. A current-month-only range can be empty because no completed month end is included. There is no date property: even `date=null` is rejected, as is newProductPeriod. Response `data[]` contains series: site, category={id,path,idPath}, includeDescendantCategoryProducts, sampleType, currency and `points[]`. Each point has `date`, `marketSize` and `sampleProfile`. Series are separated by site, category ID and paths, scope, sample type and currency; a path change can yield multiple series for one ID. Empty results return data=[]. Both nested blocks contain productCount, monthlySales and monthlyRevenue for the full market and sample respectively. The sample additionally returns avgPrice, avgMonthlySales, avgMonthlyRevenue and avgRating, avgRatingCount. No min/max price/rating fields, new-product history, distribution history or server MoM/YoY are returned. There is no top-level data.points envelope or history[] field, and no resolvedDateFrom/To; retain requested bounds locally and read actual bounds from each nonempty series' points[].date. Missing months remain absent; old SKU history is never substituted. ### Credits Search costs 1 credit per call, including empty data. Other market reads cost 1 credit per distinct returned market (site/category ID); empty data is free. Their admission check requires balance for the distinct requested market count at the unit price without pre-deducting credits. A batch is not a flat 1-credit call. Use actual meta.creditsConsumed/Remaining and their Exact variants when returned. #### Numeric filter names `avgMonthlySales`, `avgMonthlyRevenue`, `avgRatingCount`, `avgBigBsr30d`, `avgPrice`, `avgRating`, `avgPackageWeightOz`, `avgPackageVolumeIn3`, `totalProductCount`, `topNProductBigCategoryAvgBsr`, `topNProductAvgMonthlySales`, `topNProductAvgMonthlyRevenue`, `sampleBrandCount`, `sellerCount`, `avgSellerCount`, `topNProductMonthlySalesRate`, `topNBrandMonthlySalesRate`, `aPlusProductRate`, `sampleFbaProductRate`, `sampleFbmProductRate`, `sampleAmzProductRate`, `sampleNewProductCount`, `sampleNewProductRate`, `sampleNewProductAvgPrice`, `sampleNewProductAvgRatingCount`, `sampleNewProductAvgRating`, `sampleNewProductAvgMonthlySales`, `sampleNewProductAvgMonthlyRevenue` #### Numeric sort names `totalProductCount`, `sampleProductCount`, `sampleMonthlySales`, `sampleMonthlyRevenue`, `avgMonthlySales`, `avgMonthlyRevenue`, `avgPrice`, `avgBigBsr30d`, `avgRating`, `avgRatingCount`, `avgPackageWeightOz`, `avgPackageVolumeIn3`, `sampleBrandCount`, `sellerCount`, `avgSellerCount`, `aPlusProductRate`, `sampleFbaProductRate`, `sampleFbmProductRate`, `sampleAmzProductRate`, `topNProductAvgMonthlySales`, `topNProductAvgMonthlyRevenue`, `topNProductBigCategoryAvgBsr`, `topNProductMonthlySalesRate`, `topNProductMonthlyRevenueRate`, `topNBrandMonthlySalesRate`, `topNSellerConcentrationRate`, `sampleNewProductCount`, `sampleNewProductRate`, `sampleNewProductAvgPrice`, `sampleNewProductAvgRating`, `sampleNewProductAvgRatingCount`, `sampleNewProductAvgMonthlySales`, `sampleNewProductAvgMonthlyRevenue`, `totalMonth1NewProductCount`, `totalMonth1NewProductRate`, `totalMonth1NewProductMonthlySales`, `totalMonth1NewProductMonthlyRevenue`, `totalMonth3NewProductCount`, `totalMonth3NewProductRate`, `totalMonth3NewProductMonthlySales`, `totalMonth3NewProductMonthlyRevenue`, `totalMonth6NewProductCount`, `totalMonth6NewProductRate`, `totalMonth6NewProductMonthlySales`, `totalMonth6NewProductMonthlyRevenue`, `totalMonth12NewProductCount`, `totalMonth12NewProductRate`, `totalMonth12NewProductMonthlySales`, `totalMonth12NewProductMonthlyRevenue`, `totalMonthlySales`, `totalMonthlyRevenue`, `minPrice`, `maxPrice`, `medianProductPrice`, `avgMonthlyNewRatingCount`, `avgGrossMarginRate`, `aPlusProductCount`, `videoProductCount`, `videoProductRate`, `sampleMonth1NewProductCount`, `sampleMonth1NewProductRate`, `sampleMonth1NewProductMonthlySales`, `sampleMonth1NewProductMonthlySalesRate`, `sampleMonth1NewProductMonthlyRevenue`, `sampleMonth1NewProductMonthlyRevenueRate`, `sampleMonth1NewProductAvgPrice`, `sampleMonth1NewProductAvgRating`, `sampleMonth1NewProductAvgRatingCount`, `sampleMonth3NewProductCount`, `sampleMonth3NewProductRate`, `sampleMonth3NewProductMonthlySales`, `sampleMonth3NewProductMonthlySalesRate`, `sampleMonth3NewProductMonthlyRevenue`, `sampleMonth3NewProductMonthlyRevenueRate`, `sampleMonth3NewProductAvgPrice`, `sampleMonth3NewProductAvgRating`, `sampleMonth3NewProductAvgRatingCount`, `sampleMonth6NewProductCount`, `sampleMonth6NewProductRate`, `sampleMonth6NewProductMonthlySales`, `sampleMonth6NewProductMonthlySalesRate`, `sampleMonth6NewProductMonthlyRevenue`, `sampleMonth6NewProductMonthlyRevenueRate`, `sampleMonth6NewProductAvgPrice`, `sampleMonth6NewProductAvgRating`, `sampleMonth6NewProductAvgRatingCount`, `sampleMonth6NewProductMinRating`, `sampleMonth6NewProductMaxRating`, `sampleMonth12NewProductCount`, `sampleMonth12NewProductRate`, `sampleMonth12NewProductMonthlySales`, `sampleMonth12NewProductMonthlySalesRate`, `sampleMonth12NewProductMonthlyRevenue`, `sampleMonth12NewProductMonthlyRevenueRate`, `sampleMonth12NewProductAvgPrice`, `sampleMonth12NewProductAvgRating`, `sampleMonth12NewProductAvgRatingCount`, `top3ProductConcentrationRate`, `top3ProductProductCount`, `top3ProductBrandCount`, `top3ProductMonthlySales`, `top3ProductMonthlyRevenue`, `top3ProductBigCategoryAvgBsr`, `top3ProductSmallCategoryAvgBsr`, `top5ProductConcentrationRate`, `top5ProductProductCount`, `top5ProductBrandCount`, `top5ProductMonthlySales`, `top5ProductMonthlyRevenue`, `top5ProductBigCategoryAvgBsr`, `top5ProductSmallCategoryAvgBsr`, `top10ProductConcentrationRate`, `top10ProductProductCount`, `top10ProductBrandCount`, `top10ProductMonthlySales`, `top10ProductMonthlyRevenue`, `top10ProductBigCategoryAvgBsr`, `top10ProductSmallCategoryAvgBsr`, `top20ProductConcentrationRate`, `top20ProductProductCount`, `top20ProductBrandCount`, `top20ProductMonthlySales`, `top20ProductMonthlyRevenue`, `top20ProductBigCategoryAvgBsr`, `top20ProductSmallCategoryAvgBsr`, `top3BrandConcentrationRate`, `top3BrandBrandCount`, `top3BrandMonthlySales`, `top3BrandMonthlyRevenue`, `top3BrandProductCount`, `top3BrandBigCategoryAvgBsr`, `top5BrandConcentrationRate`, `top5BrandBrandCount`, `top5BrandMonthlySales`, `top5BrandMonthlyRevenue`, `top5BrandProductCount`, `top5BrandBigCategoryAvgBsr`, `top10BrandConcentrationRate`, `top10BrandBrandCount`, `top10BrandMonthlySales`, `top10BrandMonthlyRevenue`, `top10BrandProductCount`, `top10BrandBigCategoryAvgBsr`, `top20BrandConcentrationRate`, `top20BrandBrandCount`, `top20BrandMonthlySales`, `top20BrandMonthlyRevenue`, `top20BrandProductCount`, `top20BrandBigCategoryAvgBsr`, `top3SellerConcentrationRate`, `top5SellerConcentrationRate`, `top10SellerConcentrationRate`, `top20SellerConcentrationRate`, `top3SellerCountryConcentrationRate`, `top5SellerCountryConcentrationRate`, `top10SellerCountryConcentrationRate`, `top20SellerCountryConcentrationRate`, `top3ProductMonthlySalesRate`, `top3ProductAvgMonthlySales`, `top3ProductMonthlyRevenueRate`, `top3ProductAvgMonthlyRevenue`, `top5ProductMonthlySalesRate`, `top5ProductAvgMonthlySales`, `top5ProductMonthlyRevenueRate`, `top5ProductAvgMonthlyRevenue`, `top10ProductMonthlySalesRate`, `top10ProductAvgMonthlySales`, `top10ProductMonthlyRevenueRate`, `top10ProductAvgMonthlyRevenue`, `top20ProductMonthlySalesRate`, `top20ProductAvgMonthlySales`, `top20ProductMonthlyRevenueRate`, `top20ProductAvgMonthlyRevenue`, `top3BrandMonthlySalesRate`, `top3BrandAvgMonthlySales`, `top3BrandMonthlyRevenueRate`, `top3BrandAvgMonthlyRevenue`, `top5BrandMonthlySalesRate`, `top5BrandAvgMonthlySales`, `top5BrandMonthlyRevenueRate`, `top5BrandAvgMonthlyRevenue`, `top10BrandMonthlySalesRate`, `top10BrandAvgMonthlySales`, `top10BrandMonthlyRevenueRate`, `top10BrandAvgMonthlyRevenue`, `top20BrandMonthlySalesRate`, `top20BrandAvgMonthlySales`, `top20BrandMonthlyRevenueRate`, `top20BrandAvgMonthlyRevenue`, `topNBrandAvgMonthlySales`, `topNBrandAvgMonthlyRevenue`, `topNBrandMonthlyRevenueRate` ## 2a. Market detail routes | Endpoint | CLI command | Data shape | Purpose | |---|---|---|---| | `markets/profile` | `market-profile` | `data[]` | SPU profile | | `markets/price-distributions` | `market-price-distributions` | `data[]` | SPU price-distributions | | `markets/rating-distributions` | `market-rating-distributions` | `data[]` | SPU rating-distributions | | `markets/rating-count-distributions` | `market-rating-count-distributions` | `data[]` | SPU rating-count-distributions | | `markets/listing-age-distributions` | `market-listing-age-distributions` | `data[]` | SPU listing-age-distributions | | `markets/fulfillment-distributions` | `market-fulfillment-distributions` | `data[]` | SPU fulfillment-distributions | | `markets/seller-country-distributions` | `market-seller-country-distributions` | `data[]` | SPU seller-country-distributions | | `markets/content-distributions` | `market-content-distributions` | `data[]` | SPU content-distributions | | `markets/top-product-concentrations` | `market-top-product-concentrations` | `data[]` | SPU top-product-concentrations | | `markets/brand-concentrations` | `market-brand-concentrations` | `data[]` | SPU brand-concentrations | | `markets/seller-concentrations` | `market-seller-concentrations` | `data[]` | SPU seller-concentrations | | `markets/listing-launch-trend` | `market-listing-launch-trend` | `data[]` | SPU listing-launch-trend | ## 2b. markets/history Use the History contract above. --- ## 3. products/competitors | Parameter | Type | Note | |-----------|------|------| | keyword | String | Search keyword | | brand | String | Brand filter | | seller | String | Seller filter | | asin | String | ASIN filter | | categoryPath | List\ | Category filter | | sortBy | String | `monthlySalesFloor` / `monthlyRevenueFloor` / `bsr` / `price` / `rating` / `ratingCount` / `listingDate` | | sortOrder | String | `asc` / `desc` | | pageSize | Integer | default 20 | --- ## 4. products/search Same as competitors, plus: | Parameter | Type | Note | |-----------|------|------| | keywordMatchType | String | `fuzzy` / `phrase` / `exact` | | listingAge | **Enum String** | One of `30d` / `90d` / `180d` / `1y` / `2y` (⚠️ bare numbers like `180` → 422) | Filter pairs (all optional, Min/Max): `monthlySales`, `revenue`, `salesGrowthRate`, `bsr`, `subBsr`, `bsrGrowthRate`, `price`, `rating`, `ratingCount`, `fbaShipping`, `variantCount`, `grossMargin`, `sellerCount` > `mode` is **NOT** an API parameter. The 13 CLI presets in `zoodata.py` expand client-side into the filter pairs above before the request is sent; passing `mode` in a raw request returns 422. Additional: `includeBrands`, `excludeBrands`, `fulfillment` (`["FBA"]`/`["FBM"]`/`["AMZ"]`), `badges` — enum values `["bestSeller"]` / `["amazonChoice"]` / `["newRelease"]` / `["aPlus"]` / `["video"]` (⚠️ `"New Release"` with a space → 422) --- ## 5. realtime/product | Parameter | Required | Note | |-----------|----------|------| | asin | **Yes** | Product ASIN | | marketplace | No | `US`/`UK`/`DE`/`FR`/`IT`/`ES`/`JP`/`CA`/`AU`/`IN`/`MX`/`BR` (default: US) | Response fields: `asin`, `title`, `brand`, `rating`, `ratingCount`, `ratingBreakdown`, `features`, `description`, `specifications`, `categories`, `variants`, `bestsellersRank` (array), `buyboxWinner` (object with price), `images`, `dimensions`, `weight` ⚠️ Does NOT have: `monthlySalesFloor`, `fbaFee`, `sellerCount` --- ## 6. reviews/analysis | Parameter | Type | Required | Note | |-----------|------|----------|------| | mode | String | **Yes** | `asin` or `category` | | asins | List\ | When mode=asin | ⚠️ plural, array format | | categoryPath | String | When mode=category | Category path | | period | String | No | e.g. `6m` | ⚠️ `labelType` is **not** an API request parameter. The API returns all 11 dimensions in one call. Filter by `labelType` client-side from the `consumerInsights` array. Response: `reviewCount`, `avgRating`, `verifiedRate`, `ratingDistribution`, `sentimentDistribution`, `consumerInsights` (list of InsightItem), `topKeywords` InsightItem: `element`, `labelType`, `count`, `reviewRate`, `avgRating` labelType values (in response): `scenarios`, `issues`, `positives`, `improvements`, `buyingFactors`, `painPoints`, `keywords`, `userProfiles`, `usageTimes`, `usageLocations`, `behaviors` --- ## 6b. realtime/reviews | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | **Yes** | Product ASIN (10 chars) | | marketplace | String | No | `US`/`UK` only (default: US) | | cursor | String | No | Pagination token from previous response's `nextCursor`. Omit for first page. | ⚠️ No `pageSize` parameter — server returns 10 reviews/page fixed. Hard cap = **100 reviews / 10 pages**. Cost = **1 credit/page**. Response: `asin`, `reviews` (array of RealtimeReview), `nextCursor` (null = no more pages). RealtimeReview: `reviewId`, `title`, `body`, `bodyHtml`, `rating`, `author`, `date` (ISO 8601), `verifiedPurchase`, `vineProgram`, `helpfulVoteCount`, `unhelpfulVoteCount`, `reviewCountry`, `images`, `link`, `isGlobalReview` Use cases: - ASIN has <50 reviews so `/reviews/analysis` aggregation is empty - Brand-new product with no daily snapshot - Need fresh raw text for local LLM analysis (Map/Reduce → consumerInsights) See `zoodata.py reviews-raw / review-tag-prompt / review-reduce-prompt / review-aggregate` for the local toolkit that consumes this endpoint. --- ## 6c. reviews/search This route is documented for direct API reference only in this release. The bundled CLI has no `reviews/search` subcommand, and this route is not counted in the 36 CLI-backed Amazon commerce and keyword-intelligence endpoints described by the package index. | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | **Yes** | Product ASIN | | ratingMin / ratingMax | Number | No | 1-5 inclusive | | verifiedOnly | Boolean | No | Default false | | vineOnly | Boolean | No | Default false | | helpfulVoteCountMin | Integer | No | Filter low-engagement reviews | | dateStart / dateEnd | Date (YYYY-MM-DD) | No | Inclusive range | | sortBy | String | No | `recent` (default) / `rating` / `helpfulVoteCount` | | sortOrder | String | No | `desc` (default) / `asc` | | page | Integer | No | 1-indexed, default 1 | | pageSize | Integer | No | 1-20, default 10 | Response: array of TaggedReview with AI-generated `tags[{labelType, element}]` derived from the offline analysis pipeline (BigQuery daily snapshot). TaggedReview vs RealtimeReview: `reviews/search` uses snapshot data with AI tags (T+1 delay); `realtime/reviews` is live raw text (no tags). Use `reviews/search` when daily snapshot exists and you want pre-tagged data; use `realtime/reviews` for fresh data or new products. --- ## 7. products/price-band-overview | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | **Yes** | Search keyword | ⚠️ Only accepts `keyword` — does NOT support `categoryPath`. **Response (top-level):** | Field | Type | Note | |-------|------|------| | sampleMedianPrice | Float | Median price across sampled products | | hottestBand | BandObject | Band with highest sales rate | | bestOpportunityBand | BandObject | Band with highest opportunity index | **BandObject:** | Field | Type | Note | |-------|------|------| | bandIdx | Integer | Band index (0-4) | | bandLabel | String | e.g. "$10-$20" | | sampleBandMinPrice | Float | Band minimum price | | sampleBandMaxPrice | Float | Band maximum price | | sampleSkuCount | Integer | Number of SKUs in this band | | sampleSalesRate | Float | Share of total sales in this band | | sampleBrandCount | Integer | Number of brands in this band | | sampleTop3BrandSalesRate | Float | Top 3 brands' share within this band | | sampleAvgRating | Float | Average rating in this band | | sampleOpportunityIndex | Float | Composite opportunity score | --- ## 8. products/price-band-detail | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | **Yes** | Search keyword | ⚠️ Only accepts `keyword` — does NOT support `categoryPath`. **Response:** | Field | Type | Note | |-------|------|------| | sampleSkuCount | Integer | Total sampled SKUs | | sampleTotalMonthlySales | Integer | Total monthly sales across all bands | | priceBands | Array\ | Array of 5 band objects (same structure as §7) | --- ## 9. products/brand-overview | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | **Yes** | Search keyword | ⚠️ Only accepts `keyword` — does NOT support `categoryPath`. **Response:** | Field | Type | Note | |-------|------|------| | sampleBrandCount | Integer | Total number of brands found | | sampleTop10BrandSalesRate | Float | CR10 — top 10 brands' share of total sales | | sampleTop10AvgRating | Float | Average rating of top 10 brands | | sampleTop10AvgPrice | Float | Average price of top 10 brands | --- ## 10. products/brand-detail | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | **Yes** | Search keyword | ⚠️ Only accepts `keyword` — does NOT support `categoryPath`. **Response (top-level):** | Field | Type | Note | |-------|------|------| | sampleSkuCount | Integer | Total sampled SKUs | | sampleTotalMonthlySales | Integer | Total monthly sales | | sampleBrandCount | Integer | Total brands found | | brands | Array\ | Per-brand breakdown | **BrandObject:** | Field | Type | Note | |-------|------|------| | brandName | String | Brand name | | sampleSkuCount | Integer | SKUs for this brand | | sampleGroupMonthlySales | Integer | Monthly unit sales | | sampleGroupMonthlyRevenue | Float | Monthly revenue | | sampleSalesRate | Float | Share of total sales | | sampleAvgPrice | Float | Average price | | minPrice | Float | Lowest price product | | maxPrice | Float | Highest price product | | sampleAvgRating | Float | Average rating | | sampleAvgRatingCount | Integer | Average review count | | sampleProducts | Array\ | Sample products from this brand | **ProductObject** (within sampleProducts): Same fields as Shared Product Object below. --- ## 11. products/history | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | **Yes** | Single ASIN (one per call) | | startDate | String | **Yes** | Start date `YYYY-MM-DD` | | endDate | String | **Yes** | End date `YYYY-MM-DD` | | marketplace | String | No | Marketplace code, default `US` | ⚠️ `asin` is a **single string** — NOT an array. For multiple ASINs, make separate calls. ⚠️ Does NOT support `page`/`pageSize` — returns full date range in one response. ⚠️ Uses `startDate`/`endDate` — NOT `dateRange`. **Response:** Single time series object (NOT an array of snapshots). | Field | Type | Note | |-------|------|------| | asin | String | Product ASIN | | timestamps | List\ | Dates (YYYY-MM-DD) | | price | List\ | Price on each date | | bsr | List\ | BSR on each date | | subBsr | List\ | Sub-category BSR | | monthlySalesFloor | List\ | Monthly sales lower bound | | rating | List\ | Rating on each date | | ratingCount | List\ | Rating count on each date | | sellerCount | List\ | Seller count | | title | List\ | Title changes `{date, value}` | | imageUrl | List\ | Main image changes `{date, value}` | | bestSeller | List\ | Best Seller badge `{date, value}` | | amazonChoice | List\ | Amazon's Choice badge `{date, value}` | | newRelease | List\ | New Release badge `{date, value}` | | aPlus | List\ | A+ content status `{date, value}` | | inventoryStatus | List\ | Stock status `{date, value}` | | currency | String | e.g. `USD` | --- ## Keyword Intelligence Endpoints This reference is a production endpoint whitelist; every listed endpoint must be deployed and callable through the standard production base URL. Tool-surface note: - API documentation and live endpoint availability do not guarantee that the current agent session exposes matching callable tools - For skill execution, verify the live tool surface first; use this file for parameter and field confirmation after that ## 12. /openapi/v2/keywords/detail Keyword value boundary for all keyword endpoints: - The keyword endpoints expose estimated search, SERP visibility, rank, traffic-share, and impression-point signals. - Keyword endpoints are keyword-query workflows; parameters named `keyword` or `query` expect Amazon search query / keyword phrases. - For keyword endpoints that require `date` or `dateTo`, prefer T-1 or earlier and avoid the current date unless the user explicitly asks for today's lookup. - These signals support directional screening and testing priority, but do not 100% prove a keyword's value for a specific ASIN. - Seller-artifact acquisition, stage selection, field interpretation, and output policy are outside this endpoint contract and belong to the `amazon-keyword-traffic-analysis` skill. - All eleven current keyword and product-traffic request schemas retain `granularity` for compatibility. Its only supported value is `week`, and their only supported marketplace is `US`; never send another value or legacy `lookbackDays`. - For batch `keywords[]` on detail, market-profile, trend, trend-profile, and product-traffic-terms-trend, every value must already equal `LOWER(TRIM(value))`; uppercase letters, surrounding whitespace, and duplicates are rejected. The bundled CLI normalizes case and whitespace before sending. | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | Conditional | One keyword; exactly one of `keyword` / `keywords` | | keywords | List\ | Conditional | Batch of 1–20 keywords; preserves request order | | date | String | **Yes** | Lookup date `YYYY-MM-DD`; prefer T-1 or earlier; resolves to the nearest available weekly snapshot at or before that date | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[]` for both single and batch requests. Context fields include marketplace/site, requested/resolved date, weekly granularity, and `dataWindow.currentPeriod`. Each item has `identity`, `status=ok|empty`, `snapshotData`, `emptyReason`, and nullable `errorCode` / `errorMessage`. The latter are auxiliary fields, not status enums. `snapshotData` includes `estimateSearchCount`, `abaRank`, Top3 click/conversion shares, `marketCharacteristics`, `totalSkuCount`, SKU/brand/title coverage, organic/ad counts, and Top48 benchmarks. Do not expect legacy `estimateSearchCountWeekly`, `totalSkuCnt`, or top-level `data:null`. An unmatched keyword is an item with `status=empty` and an `emptyReason`. --- ## 12b. /openapi/v2/keywords/market-profile (metric layer) Availability: standard production endpoint under the documented base URL. A subject-specific calculation failure can return HTTP 500 for the whole batch; treat that as runtime behavior, not an empty item. | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | Conditional | One keyword; exactly one of `keyword` / `keywords` | | keywords | List\ | Conditional | Batch of 1–20 keywords; preserves request order | | date | String | **Yes** | Lookup date `YYYY-MM-DD`; resolves to the latest weekly snapshot on or before this date | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[]` for both single and batch requests. Context fields identify `marketplace`, `site`, `requestedDate`, `resolvedDate`, `granularity`, and `dataWindow.currentPeriod` when available. The current period is the selected snapshot, not the historical range used by annual seasonality. The MCP contract and observed response use a compact response with six graded dimensions (`demandScale`, `top3Concentration`, `top20OrganicEntryDifficulty`, `supplySaturation`, `brandStructure`, `organicProductBenchmark`), raw business evidence in `levelEvidence`, separate `marketProfile.adCoverage`, and `marketProfile.annualSeasonality`. Graded dimensions retain `level` and `interpretation`; no normalized scores are returned. Only available dimensions and evidence are included. An item without a profile contains only `identity`; legacy item `status`, `emptyReason`, support flags, and `scoringSpec` are not prerequisites for this shape. Compact `levelEvidence` field identities (each returned value is a `{value,direction}` pair): | Dimension | Business evidence fields | |---|---| | `demandScale` | `estimatedSearchVolume`, `abaSearchFrequencyRank` | | `top3Concentration` | `abaTop3ClickShare`, `abaTop3ConversionShare` | | `top20OrganicEntryDifficulty` | `organicTop20RolloverMultiplier` | | `supplySaturation` | `searchResultSkuCount`, `observedSkuCount`, `titleKeywordDensity` | | `brandStructure` | `top20RankWeightedBrandHhi`, `top1BrandShare`, `top3BrandShare` | | `organicProductBenchmark` | `top48OrganicAverageRating`, `top48OrganicAverageReviewCount`, `top48OrganicAverageRecentSaleCount` | `adCoverage` contains `adCoverageRate`, `observedAdSkuCount`, and `observedSkuCount` as `{value,direction}` pairs, without a required grade or interpretation. It is not an alias for legacy `adActivity`. Compact annual seasonality can contain only `classification`; do not require unreturned peak evidence. Profile evidence names do not rename fields on `keywords/detail`. The default HTTP surface can still return the legacy score-bearing response: `context.scoringSpec` (`id`, `version`, `scoreType`, `scoreRange`, `referenceScope`), item `status=ok|empty` / `emptyReason`, graded dimensions plus `adActivity` with `supported`, `calculationStatus`, `unsupportedReason`, and `levelEvidence.score.{value,direction}`, and nested `marketCharacteristics.volatility` / `marketCharacteristics.annualSeasonality`. A legacy unavailable item can contain `marketProfile=null`. Read scores with the returned scoring spec only in this shape; do not attach old scores or nested characteristic paths to compact evidence. Identify the response shape from the complete result and the active acquisition surface's contract. Advertising coverage is the fraction of distinct observed products seen in sponsored placements, not spend or impression share. Annual seasonality is a historical estimate independent of a trend window; historical peaks do not imply annual recurrence, `non_seasonal` can include historical peaks, and an empty `peakPeriods` means no peak was identified in available evidence. Use trend-profile for window-specific volatility. This endpoint does not return root cause, recommendations, or seller-private ABA-SQP conversion data. For compact responses, each item containing `marketProfile` costs one credit and identity-only items cost zero. The balance precheck uses requested keyword count; actual usage is in `meta.creditsConsumedExact`. Preserve returned legacy billing metadata as well. A subject-specific calculation error can return HTTP 500 for the entire batch; classify it through the shared CLI contract rather than treating it as an empty item or automatically fanning out the batch. Three-layer boundary: `keywords/detail` is the traceable data layer; `keywords/market-profile` is the stable deterministic metric layer; the Agent + skill layer combines evidence and produces confidence, explanations, limitations, and recommendations. Metric-first rule: use `market-profile` before `detail` for supported market judgments. Do not descend merely because a metric dimension has incomplete calculation coverage; both are source-related, so the missing metric input will usually remain missing. Descend only when a named Agent inference requires raw fields omitted by the metric contract, the metric endpoint is unavailable, or the user requests source evidence. Batch-first rule: once an endpoint is selected, prefer its batch form for all subjects sharing marketplace, date/range, window, filters, and sort context. Deduplicate while preserving order, chunk at 20, and use single calls only for one subject or incompatible contexts. CLI: `zoodata.py keyword-market-profile --keywords "yoga mat,pilates mat" --date 2026-06-29 --marketplace US` --- ## 13. /openapi/v2/keywords/trend | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | Conditional | One keyword; exactly one of `keyword` / `keywords` | | keywords | List\ | Conditional | Batch of 1–20 keywords; preserves request order | | dateFrom | String | **Yes** | Start date `YYYY-MM-DD` | | dateTo | String | **Yes** | End date `YYYY-MM-DD`; prefer T-1 or earlier; maximum 93-day range | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[].series[]` for both single and batch requests. Interpretation note: - `keywords/trend` is a weekly time series. Align returned period boundaries before comparing it with SERP or ASIN observation endpoints; those interfaces are not interchangeable evidence even when all use `week`. Each item has `identity`, `status=ok|empty`, `series[]`, `emptyReason`, and nullable `errorCode` / `errorMessage`. The latter are auxiliary fields, not status enums. Series fields are `periodStartDate`, `periodEndDate`, `estimateSearchCount`, `abaRank`, `abaTop3ClickShareRate`, and `abaTop3ConversionShareRate`. Context range fields are `requestedDateFrom`, `requestedDateTo`, `resolvedDateFrom`, and `resolvedDateTo`. Point boundaries identify returned weekly observations; this endpoint does not return market grading or a precomputed trend profile. --- ## 13b. /openapi/v2/keywords/trend-profile (metric layer) | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | Conditional | Exactly one of `keyword` / `keywords` | | keywords | String[] | Conditional | 1–20, mutually exclusive with `keyword` | | date | String | **Yes** | As-of date `YYYY-MM-DD` | | windowPeriods | Integer[] | **Yes** | 1–4 unique values from `4`, `8`, `12`, `26` | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[].rows[]`. Each keyword has one row per requested window. Rows return `status=ok|empty`, `rowContext`, `emptyReason`, and `trendProfile`. `status=ok` profiles expose guarded `searchDemand` and `abaRank` dimensions. Their `trendEvidence` values include an explicit direction plus slope and consistency evidence, so do not infer the server label from endpoint movement alone. Preserve null empty reasons without inventing one. The component's overall direction is `trend`; `trendPattern` is not a required field. Search-demand components can also return `volatilityLevel` and `lastPeriodWindowPosition`, both scoped to the row's `analysisWindow`. Use this metric endpoint first for trend shape and volatility; call raw `keywords/trend` only when weekly points or omitted fields are required. --- ## 14. /openapi/v2/keywords/extends | Parameter | Type | Required | Note | |-----------|------|----------|------| | query | String | **Yes** | Seed keyword | | marketplace | String | No | Only `US` is supported; default `US` | | page | Integer | No | default 1 | | pageSize | Integer | No | default 20, max 100 | | queryType | String | No | `phrase` / `fuzzy` (default `phrase`) | | sortBy | String | No | `relevanceScore` / `estimateSearchCount` / `abaRank` / `keyword` | | sortOrder | String | No | `asc` / `desc` | | granularity | String | No | Compatibility field; only `week` is supported | ⚠️ Uses `query`, NOT `keyword`. ⚠️ The current MCP schema has no `date` parameter; the service uses the latest available weekly snapshot. The bundled CLI has no `--date` option for this command. ⚠️ Empty `data.rows[]` is a normal success case. **Response:** `data.context + data.query + data.queryType + data.rows[]`. Each row contains `matchData.{query,keyword,site,relevanceScore}` and `keywordSnapshot`. `keywordSnapshot.dataWindow.currentPeriod` provides the resolved weekly period; its metric families match the current `keywords/detail` snapshot contract. Do not flatten the response back to legacy `term`, `seedKeyword`, or `estimateSearchCountWeekly` fields. --- ## 15. /openapi/v2/keywords/search-results | Parameter | Type | Required | Note | |-----------|------|----------|------| | keyword | String | **Yes** | Keyword to inspect | | date | String | **Yes** | Snapshot lookup date `YYYY-MM-DD`; prefer T-1 or earlier | | marketplace | String | No | Only `US` is supported; default `US` | | page | Integer | No | default 1 | | pageSize | Integer | No | default 20, max 100 | | exploreTypes | Array\ | No | `ORG` / `SP` / `SB` / `SBV` / `SPR` | | sortBy | String | No | `absolutePosition` / `estimateImpressionPoint` / `latestObservedAt` / `price` / `rating` / `ratingCount` / `recentSales` / `asin` / `title` | | sortOrder | String | No | `asc` / `desc` | | granularity | String | No | Compatibility field; only `week` is supported | ⚠️ Compatibility-retained `granularity` accepts only `week`; do not send legacy `lookbackDays`. Use the returned weekly period boundaries instead of inferring a rolling window. ⚠️ Use this endpoint as the primary source for "what products are currently showing on the keyword SERP/page 1" because it already returns listing-level product fields. ⚠️ Do not replace it with `products/search` when the question is about observed Amazon keyword SERP composition or ordering. ⚠️ When analyzing this endpoint, separate `exploreType` at least into `ORG` and sponsored placements instead of collapsing all rows together. **Response:** `data.context + data.identity + data.rows[]`. Key row fields: `latestObservedAt`, `exploreType`, `absolutePosition`, `pageIndex`, `pagePosition`, `asin`, `title`, `brand`, `price`, `currency`, `link`, `imageLink`, `rating`, `ratingCount`, `recentSales`, `hasVideo`, `estimateImpressionPoint`, `keywordTotalEstimateImpressionPoint` Interpretation rule: - `keywords/search-results` = observed keyword SERP snapshot - It can answer page-1 product mix, brand mix, ad vs organic composition, and visible price band questions - If you also use `products/search`, present it as a broader catalog supplement, not as the same thing --- ## 16. /openapi/v2/keywords/product-traffic-terms | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | **Yes** | Target ASIN | | date | String | **Yes** | Snapshot lookup date `YYYY-MM-DD`; prefer T-1 or earlier | | marketplace | String | No | Only `US` is supported; default `US` | | page | Integer | No | default 1 | | pageSize | Integer | No | default 20, max 100 | | exploreTypes | Array\ | No | `ORG` / `SP` / `SB` / `SBV` / `SPR` | | keywordContains | String | No | Optional substring filter on returned keywords | | keywordEstimateSearchCountMin | Integer | No | Minimum estimated keyword search count; at least 0 and no greater than the maximum | | keywordEstimateSearchCountMax | Integer | No | Maximum estimated keyword search count; at least 0 and no less than the minimum | | keywordAbaRankMin | Integer | No | Minimum numeric ABA rank; at least 1 and no greater than the maximum | | keywordAbaRankMax | Integer | No | Maximum numeric ABA rank; at least 1 and no less than the minimum | | sortBy | String | No | `trafficShare` / `estimateImpressionPoint` / `absolutePosition` / `avgPosition` / `keywordEstimateSearchCount` / `keywordAbaRank` / `keyword` | | sortOrder | String | No | `asc` / `desc` | | granularity | String | No | Compatibility field; only `week` is supported | ⚠️ The MCP `competitor-product-keywords` tool is retired and returns `tool_retired` with replacement `openapi_v2_product_traffic_terms`. Use this route for any target ASIN, including a competitor. ⚠️ Compatibility-retained `granularity` accepts only `week`; do not send legacy `lookbackDays`; use the returned weekly period boundaries. ⚠️ In skill workflows, this endpoint is a reverse-ASIN source endpoint, not a substitute for `keywords/search-results` when the question is about visible page-1 product composition. **Response:** `data.context + data.identity + data.rows[]`. Key row fields: `latestObservedAt`, `exploreType`, `absolutePosition`, `pageIndex`, `pagePosition`, `asin`, `keyword`, `estimateImpressionPoint`, `asinTotalEstimateImpressionPoint`, `avgPosition`, `daysCoverageRate`, `observationCount`, `keywordEstimateSearchCount`, `keywordAbaRank`, and `trafficShare`. --- ## 17. /openapi/v2/keywords/product-traffic-structure-profile | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | Conditional | One target ASIN; exactly one of `asin` / `asins` | | asins | List\ | Conditional | Batch of 1–20 target ASINs; exactly one of `asin` / `asins` | | date | String | **Yes** | Lookup date `YYYY-MM-DD`; prefer T-1 or earlier | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[]`, preserving ASIN request order. Observed context fields: `marketplace`, `requestedDate`, nullable `resolvedDate`, `granularity`, and `dataWindow.{currentPeriod,previousPeriod}`. Each item contains `identity.{asin,site}`, `status=ok|empty`, `emptyReason`, and nullable `productTrafficTermsProfile`. An unavailable current period returns `status=empty`, `emptyReason=current_period_unavailable`, and `productTrafficTermsProfile=null`; this is a coverage result, not evidence of weak traffic. Billing is per successfully returned ASIN item: each item with `status=ok` is billed once, while an item with `status=empty` is not billed. Use the response's `meta.creditsConsumed` and `meta.creditsConsumedExact` as the authoritative usage record rather than calculating credits from the number of requested ASINs. A non-null `productTrafficTermsProfile` has the following observed structure. Despite the retained response field name, this endpoint is the current-vs-previous-week traffic-structure metric, not a multi-week trend profile: - `summary` - `currEstimateImpressionPoint`, `prevEstimateImpressionPoint` - `impressionPointChangeCount`, `impressionPointChangeRate` - `currTermCount`, `prevTermCount`, `termCountChange`, `termCountChangeRate` - `totalIncreaseImpressionPoint`, `totalDecreaseImpressionPoint` - `trafficStructureChange`: keyed by each traffic type returned by the service. A live response returned `ORG`, `SP`, `SB`, and `SPR`; do not invent an absent channel. Each channel object has `currEstimateImpressionPoint`, `currAsinTrafficShare`, `prevEstimateImpressionPoint`, `prevAsinTrafficShare`, `impressionPointChangeCount`, `impressionPointChangeRate`, `currTermCount`, `prevTermCount`, `termCountChange`, and `termCountChangeRate`. - `organicStructureChange`: `currTermCount`, `prevTermCount`, `termCountChange`, `termCountChangeRate`, `newTermCount`, `lostTermCount`, `newTerms[]`, and `lostTerms[]`. - `termChangeDrivers`: `gainerCount`, `loserCount`, `top10Gainers[]`, and `top10Losers[]`. For this profile's previous-period count, share, and impression-point fields, `null` means the previous weekly data is unavailable. A numeric `0` means the previous weekly period exists but the relevant signal was not observed. Do not coerce `null` to zero or zero to missing data. If `dataWindow.previousPeriod` is null, empty comparison arrays do not establish zero new/lost/gaining/losing terms. The live response used to validate the container structure returned empty arrays, so their item schema remains response-led: preserve fields from a non-empty response and do not invent array-item fields. Treat the object as a server-calculated metric. Preserve its returned modules, channel keys, values, and period scope. Do not read retired flat overview fields or synthesize missing profile modules client-side. Retired routes are intentionally absent from the bundled CLI. Generic HTTP 410 behavior is owned by `cli-contract.md`: preserve the migration response, do not retry, and do not infer a new CLI command from `replacementPath`. --- ## 18. /openapi/v2/keywords/product-traffic-terms-trend | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | **Yes** | Target ASIN | | keyword | String | Conditional | One exact keyword; exactly one of `keyword` / `keywords` | | keywords | List\ | Conditional | Batch of 1–20 exact keywords for the same ASIN | | dateFrom | String | **Yes** | Start date `YYYY-MM-DD` | | dateTo | String | **Yes** | End date `YYYY-MM-DD`; prefer T-1 or earlier; maximum 26-week range | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[].series[]` for both single and batch requests. Each item has `identity`, `status=ok|empty`, `series[]`, `emptyReason`, and nullable `errorCode` / `errorMessage`. The latter are auxiliary fields, not status enums. Each series point contains `date` plus nested `asinSnapshot`, `traffic`, `placement`, `keywordMetrics`, and `adActivity` groups. Exposure-position fields under `placement` are nullable for both unavailable period data and no observed position. A null position does not distinguish those states by itself; inspect returned period boundaries and observation/coverage fields. Never convert a null position to numeric zero. ⚠️ `granularity` accepts only `week`; do not send legacy `lookbackDays`, `page`, `pageSize`, `sortBy`, or `sortOrder`. Diagnosis curves and events: - Price curve: `asinSnapshot.latestPrice` - BSR curve: `asinSnapshot.latestBsr`, `asinSnapshot.latestSubBsr` - Sales curve: `asinSnapshot.latestMonthlySaleCount` - Rating curve: `asinSnapshot.latestRating`, `asinSnapshot.latestRatingCount` - Traffic-estimate curve: `traffic.*` plus `placement.avgOrganicObservation` / `placement.avgAdObservation` - Keyword fields: use `keywordMetrics` only as supporting context for traffic-estimate changes - Listing events: changes in `asinSnapshot.latestTitle` / `asinSnapshot.latestMainImageLink` Key groups: product/listing/rank fields in `asinSnapshot`; ORG/SP/SB/SBV/SPR impression points in `traffic`; positions/pages/observation timestamps in `placement`; `keywordEstimateSearchCount`, `keywordAbaRank`, Top3 shares, and `metricWindow` in `keywordMetrics`; observation/campaign/ad counts in `adActivity`. --- ## 19. /openapi/v2/keywords/product-traffic-trend This is the ASIN-level raw weekly trend across all observed keywords. It has no keyword dimension; use `product-traffic-terms-trend` for one ASIN plus one or more named keywords. | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | Conditional | One target ASIN; exactly one of `asin` / `asins` | | asins | List\ | Conditional | Batch of 1–20 target ASINs; exactly one of `asin` / `asins` | | dateFrom | String | **Yes** | Start date `YYYY-MM-DD` | | dateTo | String | **Yes** | End date `YYYY-MM-DD`; prefer T-1 or earlier; maximum 26-week range | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[].series[]`, preserving ASIN request order. Inspect each item's `status=ok|empty` before reading `series`; missing weeks are not filled with zero. Each weekly series point includes `periodStartDate`, `periodEndDate`, `totalEstimateImpressionPoint`, `organicEstimateImpressionPoint`, `adEstimateImpressionPoint`, `totalTermCount`, `organicTermCount`, `adTermCount`, `organicFirst3PagesTermCount`, `trafficByExploreType[]`, `keywordDemandRankDistribution[]`, and `organicAcquisitionRateDistribution[]`. Impression points are estimated traffic scores, not actual impression counts. Null shares stay unavailable; do not calculate or fill them unless the user asks for a transparent Agent-side calculation. Billing is once per ASIN with `status=ok`; empty items are free. Use returned credit metadata. --- ## 20. /openapi/v2/keywords/product-traffic-trend-profile This is the server-calculated ASIN-level four-week trend metric. Use `product-traffic-trend` when raw weekly points are required and `product-traffic-structure-profile` for current-vs-previous-week structure and driver evidence. | Parameter | Type | Required | Note | |-----------|------|----------|------| | asin | String | Conditional | One target ASIN; exactly one of `asin` / `asins` | | asins | List\ | Conditional | Batch of 1–20 target ASINs; exactly one of `asin` / `asins` | | date | String | **Yes** | As-of date `YYYY-MM-DD`; prefer T-1 or earlier | | windowPeriods | Integer[] | No | Defaults to `[4]`; `[4]` is the only supported value | | detailLevel | String | No | `summary` (default) or `full` | | marketplace | String | No | Only `US` is supported; default `US` | | granularity | String | No | Compatibility field; only `week` is supported | Send `granularity=week` when specifying the compatibility field; the bundled CLI sends it explicitly. **Response:** `data.context + data.items[].rows[]`, preserving ASIN request order. Read row `status=ok|empty`, then each component's `supported`, `calculationStatus`, and `unsupportedReason`. A successful row contains `trafficTrendProfile`; summary mode covers `asinTotalTraffic`, `organicTraffic`, `adTraffic`, and `termCoverage`, while full mode may add placement and distribution breakdowns. `detailLevel` changes response detail only, not query scope or billing. Each component returns the server's `trend`, `volatilityLevel`, `lastPeriodWindowPosition`, and `trendEvidence`. Treat `trend` as the conclusion for the resolved four-week window, not as a forecast or causal explanation. Share changes are absolute decimal differences (for example, `0.05` means five percentage points); change rates are relative. Normalized-slope magnitudes are not comparable across ASINs and are not percentage growth. Billing is once per ASIN with at least one `status=ok` row; empty-only ASINs are free. Use returned credit metadata. --- ## Shared Product Object (products/search, competitors & brand-detail sampleProducts) Boundary note: - `products/search` is a query against ZooData's product-database snapshot - It is useful for broader catalog analysis such as market winners, sales distribution, price bands, and variant concentration - It does NOT represent Amazon live keyword SERP ordering - Do not describe `products/search` output as "Amazon search results" or "Amazon首页结果" unless you are explicitly talking about the ZooData product database rather than the observed Amazon keyword SERP | Field | Type | Note | |-------|------|------| | asin | String | | | title | String | | | brand | String | | | price | Float | Top-level (unlike realtime) | | bsr | Integer | BSR rank (NOT `bsr` or `bestsellersRank`) | | monthlySalesFloor | Integer | Lower-bound monthly sales | | monthlyRevenueFloor | Float | Monthly revenue lower bound | | salesGrowthRate | Float | Growth rate | | rating | Float | 0-5 | | ratingCount | Integer | NOT `reviewCount` | | fbaFee | Float | | | sellerCount | Integer | | | variantCount | Integer | | | fulfillment | String | FBA/FBM/AMZ | | listingDate | String | | | buyBoxSellerName | String | | | categoryPath | List | Full category path root→leaf; always present — lets a keyword→category lookup resolve from the search row without a realtime call | | bsrCategory | String | BSR category name (root); fallback when `categoryPath` is absent |