# Overview Source: https://env.7xmtools.com/api-docs/ Everything you need to integrate Keepa data into your application: how to get access, make your first request, and where each endpoint and response object is documented. Token-based access · JSON responses The Keepa API delivers Keepa's data on Amazon marketplaces straight to your application: complete price histories, detailed product data, marketplace offers, deals, best seller lists and seller information — plus tracking, which notifies you with updated price data for the products you select. All requests are issued over HTTPS and every response is JSON. Find out more about the API on [keepa.com](https://env.7xmtools.com/api). Base URL: `https://api.keepa.com/` ## Quick start ### 1. Get an API key Subscribe to an API plan at [keepa.com/api](https://env.7xmtools.com/api). Every request requires your API access key as a parameter; you can view and change your key on the [API page](https://env.7xmtools.com/api) of your Keepa account. ### 2. Make your first request All requests are issued over HTTPS and must accept gzip encoding; [zstd is supported as well](https://env.7xmtools.com/api-docs/request-basics.html#compression) and recommended. GET works for every endpoint; endpoints that take a large JSON query ([Product Finder](https://env.7xmtools.com/api-docs/product-finder.html), [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html), [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html), [Add Tracking](https://env.7xmtools.com/api-docs/tracking.html#add-tracking)) also accept POST. If possible, use a Keep-Alive connection; multiple requests can be made in parallel to increase throughput. The following request fetches product data and price history for one ASIN on amazon.com (`domain=1`): **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { if (result.status == ResponseStatus.OK) { System.out.println(result.products[0].title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { echo $response->products[0]->title; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS"} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() print(data["products"][0]["title"]) print("Tokens left:", data["tokensLeft"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS"); const data = await res.json(); console.log(data.products[0].title); console.log("Tokens left:", data.tokensLeft); ``` **cURL** ```bash curl -s --compressed "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS" ``` Every response is JSON and always includes the current state of your token bucket alongside the payload: ```json { "refillRate": 5, "refillIn": 41260, "tokensLeft": 295, "tokensConsumed": 1, "tokenFlowReduction": 0.0, "processingTimeInMs": 32, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Product Title" } ] } ``` *Response shortened for readability; illustrative values.* Details on the response format, the token bucket fields and the possible HTTP status codes are covered in [Making Requests](https://env.7xmtools.com/api-docs/request-basics.html). ### 3. Understand tokens API access is metered with a token bucket: your plan generates a fixed number of tokens per minute (24/7, whether you make requests or not), and each request consumes tokens — for example, one token per requested product. This allows request bursts and a constant request rate throughout your plan's duration. Every response tells you how many tokens you have left (`tokensLeft`) and when the bucket refills (`refillIn`), so you can plan your requests. > **Important:** Unused tokens expire after 60 minutes. Read [Plans & Tokens](https://env.7xmtools.com/api-docs/plans-tokens.html) for how plans, subscriptions and token costs work in detail. ## Endpoints The API offers numerous endpoints, each documented on its own page. All paths are relative to the base URL `https://api.keepa.com/`. | Endpoint | Path | Token cost | Description | | --- | --- | --- | --- | | [Product Request](https://env.7xmtools.com/api-docs/product.html) | `/product` | 1 token per product (more with optional parameters) | Retrieve products, including price history, by ASIN or product code. | | [Product Search](https://env.7xmtools.com/api-docs/product-search.html) | `/search?type=product` | 10 tokens per search (up to 20 results) | Search for Amazon products by keyword. | | [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html) | `/query` | 10 + 1 per 100 ASINs | Query the product database with complex filter criteria. | | [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) | `/deal` | 5 tokens per request (up to 150 deals) | Browse recent price drops and deals. | | [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) | `/bestsellers` | 50 tokens per request | Retrieve the best sellers list of a category. | | [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html) | `/category` | 1 token per request (up to 10 categories) | Look up category objects by category ID. | | [Category Search](https://env.7xmtools.com/api-docs/category-search.html) | `/search?type=category` | 1 token per search | Search for Amazon categories by name. | | [Seller Information](https://env.7xmtools.com/api-docs/seller.html) | `/seller` | 1 token per seller (+9 for storefront) | Retrieve information about marketplace sellers. | | [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html) | `/sellerquery` | 10 + 1 per 100 seller IDs | Query the seller database with complex filter criteria. | | [Most Rated Sellers](https://env.7xmtools.com/api-docs/most-rated-sellers.html) | `/topseller` | 50 tokens per request | Retrieve the list of most rated marketplace sellers. | | [Lightning Deals](https://env.7xmtools.com/api-docs/lightning-deals.html) | `/lightningdeal` | 1 token per ASIN · 500 tokens for the full list | Retrieve Amazon lightning deals. | | [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html) | `/graphimage` | 1 token per image | Render price history charts as images. | | [Tracking API](https://env.7xmtools.com/api-docs/tracking.html) | `/tracking` | varies per tracked product | Create and manage product trackings and receive notifications. | Each endpoint page documents its token cost in detail, including the options that change it. ## Response objects All objects returned by API requests are explained on the following pages. - [Product Object](https://env.7xmtools.com/api-docs/product-object.html): The core object with product data and price history for a single ASIN. - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html): Pre-computed statistics for a product, returned on request with product data. - [Marketplace Offer Object](https://env.7xmtools.com/api-docs/offer-object.html): A single marketplace offer of a product, including seller and condition. - [Category Object](https://env.7xmtools.com/api-docs/category-object.html): An Amazon category node as returned by category lookups and searches. - [Deal Object](https://env.7xmtools.com/api-docs/deal-object.html): A price-drop entry returned by the Browsing Deals request. - [Best Sellers Object](https://env.7xmtools.com/api-docs/best-sellers-object.html): The ranked ASIN list of a category's best sellers. - [Seller Object](https://env.7xmtools.com/api-docs/seller-object.html): Information about a marketplace seller. - [Lightning Deal Object](https://env.7xmtools.com/api-docs/lightning-deal-object.html): State and timing of an Amazon lightning deal. - [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html): Search insights data returned by the API. - [Tracking Object](https://env.7xmtools.com/api-docs/tracking-object.html): Represents an active product tracking. - [Tracking Creation Object](https://env.7xmtools.com/api-docs/tracking-creation-object.html): The object submitted to the Tracking API to create a new tracking. - [Notification Object](https://env.7xmtools.com/api-docs/notification-object.html): A notification event fired by one of your trackings. ## Official clients & libraries Keepa provides clients for [Java](https://github.com/keepacom/api_backend) and [PHP](https://packagist.org/packages/keepa/php_api) for fast integration. Even if you do not use Java or PHP, these resources might still be helpful for insights and examples. There is also a community-developed [Python client](https://github.com/akaszynski/keepa) available. | Library | Maintainer | Where | | --- | --- | --- | | Java client | Keepa (official) | [github.com/keepacom/api\_backend](https://github.com/keepacom/api_backend) | | PHP client | Keepa (official) | [packagist.org/packages/keepa/php\_api](https://packagist.org/packages/keepa/php_api) | | Python client | Community | [github.com/akaszynski/keepa](https://github.com/akaszynski/keepa) | ## AI assistants (MCP) Not writing code at all? Keepa also operates a hosted [MCP Server](https://env.7xmtools.com/api-docs/mcp.html) that hands AI assistants like Claude the same data directly — price histories, deals and seller information — authenticated with the same API key, metered by the same tokens, with nothing to install. For an assistant that writes code against the API, these docs come as Markdown too: start with the [quick reference](https://env.7xmtools.com/api-docs/quick-reference.md) or [llms.txt](https://env.7xmtools.com/api-docs/llms.txt). > **Note:** Plans, pricing and your personal API access key are managed in your [Keepa API dashboard](https://env.7xmtools.com/api). # Making Requests Source: https://env.7xmtools.com/api-docs/request-basics.html Everything you need to call the Keepa API: the base URL, your access key, transport requirements (HTTPS, gzip or zstd, keep-alive), the token-bucket information included in every JSON response, and the possible HTTP status codes. HTTPS GET · POST (selected endpoints) The Keepa API offers numerous endpoints, which are explained on the individual pages of this documentation (see the **Endpoints** section in the sidebar, or the [overview](https://env.7xmtools.com/api-docs/index.html)). ## Official API Clients Keepa provides clients for [Java](https://github.com/keepacom/api_backend) and [PHP](https://packagist.org/packages/keepa/php_api) for fast integration. Even if you do not use Java or PHP, these resources might still be helpful for insights and examples. There is also a community-developed [Python client](https://github.com/akaszynski/keepa) available. ## Price Plans Requests consume tokens from your subscription's token bucket. Find out how the Keepa API price plans and the token system work on the [Plans & Tokens](https://env.7xmtools.com/api-docs/plans-tokens.html) page. ## Request Basics ``` GET https://api.keepa.com/?key=& ``` | Aspect | Requirement | | --- | --- | | **Base URL** | `https://api.keepa.com/` | | **API Access Key** | Every request requires your API access key as a parameter (`key`). You can find and change your key [on the Keepa website](https://env.7xmtools.com/api). | | **HTTP Method** | All requests are issued over **HTTPS** and must accept **gzip** encoding; **zstd** is supported as well and recommended (see [Response compression](https://env.7xmtools.com/api-docs/request-basics.html#compression)). **GET** works for every endpoint. Endpoints that take a large JSON query — [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html), [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html), [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) and [Add Tracking](https://env.7xmtools.com/api-docs/tracking.html#add-tracking) — additionally accept **POST**, which avoids URL-encoding the query and the URL length limit. If possible, use a **Keep-Alive** connection. | | **Parallel Requests** | Multiple requests can be made in parallel to increase throughput. | ### Response compression Responses are always compressed. **gzip** is the baseline that every client must support; **zstd** is supported as well and is the recommended choice — it is smaller than gzip and faster to decompress. The coding is selected from the `Accept-Encoding` request header: - Send `Accept-Encoding: gzip, zstd` to receive zstd. The token must be listed explicitly — a wildcard (`*`) does not enable it, and `zstd;q=0` is honored as a refusal. - Anything else, including no `Accept-Encoding` header at all, is served gzip. Always decode based on the `Content-Encoding` response header rather than assuming a coding: a request that advertises zstd can still be answered with gzip. Most HTTP clients handle both transparently (curl with `--compressed`, Python `requests`, browser `fetch`); older ones may need an extra package for zstd (for example `pip install "urllib3[zstd]"`). If your client cannot decode zstd, simply keep advertising `gzip` only. ## Response Format The response is always in **JSON** format. Every response will contain information about your current API access: ```json { "refillRate": Integer, "refillIn": Integer, "tokensLeft": Integer, "tokensConsumed": Integer, "tokenFlowReduction": Double, "processingTimeInMs": Integer, "error": { "type": String, "message": String, "details": String } } ``` ### Response fields | Field | Type | Description | | --- | --- | --- | | `refillRate` | Integer | Number of tokens generated by your active subscriptions. | | `refillIn` | Integer | Time in milliseconds until your token bucket will be refilled (happens every minute). | | `tokensLeft` | Integer | How many tokens you currently have left. This value can be negative, as requests are always executed as long as there is a positive token balance when the request is submitted. | | `tokensConsumed` | Integer | Number of tokens this request consumed. | | `tokenFlowReduction` | Double | Tracking products through the API reduces your actual token refill rate by this value (rounded to an integer). | | `processingTimeInMs` | Integer | Time the request's server side processing took, in milliseconds. | | `error` | Object | Contains error information (`type`, `message`, `details` — all String). Only set if an error occurred. An error does not mean the whole request failed (e.g., batch requests). | > **Note:** You can use this information to plan your requests. **Unused tokens will expire after 60 minutes.** ## Possible HTTP Status Codes | Code | Status | Meaning | | --- | --- | --- | | `200` | OK | The request was successfully executed. | | `400` | Bad Request | The request was malformed or could not be successfully executed. | | `402` | Payment Required | The used API key does not grant access. | | `405` | Method Not Allowed | A request parameter is out of the allowed range. | | `429` | Too Many Requests | You are out of tokens. | | `500` | Internal Server Error | An unexpected error occurred when executing this request. | > **Note:** For any status code other than 200, you will still receive the token bucket information in the error stream. The remainder of the response varies and is explained on the individual endpoint pages. ## Examples A good first request is a minimal [Product Request](https://env.7xmtools.com/api-docs/product.html) for a single ASIN: it costs a single token and — like every API response — returns your current token status in the response envelope, so you can verify that your key works and see how many tokens you have left. ```bash https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { if (result.status == ResponseStatus.OK) { System.out.println(result.products[0].title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { echo $response->products[0]->title; } ``` **Python** ```python import requests # A Session reuses the connection (keep-alive); requests decodes gzip transparently. session = requests.Session() params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS"} r = session.get("https://api.keepa.com/product", params=params) data = r.json() print("Tokens left:", data["tokensLeft"]) print("Title:", data["products"][0]["title"]) ``` **Node.js** ```javascript // fetch keeps the connection alive and handles gzip automatically. const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS"); const data = await res.json(); console.log("Tokens left:", data.tokensLeft); console.log("Title:", data.products[0].title); ``` **cURL** ```bash curl -s --compressed "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS" ``` ### Example response Every response starts with the token bucket envelope described above; the endpoint's payload (here: the `products` array of the Product Request) follows alongside it. The `error` field is absent because no error occurred. ```json { "processingTimeInMs": 32, "tokensLeft": 279, "refillIn": 41565, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 1, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Product, 16 oz" } ] } ``` *Response shortened for readability; illustrative values.* See the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) for the full payload structure. ### Example error response If a request fails (any status code other than 200), the token bucket information is still delivered in the error stream, together with the `error` object. In this example the token balance is exhausted, so the request is answered with HTTP `429 - Too Many Requests`. Note that `tokensLeft` can be negative: ```json { "processingTimeInMs": 2, "tokensLeft": -3, "refillIn": 12844, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 0, "error": { "type": "documentationExample", "message": "You are out of tokens.", "details": "Wait until your token bucket refills." } } ``` *Illustrative values — the actual error `type`, `message` and `details` strings vary by endpoint and error condition.* ## Additional Information - **Available Requests:** [View all available requests](https://env.7xmtools.com/api-docs/index.html#endpoints) # Plans & Tokens Source: https://env.7xmtools.com/api-docs/plans-tokens.html Keepa API plans are rate-limited with a token bucket: every plan generates a fixed number of tokens per minute, and each API request consumes tokens. This page explains the token model, subscription billing, and the token cost of each request type. Token bucket rate limiting ## How Plans Work Keepa's [API plans](https://env.7xmtools.com/api/pricing) are all billed monthly in advance and continue from one billing period to the next until canceled. A subscription can be canceled at any time. Access to the API is limited via the [token bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket). This allows request bursts as well as a constant rate of requests throughout the plan's duration — it is not possible to use up the whole contingent by accident. The plans differentiate by the **number of tokens that are generated per minute**. Unused tokens **expire after 60 minutes**. ## The Token Bucket Model Your plan continuously adds tokens to a bucket. Because each token is valid for 60 minutes, the bucket can hold at most *rate × 60* tokens at any time. Every API request removes tokens from the bucket; tokens that sit unused for 60 minutes expire. *The token bucket: constant token generation, limited bucket capacity, expiry of unused tokens.* ### Example: the 60 tokens per minute plan The *60 tokens per minute* plan generates 60 tokens every minute, and each token is valid for 60 minutes — so the token bucket capacity is 3,600 tokens. The tokens are generated 24/7, whether you are making requests or not. Each requested product consumes one token. If you were to use every generated token throughout a 31-day month of the plan, you could request a total of **2,678,400 products**. | Property | 60 tokens per minute plan | | --- | --- | | Token generation | 60 tokens every minute, 24/7 (whether you make requests or not) | | Token lifetime | 60 minutes (unused tokens expire) | | Bucket capacity | 60 × 60 = **3,600 tokens** (also the maximum burst you can spend at once) | | Cost per requested product | 1 token | | Maximum products in a 31-day month | 60 × 60 × 24 × 31 = **2,678,400** | > **Note:** Some API requests require different amounts of tokens — the costs are listed in the [Token Costs by Request Type](https://env.7xmtools.com/api-docs/plans-tokens.html#token-costs) section below and on the individual endpoint pages. ## Managing Your Subscription ### Cancel A subscription can be canceled at any time through your [dashboard](https://env.7xmtools.com/api). Once canceled, it is scheduled to be terminated at the end of its period. > **Note:** A canceled subscription keeps running until the end of the period you already paid for. Until then you can **resume** it from your dashboard, and billing continues as before. Once the period has ended and the subscription has expired, it can no longer be reactivated — you then have to subscribe to a new plan. ### Upgrade / Downgrade Subscriptions can be changed by switching the plan. You can **upgrade** your subscription level at any time. A **downgrade** is possible as well, but only once every 28 days. The new plan will be active immediately. Your billing cycle will remain the same, and you will be immediately charged a prorated amount in case of an upgrade, or receive a credit to your Keepa account in case of a downgrade (no refund possible). **Example:** You are billed on the 1st of each month and upgrade your subscription exactly half-way through the plan's billing cycle (i.e., on the 15th of March). In that case, you have already been charged the full monthly cost of 10 EUR of your existing plan and used half of the current billing cycle. When you switch to the new plan, with a higher cost of 25 EUR, the unused portion of the previous plan results in a credit of 5 EUR. The cost of the new plan for the rest of the billing cycle (i.e., the rest of March) will be 12.50 EUR. Therefore, the total prorated cost of switching from the cheaper plan to the more expensive plan is **7.50 EUR**. This amount will be charged immediately. | Proration item (upgrade on 15 March) | Amount | | --- | --- | | Credit for the unused half of the old plan (10 EUR/month) | −5.00 EUR | | New plan (25 EUR/month) for the remaining half of March | +12.50 EUR | | **Charged immediately** | **7.50 EUR** | ### Multiple subscriptions Instead of upgrading an existing subscription, you can subscribe to an additional plan. All subscriptions will be active simultaneously, and each subscription will have its own billing cycle and billing information, but they share the same payment method and API key. ## Payment Keepa accepts payments via credit card through the payment provider [Stripe.com](https://stripe.com/). Keepa never has access to your full credit card information. If you require other forms of payment, please contact [info@keepa.com](mailto:info@keepa.com). Keepa does not offer discounts. ## Dashboard Once you have purchased a plan, you can use the [API page](https://env.7xmtools.com/api) to: - view the status of your API access, - manage your subscription, - change your payment and billing details, - generate a new API access key, - retrieve receipts (invoices). ## Token Costs by Request Type The available requests and their token costs: | Request | Token cost | | --- | --- | | [Product Request](https://env.7xmtools.com/api-docs/product.html) | 1 token per product (more with optional parameters) | | [Product Search](https://env.7xmtools.com/api-docs/product-search.html) | 10 tokens per search (up to 20 results) | | [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html) | 10 + 1 per 100 ASINs | | [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) | 5 tokens per request (up to 150 deals) | | [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) | 50 tokens per request | | [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html) | 1 token per request (up to 10 categories) | | [Category Search](https://env.7xmtools.com/api-docs/category-search.html) | 1 token per search | | [Seller Information](https://env.7xmtools.com/api-docs/seller.html) | 1 token per seller (+9 for storefront) | | [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html) | 10 + 1 per 100 seller IDs | | [Most Rated Sellers](https://env.7xmtools.com/api-docs/most-rated-sellers.html) | 50 tokens per request | | [Lightning Deals](https://env.7xmtools.com/api-docs/lightning-deals.html) | 1 token per ASIN · 500 tokens for the full list | | [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html) | 1 token per image | | [Tracking API](https://env.7xmtools.com/api-docs/tracking.html) | varies per tracked product | > **Tip:** Each endpoint page documents its token cost in detail, including options that change the cost (for example, requesting marketplace offers with a product). ## Examples ### Will my workload fit a plan? Since tokens are generated 24/7 at a fixed rate, the monthly token budget of a plan is simply `rate × 60 × 24 × days`. Combine that with the token costs above to check whether a planned workload fits a plan (illustrative calculation): ```python # Will a "60 tokens per minute" plan cover my monthly workload? RATE = 60 # tokens generated per minute (plan tier) tokens_per_month = RATE * 60 * 24 * 31 # 2,678,400 tokens in a 31-day month # Planned monthly workload (costs from the token cost table): products = 1_500_000 * 1 # product requests: 1 token per ASIN offer_pages = 120_000 * 6 # offer pages: 6 tokens per found offer page deal_batches = 2_000 * 5 # browsing deals: 5 tokens per 150 deals best_sellers = 30 * 50 # best sellers lists: 50 tokens per list needed = products + offer_pages + deal_batches + best_sellers print(f"Plan budget: {tokens_per_month:,} tokens/month") # 2,678,400 print(f"Workload: {needed:,} tokens/month") # 2,231,500 print("Fits!" if needed <= tokens_per_month else "Upgrade needed.") ``` Remember the burst limit: because unused tokens expire after 60 minutes, the bucket never holds more than `rate × 60` tokens (3,600 on the 60/min plan), so a burst larger than that has to be spread out over time while tokens refill. ### Checking your token balance Every API response includes the current status of your token bucket, so you can monitor your balance with any request — for example a [product request](https://env.7xmtools.com/api-docs/product.html), which consumes 1 token per ASIN. See [Making Requests](https://env.7xmtools.com/api-docs/request-basics.html) for the full response envelope. ``` GET https://api.keepa.com/product?key=&domain=&asin= ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { if (result.status == ResponseStatus.OK) { System.out.println(result.products[0].title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { echo $response->products[0]->title; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS"} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() print(f"Tokens left: {data['tokensLeft']} (refill rate: {data['refillRate']}/min)") ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS"); const data = await res.json(); console.log(`Tokens left: ${data.tokensLeft} (refill rate: ${data.refillRate}/min)`); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS" ``` ### Example response ```json { "processingTimeInMs": 16, "tokensLeft": 3487, "refillIn": 21000, "refillRate": 60, "tokenFlowReduction": 0.0, "tokensConsumed": 1, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Product Title" } ] } ``` Response shortened for readability; illustrative values. `tokensLeft` is your current bucket balance, and `refillRate` is your plan's tokens-per-minute rate — the fields are documented on the [Making Requests](https://env.7xmtools.com/api-docs/request-basics.html) page. # MCP Server Source: https://env.7xmtools.com/api-docs/mcp.html Put Keepa's Amazon data in the hands of AI assistants like Claude and ChatGPT through the hosted Model Context Protocol server. Nothing to install — sign in with your Keepa account or connect with your API key, and your assistant can research prices, deals, sellers and products on its own. MCP · Streamable HTTP · Uses your plan's tokens The [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) is an open standard that lets AI assistants call external tools. Keepa operates an official MCP server, **fully hosted**: there is nothing to download, install or update — clients connect to `https://env.7xmtools.com/mcp`, sign in with your Keepa account or send your Keepa API access key, and new server versions are live the moment they are deployed. You need an active [Keepa API subscription](https://env.7xmtools.com/api/pricing) or Keepa Pro. Pro includes a small API allowance, enough to try the server; an API plan sets the rate for regular use. Your access key is shown on the [API page](https://env.7xmtools.com/api) of your Keepa account. Tool calls consume the same [tokens](https://env.7xmtools.com/api-docs/plans-tokens.html) as direct API requests. ## Connect your AI assistant ``` POST https://env.7xmtools.com/mcp ``` The endpoint speaks MCP over Streamable HTTP and accepts two kinds of authentication: a **sign-in with your Keepa account** (OAuth), which assistants with a connector screen such as Claude and ChatGPT use, and your **API access key** sent as a Bearer token, `Authorization: Bearer YOUR_API_KEY`, for clients set up through a configuration file or the command line. ### Sign in with your Keepa account Add `https://env.7xmtools.com/mcp` as a custom connector and leave any client ID or secret fields empty. The assistant opens a keepa.com page that names the app and asks for your approval — log in there first if you are not logged in. After you approve, you return to the assistant and the connector is ready. - **Claude** (claude.ai and the Claude apps): Settings ▸ Connectors ▸ Add custom connector, enter the URL, then Connect. On Team and Enterprise plans an owner adds the connector for the organization first. - **ChatGPT**: custom connectors need developer mode, which you turn on under Settings ▸ Apps & Connectors ▸ Advanced settings. Then create a connector with the URL above and OAuth as authentication. Availability depends on your ChatGPT plan. - **Claude Code**: `claude mcp add --transport http keepa https://env.7xmtools.com/mcp`, then run `/mcp` in a session, choose *keepa* and Authenticate. What approving means: - The app uses Keepa through your API access, so your account needs an active API subscription or Keepa Pro, and every tool call uses your tokens. - The app never sees your password or your API key. Generating a new API key leaves connected apps working. - You can disconnect an app at any time on the [API page](https://env.7xmtools.com/api) under *Connected apps*. Changing your password disconnects all of them. ### Quick setup by client For clients set up with your API key — each tab shows the complete, verified setup. Replace `YOUR_API_KEY` with your Keepa API access key. **Claude Code** ```bash claude mcp add --transport http keepa https://env.7xmtools.com/mcp --header "Authorization: Bearer YOUR_API_KEY" ``` **Claude Desktop** ```json // Claude ▸ Settings… ▸ Developer ▸ Edit Config — claude_desktop_config.json // (bridges via the mcp-remote package; requires Node.js. Restart Claude Desktop afterwards.) { "mcpServers": { "keepa": { "command": "npx", "args": ["-y", "mcp-remote", "https://env.7xmtools.com/mcp", "--transport", "http-only", "--header", "Authorization:${AUTH_HEADER}"], "env": { "AUTH_HEADER": "Bearer YOUR_API_KEY" } } } } ``` **Cursor** ```json // ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project) { "mcpServers": { "keepa": { "url": "https://env.7xmtools.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` **VS Code** ```json // .vscode/mcp.json — VS Code asks for the key on first start and stores it encrypted { "inputs": [ { "type": "promptString", "id": "keepa-api-key", "description": "Keepa API key", "password": true } ], "servers": { "keepa": { "type": "http", "url": "https://env.7xmtools.com/mcp", "headers": { "Authorization": "Bearer ${input:keepa-api-key}" } } } } ``` **Gemini CLI** ```bash # -s user = save in ~/.gemini/settings.json (omit for per-project scope) gemini mcp add -s user --transport http --header "Authorization: Bearer YOUR_API_KEY" keepa https://env.7xmtools.com/mcp ``` **Windsurf** ```json // ~/.codeium/windsurf/mcp_config.json { "mcpServers": { "keepa": { "serverUrl": "https://env.7xmtools.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` **Codex CLI** ```bash # Codex reads the key from the KEEPA_API_KEY environment variable — # it is never written into the config file codex mcp add keepa --url https://env.7xmtools.com/mcp --bearer-token-env-var KEEPA_API_KEY ``` **Cline** ```json // Cline panel ▸ MCP Servers ▸ Configure. The type string must be exactly "streamableHttp" // (Roo Code uses the same shape with "type": "streamable-http") { "mcpServers": { "keepa": { "type": "streamableHttp", "url": "https://env.7xmtools.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` **Other** ```json // Any MCP client with Streamable HTTP + custom header support. // Most read a JSON configuration in this common shape (file name and exact keys vary per client): { "mcpServers": { "keepa": { "type": "http", "url": "https://env.7xmtools.com/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` > **Tip:** Where possible, keep the key out of config files that might be committed or shared: VS Code prompts for it (`inputs`), Codex CLI reads it from an environment variable, and Cursor, Windsurf and Gemini CLI support `${env:…}`-style interpolation inside `headers`. > **Note:** Claude Desktop can also skip the configuration file: its connector screen signs in with your Keepa account as described [above](https://env.7xmtools.com/api-docs/mcp.html#sign-in). > **Important:** Your API key is a secret. Client configurations that embed it (for example a checked-in `.mcp.json`) must not be committed to shared repositories or otherwise published. Anyone with the key can spend your tokens. ## What your assistant can do Once connected, the assistant can look up products with prices, statistics and Buy Box data, walk decoded price histories, render Keepa charts, search Amazon, run [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html) and [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html) database queries, browse recent price drops and Lightning Deals, pull category best sellers, inspect sellers and their storefronts, and manage price trackings with notifications. It can answer questions like *"How has the Buy Box price of this ASIN developed over the last year?"* or *"Find me kitchen products whose price dropped at least 30% this week"* by calling the Keepa API itself. Every tool description states its token cost and every response carries your current balance, so a connected assistant paces its own spending — the balance it spends is your plan's. Responses are deliberately shaped for language models rather than for programs; if you are writing code against Keepa data, use the [REST API](https://env.7xmtools.com/api-docs/request-basics.html) directly. ## These docs for your assistant If an assistant writes code against the API, or answers questions about it, point it at these Markdown versions of this documentation, made for reading by tools: - [Quick reference](https://env.7xmtools.com/api-docs/quick-reference.md): every endpoint with its method, path, token cost and parameters, in one file. - [llms.txt](https://env.7xmtools.com/api-docs/llms.txt): an index of every page, following the [llms.txt](https://llmstxt.org/) convention; [llms-full.txt](https://env.7xmtools.com/api-docs/llms-full.txt) holds all pages in one file. - Each page as Markdown: the **Markdown** link at the top of every page opens it, and **Copy as Markdown** puts it on the clipboard to paste into a chat. # API Changelog Source: https://env.7xmtools.com/api-docs/changelog.html A record of additions, changes and deprecations to the Keepa API, listed newest first. Review new entries to keep your integrations running uninterrupted. Official announcement · Latest: Oct 8, 2026 ## October 8, 2026 Search Insights now split the new offers by fulfilment. ### 1. Additions - [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html#fields): new `avgOfferCountNewFBA` and `avgOfferCountNewFBM` fields, the average number of new offers per product fulfilled by Amazon and by the merchant. Both average over the same products as `avgOfferCountNew`, counting a product without offers of that kind as 0, so together they come close to `avgOfferCountNew`. ## September 3, 2026 Filtering on missing values, and whether a Buy Box price already includes import fees. ### 1. Additions - [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html#exists-filter): new `exists` filter, selecting products by whether a field holds a value at all — `"exists": { "brand": false }` returns those with no brand. - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html#fields): new `buyBoxPriceIncludesImportFees` field, whether the price Amazon displays for the Buy Box offer includes the import fees deposit. Where it does, the reported `buyBoxPrice` excludes them. ## August 27, 2026 Variations now carry their parent’s descriptive text. ### 1. Additions - [Product Object](https://env.7xmtools.com/api-docs/product-object.html#fields-variations): new `parentTitle` and `parentHighlights` fields, carrying the `title` and `itemHighlights` of the ASIN named in `parentAsin`. They are provided on variations only — a parent product references itself in `parentAsin` and so has neither — and let a variation be labelled with its parent’s wording without a second request for the parent ASIN. Both are snapshots of the parent’s current values and are **undefined** when the parent cannot be resolved, `parentHighlights` also when the parent has no item highlights. ## August 25, 2026 Offers now carry the strikethrough price Amazon shows above them. ### 1. Additions - [Offer Object](https://env.7xmtools.com/api-docs/offer-object.html#fields): new `savingBasis` field, the offer’s strikethrough reference price, together with `savingBasisType` stating what that number is — the *typical price* (the 90-day median paid), the EU *recent lowest price* of the last 30 days, a manufacturer *list price*, or a *new price* shown against a used offer. Amazon renders all four identically, so the type is required to read the value correctly. Both fields are only present when Amazon shows a reference price for that offer. ## August 18, 2026 Product images now state what they show. ### 1. Additions - [Product Object](https://env.7xmtools.com/api-docs/product-object.html#fields-images-categories): new `variant` field on every entry of the `images` array. It carries Amazon’s own image variant code — *MAIN* for the primary image, *PT01* – *PT08* for further catalogue images, *SWCH* for the colour or style swatch, and a long tail of others such as angle shots, ingredient and nutrition panels and interior pages — so an image can be selected by what it shows rather than by its position in the array. ## August 9, 2026 A new endpoint joins the API: the [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html). ### 1. Additions - [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html) (`/sellerquery`): queries the seller database with complex filter criteria — name and business details, rating history, fulfilment activity, storefront size, Buy Box performance and catalogue profile — and returns a `sellerIdList`. It uses the same request grammar as the [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html), including `page` / `perPage`, `sort` and the `_gte` / `_lte` range syntax, and adds a free-text `search` filter across seller name, business name, address and the identifier fields. Token cost: 10 tokens + 1 per 100 returned seller IDs. The response carries seller IDs only — resolve them through the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request. ## August 6, 2026 Notifications now carry a stable identifier. ### 1. Additions - [Notification Object](https://env.7xmtools.com/api-docs/notification-object.html): new `notificationId` field, a unique identifier for the notification. It is present on notifications delivered by webhook and by the *Get Notifications* call, and lets you refer to one specific notification rather than matching on `asin`, `createDate`, `csvType` and `trackingNotificationCause` together. ## July 28, 2026 The [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html) gains a new series selection surface and access to all three Keepa graph types. ### 1. Additions - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html#param-types): the new `types` parameter selects series by [csv type index](https://env.7xmtools.com/api-docs/product-object.html#csv-array), each optionally with its own colour — for example `&types=11:8888dd,12,34`. It reaches every drawable csv type, including the offer counts, rating and review count that were not previously selectable. - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html#rank-graphs): the **Category Sales Ranks & Monthly Sales** graph can now be rendered, through `subranks`, `cRanks`, `monthlysold` and `cMonthlysold`. Each category is scaled on its own axis so the shapes stay comparable. - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html): new `legend` parameter toggles the chart legend (`1` = show, default). - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html): new `lw` parameter sets the series line width, from `0.5` to `3.0` (default `1.5`). It applies to all three graph types and scales each series proportionally, so their relative thicknesses are preserved. - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html): the maximum `width` and `height` are now **1800** px. ### 2. Semantic & logic changes - [Graph Image API](https://env.7xmtools.com/api-docs/graph-image.html#series-selection): Keepa offers three graph types — Price history, Category Sales Ranks & Monthly Sales, and Offer Counts and Ratings. Each has its own axes and value space, so a single image can only ever contain series from **one** of them. `types` and the sales rank parameters are mutually exclusive; a request naming both returns the bad-request image. - [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html): `priceTypes` now rejects price types that carry no deal data. Such a query previously validated and then always returned an empty result. The accepted values are listed on the Browsing Deals page. - [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html): requests for the current calendar month, or for an out-of-range `month`, are now rejected instead of silently returning the current-rank list. ## April 20, 2026 Please prepare for the following changes scheduled for April. ### 1. Removals & replacements - [Product Object](https://env.7xmtools.com/api-docs/product-object.html): the following fields will be removed: `deals.endTime`, `deals.startTime`, `deal.percentClaimed`, `formats`, `newPriceIsMAP`. - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html): `buyBoxMinOrderQuantity`, `buyBoxMaxOrderQuantity`, and `buyBoxIsPrimePantry` will be removed. - [Category Object](https://env.7xmtools.com/api-docs/category-object.html): the `contextFreeName` field and promotional categories will no longer be provided. - **Digital products:** the API will no longer provide any new data for digital products. Historical data will still be available. #### Legacy field migration The following legacy [Product Object](https://env.7xmtools.com/api-docs/product-object.html) fields will be removed. Please migrate to their replacements: | Removed field | Use instead | | --- | --- | | `variationCSV` | `variations` | | `imagesCSV` | `images` | | `productGroup` | `websiteDisplayGroupName` | ### 2. Semantic & logic changes - [Product Search Request](https://env.7xmtools.com/api-docs/product-search.html): the `page` parameter will be removed. To compensate, the result count per request will increase from 10 to 20 (token cost remains unchanged). - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html): - The fields `buyBoxSavingBasis`, `buyBoxSavingBasisType`, and `buyBoxSavingPercentage` will require the `offers` parameter to be updated. - The `buyBoxAvailabilityMessage` values will change from natural language (e.g., `"In Stock"`) to one of three values: `IN_STOCK`, `BACKORDER_NO_ETA`, `BACKORDER_WITH_ETA`. > **Note:** The removal of the `page` parameter does **not** affect the [Product Finder API](https://env.7xmtools.com/api-docs/product-finder.html). ## February 23, 2026 ### 1. Field deprecations (removed from response) The following fields have been removed to streamline the data structure: - [Product Object](https://env.7xmtools.com/api-docs/product-object.html): `rentalDetails`, `rentalSellerId`, `rentalPrices`, and the `RENT` price history. - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html): `isAddonItem`. - [Offer Object](https://env.7xmtools.com/api-docs/offer-object.html): `isScam`. - [Seller Object](https://env.7xmtools.com/api-docs/seller-object.html): `feedback`, `isScammer`. - [Seller Lookup Request](https://env.7xmtools.com/api-docs/seller.html): the `update` parameter has been removed. Storefront data is now automatically populated via Keepa’s database. ### 2. Semantic & logic changes Please update your logic to accommodate these new definitions: - [Seller Object](https://env.7xmtools.com/api-docs/seller-object.html): the `totalStorefrontAsins` value is now calculated using Keepa’s internal database aggregation rather than the Amazon storefront. - [Product Object](https://env.7xmtools.com/api-docs/product-object.html) (`csv` field) — **price definition update:** for the `NEW`, `USED`, `COLLECTIBLE`, and `REFURBISHED` time series, the pricing definition has changed: - **Historical data:** entries dated *before* February 23, 2026, reflect the **lowest listing price**. - **New data:** entries dated *on or after* February 23, 2026, reflect the **lowest landing price** (listing price + shipping). ### 3. Additions - [Product Object](https://env.7xmtools.com/api-docs/product-object.html): added `COUNT_NEW_FBA` and `COUNT_NEW_FBM` histories to the `csv` field. - [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html): added `buyBoxShippingTime`. ### 4. Improvements - [Product Object](https://env.7xmtools.com/api-docs/product-object.html): the `NEW_FBA` and `NEW_FBM_SHIPPING` price types are now updated more frequently. ## Questions & Support If you have any questions regarding these updates, please contact support at [info@keepa.com](mailto:info@keepa.com). # Settings Source: https://env.7xmtools.com/api-docs/settings.html Store your API access key to run the interactive examples on the endpoint pages directly against the live API. ## API access key Your key is stored **only in this browser** (localStorage) and is sent exclusively to `api.keepa.com` when you run an example. It is never transmitted anywhere else. You can find and manage your key in your [Keepa API dashboard](https://env.7xmtools.com/api). Saving verifies the key against the live API first. A key that does not verify is not stored. > **Signed in to Keepa?** If you are signed in on [keepa.com](https://env.7xmtools.com/) in this browser and have opened the [API dashboard](https://env.7xmtools.com/api) at least once, the examples use your account’s key automatically — there is nothing to enter here. Saving a key below tells **this documentation site** to use that key instead — useful if you were given a key that does not belong to your own Keepa account. It is stored in this browser only and never changes the key on your Keepa account; to do that, use [Generate new key](https://env.7xmtools.com/api) in the API dashboard. ## Running examples Endpoint pages show a **▸ Run** button on their example blocks. It executes the example request with your key and shows the live JSON response (or the generated chart for the Graph Image API), including the tokens consumed. > **Note:** Each run consumes tokens according to the endpoint's token cost. The Run button is only offered for read-only requests — examples that create or delete state (e.g. the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html)) are excluded on purpose. # Product Request Source: https://env.7xmtools.com/api-docs/product.html Retrieves the [product object](https://env.7xmtools.com/api-docs/product-object.html) for one or more products (up to 100 per request) by ASIN or product code, with optional statistics, marketplace offers, Buy Box, stock and variation data. GET · 1 token per product (more with optional parameters) Retrieves the [product object](https://env.7xmtools.com/api-docs/product-object.html) for the specified ASIN and domain. If our last update is older than \~1 hour, it will be automatically refreshed before being delivered to ensure near real-time pricing data. You can request products via either their ASIN (preferred) or UPC, EAN, GTIN and ISBN-13 codes. You cannot use both parameters, `asin` and `code`, in the same request. If a requested ASIN or code does not exist, no product will be returned, but 1 token is still consumed per requested ASIN or code. > **Note:** Keepa cannot track Amazon Fresh. ## Endpoint Request by ASIN: ``` GET https://api.keepa.com/product?key=&domain=&asin= ``` Or request by product code (UPC, EAN, GTIN or ISBN-13): ``` GET https://api.keepa.com/product?key=&domain=&code= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [Domain IDs](https://env.7xmtools.com/api-docs/product.html#domain-ids) table below for valid values. | | `asin` | required\* | The ASIN of the product you want to request. For batch requests, a comma-separated list of ASINs (up to 100). | | `code` | required\* | The product code of the product you want to request. We currently allow UPC, EAN, GTIN, and ISBN-13 codes. For batch requests, a comma-separated list of codes (up to 100). Multiple ASINs can have the same product code, so requesting a product code can return multiple products. Use the `code-limit` parameter to limit the number of returned products per code. | \* Provide either `asin` *or* `code` — you cannot use both parameters in the same request. ### Domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Optional Parameters | Parameter | Extra token cost | Purpose | | --- | --- | --- | | [`stats`](https://env.7xmtools.com/api-docs/product.html#param-stats) | none | Include a `stats` field with current prices and statistics. | | [`update`](https://env.7xmtools.com/api-docs/product.html#param-update) | 0 or 1 per product | Force a refresh if the product's last update is older than specified hours. | | [`history`](https://env.7xmtools.com/api-docs/product.html#param-history) | none | Exclude historical data fields to reduce response size and processing time. | | [`days`](https://env.7xmtools.com/api-docs/product.html#param-days) | none | Limit historical data to the recent X days. | | [`code-limit`](https://env.7xmtools.com/api-docs/product.html#param-code-limit) | none | Limit the number of products returned per code when using the `code` parameter. | | [`offers`](https://env.7xmtools.com/api-docs/product.html#param-offers) | 6 per found offer page | Retrieve up-to-date marketplace offers; incurs additional token cost. | | [`only-live-offers`](https://env.7xmtools.com/api-docs/product.html#param-only-live-offers) | none | Include only live marketplace offers; reduces response size. | | [`videos`](https://env.7xmtools.com/api-docs/product.html#param-videos) | none | Include video metadata. | | [`aplus`](https://env.7xmtools.com/api-docs/product.html#param-aplus) | none | Include A+ content. | | [`rating`](https://env.7xmtools.com/api-docs/product.html#param-rating) | up to 1 per product | Include existing rating and review count history; may consume an extra token. | | [`buybox`](https://env.7xmtools.com/api-docs/product.html#param-buybox) | 2 per product | Include Buy Box related data; incurs additional token cost. | | [`stock`](https://env.7xmtools.com/api-docs/product.html#param-stock) | 2 per product | Include stock information in offers and statistics; incurs additional token cost. | | [`historical-variations`](https://env.7xmtools.com/api-docs/product.html#param-historical-variations) | 1 per product with a parent ASIN | Include historical and out of stock variations; incurs additional token cost. | ### `stats` **Token cost:** no extra token cost. If specified, the product object will include a `stats` field (a [statistics object](https://env.7xmtools.com/api-docs/statistics-object.html)) with quick access to current prices, min/max prices, and weighted mean values. If the `offers` parameter is used, it will also provide Buy Box information. You can provide the `stats` parameter in two forms: - **Last x days** (positive integer value): calculates the stats for the last **x** days. - **Interval:** specify a date range for the stats calculation using two timestamps (Unix epoch time in milliseconds) or two date strings (ISO8601 format, UTC). > **Note:** If there is insufficient historical data for a price type, the actual interval of the weighted mean calculation may be shorter than specified. All data provided via the `stats` field are calculated using the product object's `csv` history field; no new data is provided through this parameter. Examples: - `&stats=180` — last 180 days - `&stats=2015-10-20,2015-12-24` — from Oct 20 to Dec 24, 2015 - `&stats=2011-01-01,2025-01-01` — entire history - `&stats=1445299200000,1450915200000` — Unix epoch time in milliseconds, from Oct 20 to Dec 24, 2015 ### `update` **Additional token cost:** 0 or 1 per product. Positive integer value. If the product's last update is older than **update** hours, force a refresh. The default value used by the API is 1 hour. This parameter also works in conjunction with the `offers` parameter. Using this parameter, you can achieve the following: - **Speed up requests:** if up-to-date data is not required, use a higher value than **1** hour. No extra token cost. - **Always retrieve live data:** use the value **0**. If our last update was less than 1 hour ago, this consumes **1 extra token**. - **No update at all:** use the value **-1**. If the product is missing in our database and the `asin` parameter was used, the product request will consume **0 tokens**, and you will not receive any product data. Use this if you are only interested in products we have historical data for to save tokens. - **Reduced offers token usage:** when combined with the `offers` parameter and our last offers data update is newer than **update** hours, the offers token usage will be reduced to 5 tokens, and no update will take place, regardless of the number of offer pages requested. Example: `&update=48` — only trigger an update if the product's last update is older than 48 hours. ### `history` **Token cost:** no extra token cost. Boolean value (`0` = false, `1` = true). If specified and set to `0`, the product object will not include the `csv`, `salesRanks`, `monthlySoldHistory`, `parentAsinHistory`, `couponHistory`, `buyBoxSellerIdHistory`, `buyBoxUsedHistory` and `salesRankReferenceHistory` fields. If you do not need them, use this to have them removed from the response. This will improve processing time and considerably decrease the size of the response. Example: `&history=0` ### `days` **Token cost:** no extra token cost. Any positive integer value. If specified with a positive value **X**, the product object will limit all historical data to the recent **X** days. This includes the `csv`, `buyBoxSellerIdHistory`, `salesRankReferenceHistory`, `salesRanks`, `offers`, and `offers.offerCSV` fields. If you do not need old historical data, use this to reduce the response size and improve processing time. The parameter does not use calendar days; so **1 day** equals the last 24 hours. Example: `&days=90` ### `code-limit` **Token cost:** no extra token cost. Any positive integer value. Sets a constraint on the maximum number of products returned for a given code when utilizing the `code` parameter. Use this parameter to limit the volume of product results associated with specific product codes. Example: `&code-limit=10` ### `offers` **Token cost:** 6 for every found offer page (contains up to 10 offers) per product, with a minimum of 5 tokens if the retrieval succeeds but no offer page is found. Positive integer value between **20** and **100**. Determines the number of **up-to-date** marketplace offers to retrieve. The additional token cost is calculated based on the number of found offers, not the requested amount (as a product can have fewer offers than requested). When using the `offers` parameter, the basic 1 token cost per ASIN of the product request does not apply. If the `offers` parameter is used, the product object will contain additional data: - [Marketplace offer objects](https://env.7xmtools.com/api-docs/offer-object.html) - Information on the New and Used Buy Box, including a history of Buy Box winners - Price history data for FBA (Fulfillment by Amazon), FBM (Fulfillment by Merchant), Warehouse Deals, Prime exclusive, and all Used and Collectible sub-conditions, including shipping and handling costs - Rating and review count history All offers-related data is updated independently, irregularly, and not as often as all other product data. Keep this in mind when evaluating the additional historical data. > **Notes:** > > - The returned product may have more offers than specified because we keep a history of offers. The number specified in this parameter determines how many offers we attempt to retrieve/update from Amazon. Each offer object has a `lastSeen` field that can be used to filter up-to-date offers. > - Batched requests are processed in parallel. > - All offers-related data is freshly updated and up-to-date. > - The request will require more time to complete, ranging from 2 to 20 seconds with an average of 5 seconds. Use batch requests or parallel requests to increase throughput when required. > - If we fail to retrieve/refresh the offers data, the request will consume 1 token. The request will return successfully and will contain, if available, all **historical** offers (unless `only-live-offers` is used) and product data. You can retry the request after a few minutes. > - If the retrieval succeeds but the product has no marketplace offers at all, no offer page is found and the request consumes 5 tokens. This is a successful retrieval, not a failure: the product object is returned with `offersSuccessful` set to `true`. > - If the product no longer exists on Amazon, the request is treated the same way: 5 tokens, `offersSuccessful` set to `true`, no live offers. For the next 7 days on amazon.com, amazon.co.jp and amazon.de, or 6 hours on the other marketplaces, requests for it are answered from our data at the same cost. > **Limitations:** not available for digital products, movie rentals, product bundles, Amazon Fresh, luxury stores, Amazon Haul/Bazaar, and Amazon Pantry. Example: `&offers=40` — requested up to 40 offers, but the product only has 18 offers. Total token cost for the request: 6 per found offer page = **12 tokens**. ### `only-live-offers` **Token cost:** no extra token cost. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the product object will only include live marketplace offers (when used in combination with the `offers` parameter). If you do not need historical offers, use this to reduce the response size and improve processing time. If only live offers are requested and our system fails to retrieve them, the product request will consume no tokens. Example: `&only-live-offers=1` ### `videos` **Token cost:** no extra token cost. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the videos metadata will be provided when available. Using this parameter does not trigger an update to the videos data; it only gives access to our existing data if available. If you need up-to-date data, you have to use the `offers` parameter. ### `aplus` **Token cost:** no extra token cost. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the A+ content will be provided when available. Using this parameter does not trigger an update to the A+ content; it only gives access to our existing data if available. If you need up-to-date data, you have to use the `offers` parameter. ### `rating` **Token cost:** up to 1 extra token per product. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the product object will include our existing `RATING` and `COUNT_REVIEWS` history in the `csv` field, regardless of whether the `offers` parameter is used. The extra token will only be consumed if our last update to both data points is less than 14 days ago. Using this parameter does not trigger an update to those two fields; it only gives access to our existing data if available. If you need up-to-date data, you have to use the `offers` parameter. Use this if you need access to the rating data, which may be outdated, but do not need any other data fields provided through the `offers` parameter to save tokens and speed up the request. If there is no rating data returned, you can still make another request using the `offers` parameter. Example: `&rating=1` — include the rating and review count data in the `csv` history data field of the product object and respective fields of the [statistics object](https://env.7xmtools.com/api-docs/statistics-object.html). ### `buybox` **Additional token cost:** 2 per product. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the product and [statistics object](https://env.7xmtools.com/api-docs/statistics-object.html) will include all available Buy Box related data: - Current price, price history, and statistical values - `buyBoxSellerIdHistory` - All Buy Box fields in the statistics object The `buybox` parameter does not trigger a fresh data collection. If the `offers` parameter is used, the `buybox` parameter is ignored, as the `offers` parameter also provides access to all Buy Box related data. To access the statistics object, the `stats` parameter is required. Example: `&buybox=1` ### `stock` **Additional token cost:** 2 per product. Boolean value (`0` = false, `1` = true). If set to `1`, the response includes the stock data available for the product: - together with the `offers` parameter, the [marketplace offer objects](https://env.7xmtools.com/api-docs/offer-object.html) include the `stockCSV` field; - together with the `stats` parameter, the [statistics object](https://env.7xmtools.com/api-docs/statistics-object.html#stock-fields) includes the `stockAmazon` and `stockBuyBox` fields. In both cases the product object includes the `lastStockUpdate` field. Without `offers` or `stats`, the parameter adds only `lastStockUpdate` and costs no extra tokens. > **Token cost note:** The `stock` parameter incurs 2 extra tokens only if `lastStockUpdate` is newer than 7 days and the response contains stock data for the product (`stockCSV` in an offer, or the stock fields of the statistics object). > **Limitations & performance notes:** > > - **Offer limit:** usually, stock data is only retrieved for the top 10 offers. > - **Data freshness:** this parameter is not guaranteed to collect fresh stock data. > - **Latency:** the request will require more time to retrieve stock data, typically adding 1 to 2 seconds per offer to the total response time. Example: `&stock=1` ### `historical-variations` **Additional token cost:** 1 per product that has a parent ASIN. Boolean value (`0` = false, `1` = true). If specified and set to `1`, the product object will have the `historicalVariations` field set, which provides a list of historical and out of stock variation ASINs of the requested product. Example: `&historical-variations=1` ## Token Cost The base cost is **1 token per product**. If a requested ASIN or code does not exist, 1 token is still consumed. Optional parameters can add to — or in some cases replace or reduce — that cost: | Scenario | Token cost | | --- | --- | | Basic request (per requested product) | 1 token | | `offers` used | 6 tokens per found offer page (up to 10 offers per page) per product; the basic 1 token per ASIN does *not* apply | | `offers` used, retrieval succeeds but the product has no offers | 5 tokens (no offer page is found; `offersSuccessful` is `true`) | | `offers` used, the product no longer exists on Amazon | 5 tokens (`offersSuccessful` is `true`, no live offers); for 7 days on .com, .co.jp and .de and 6 hours elsewhere, further requests are answered from our data at the same cost | | `offers` used, but offers retrieval/refresh fails | 1 token (historical offers and product data are still returned, unless `only-live-offers` is used) | | `offers` + `only-live-offers`, retrieval fails | 0 tokens | | `offers` + `update`, last offers data update newer than `update` hours | 5 tokens flat, no update takes place (regardless of the number of offer pages requested) | | `update=0` and our last update was less than 1 hour ago | +1 extra token | | `update=-1`, product missing in our database, `asin` parameter used | 0 tokens (no product data returned) | | `rating=1` | up to +1 token per product (only if our last update to both rating and review count data is less than 14 days ago) | | `buybox=1` | +2 tokens per product | | `stock=1` | +2 tokens per product (only if `lastStockUpdate` is newer than 7 days and the response contains stock data) | | `historical-variations=1` | +1 token per product that has a parent ASIN | | `stats`, `history`, `days`, `code-limit`, `only-live-offers`, `videos`, `aplus` | no extra token cost | ## Response A `products` field containing an array of [product objects](https://env.7xmtools.com/api-docs/product-object.html) with an entry for each ASIN that was requested. ## Examples ### Basic request (single ASIN) Request the product object for a single ASIN on amazon.com (domain `1`): **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { if (result.status == ResponseStatus.OK) { System.out.println(result.products[0].title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { echo $response->products[0]->title; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS"} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() product = data["products"][0] print(product["title"], product["lastUpdate"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS"); const data = await res.json(); const product = data.products[0]; console.log(product.title, product.lastUpdate); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS" ``` ### Example response ```json { "timestamp": 1783468800000, "tokensLeft": 297, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 1, "processingTimeInMs": 812, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Wireless Bluetooth Speaker (Black)", "trackingSince": 1052640, "listedSince": 1048200, "lastUpdate": 7663880, "lastPriceChange": 7663520, "brand": "examplebrand", "manufacturer": "ExampleBrand Inc.", "model": "EB-100", "color": "Black", "rootCategory": 172282, "categories": [3236451011], "parentAsin": null, "csv": [ [7650120, 2999, 7658340, 3199, 7663520, 3099], [7650120, 2799, 7660100, 2749, 7663520, 2699], null, [7650120, 5310, 7663880, 4874] ] } ] } ``` Response shortened for readability; illustrative values. Prices are integers in the smallest currency unit (e.g. cents), and history timestamps are in Keepa Time minutes — see the [product object](https://env.7xmtools.com/api-docs/product-object.html) for the full field reference and the conversion formula. ### Batch request (comma-separated ASINs, up to 100) Request several products at once by passing a comma-separated list of ASINs (up to 100). Each returned product costs 1 token (plus any optional-parameter costs): **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B0F3GWXLTS", "B0BDHWDR12", "B07FZ8S74R"); api.sendRequest(r) .done(result -> { for (Product product : result.products) { System.out.println(product.asin + " " + product.title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B0F3GWXLTS', 'B0BDHWDR12', 'B07FZ8S74R'])); if ($response->status == ResponseStatus::OK) { foreach ($response->products as $product) { echo $product->asin . " " . $product->title . PHP_EOL; } } ``` **Python** ```python import requests asins = ["B0F3GWXLTS", "B0BDHWDR12", "B07FZ8S74R"] # up to 100 per request params = {"key": "YOUR_API_KEY", "domain": 1, "asin": ",".join(asins)} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() for product in data["products"]: print(product["asin"], product["title"]) ``` **Node.js** ```javascript const asins = ["B0F3GWXLTS", "B0BDHWDR12", "B07FZ8S74R"]; // up to 100 per request const url = `https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=${asins.join(",")}`; const res = await fetch(url); const data = await res.json(); for (const product of data.products) console.log(product.asin, product.title); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS,B0BDHWDR12,B07FZ8S74R" ``` ### Example response ```json { "timestamp": 1783468800000, "tokensLeft": 294, "refillIn": 38000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 3, "processingTimeInMs": 1420, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Wireless Bluetooth Speaker (Black)", "lastUpdate": 7663880 }, { "asin": "B0BDHWDR12", "domainId": 1, "title": "Example USB-C Charging Cable, 2 m", "lastUpdate": 7663910 }, { "asin": "B07FZ8S74R", "domainId": 1, "title": "Example Smart Home Hub, 2nd Generation", "lastUpdate": 7663845 } ] } ``` Response shortened for readability; illustrative values. Each entry in `products` is a full [product object](https://env.7xmtools.com/api-docs/product-object.html). ### Offers request Retrieve up-to-date marketplace offers with `&offers=20`. Note the different token accounting: 6 tokens per found offer page instead of the basic 1 token per ASIN. **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, 20, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { Product product = result.products[0]; System.out.println(product.offers.length + " offers"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, 20, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { $product = $response->products[0]; echo count($product->offers) . " offers"; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS", "offers": 20} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() product = data["products"][0] for offer in product["offers"]: print(offer["sellerId"], offer["lastSeen"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&offers=20"); const data = await res.json(); const product = data.products[0]; product.offers.forEach(o => console.log(o.sellerId, o.lastSeen)); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&offers=20" ``` ### Example response ```json { "timestamp": 1783468800000, "tokensLeft": 282, "refillIn": 29000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 12, "processingTimeInMs": 4380, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Wireless Bluetooth Speaker (Black)", "lastUpdate": 7663930, "lastOffersUpdate": 7663930, "buyBoxSellerIdHistory": ["7660100", "ATVPDKIKX0DER", "7663930", "A2L77EE7U53NWQ"], "liveOffersOrder": [0, 1], "offers": [ { "offerId": 0, "lastSeen": 7663930, "sellerId": "A2L77EE7U53NWQ", "condition": 1, "isPrime": true, "isFBA": true, "offerCSV": [7655800, 2799, 0, 7663930, 2699, 0] }, { "offerId": 1, "lastSeen": 7663930, "sellerId": "ATVPDKIKX0DER", "condition": 1, "isPrime": true, "isFBA": true, "offerCSV": [7650120, 2999, 0, 7663930, 2749, 0] } ] } ] } ``` Response shortened for readability; illustrative values. In this example 2 offer pages were found, so the request consumed 6 × 2 = 12 tokens. See the [marketplace offer object](https://env.7xmtools.com/api-docs/offer-object.html) for all offer fields. # Product Search Source: https://env.7xmtools.com/api-docs/product-search.html Search for Amazon products using keywords and retrieve up to 20 results per search term — either as full product objects or as a plain list of ASINs. GET · 10 tokens per search (up to 20 results) Search for Amazon products using keywords, returning up to **20** results per search term. The results are in the same order as a search on Amazon, excluding sponsored content. By default, the product search response contains the [product objects](https://env.7xmtools.com/api-docs/product-object.html) of the found products. ## Endpoint ``` GET https://api.keepa.com/search?key=&domain=&type=product&term= ``` ## Parameters ### Required parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/product-search.html#domain-ids) below. | | `type` | required | Must be set to `product` for a product search. | | `term` | required | The term you want to search for. Should be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding). | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ### Optional parameters | Parameter | Required | Description | | --- | --- | --- | | `asins-only` | optional | If provided and set to `1`, only the ASINs of the found products will be provided instead of the full product objects.
**Example:** `&asins-only=1` | | `stats` | optional | No extra token cost. If specified, the product object will include a `stats` field (see [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html)) with quick access to current prices, min/max prices, and weighted mean values. You can provide the `stats` parameter in two forms:
• **Last x days:** a positive integer value representing the number of last days to calculate stats for.
**Example:** `&stats=180` (stats for the last 180 days)
• **Interval:** a date range for the stats calculation using two timestamps (Unix epoch time in milliseconds) or two date strings (ISO8601 format, with or without time in UTC).
**Examples:** `&stats=2015-10-20,2015-12-24` (from October 20 to December 24, 2015) · `&stats=1445299200000,1450915200000` (Unix epoch time in milliseconds) | | `update` | optional | **Additional token cost:** 0 or 1 per found product.
Positive integer value. If the product's last update is older than `` hours, force a refresh. The default value the API uses is **1** hour.
**Usage:**
• **Speed up requests:** if up-to-date data is not required, use a higher value than **1** hour. No extra token cost.
• **Always retrieve live data:** use the value **0**. If our last update for the product was less than 1 hour ago, this consumes **1 extra token** per product.
**Example:** `&update=48` (only trigger an update if the product's last update is older than 48 hours) | | `history` | optional | No extra token cost. Boolean value (`0` = false, `1` = true). If specified and set to `0`, the product object will not include the `csv` field. Use this to reduce response size and improve processing time if you do not need the historical data.
**Example:** `&history=0` | | `rating` | optional | Up to **1** extra token per found product (**maximum of 5 additional tokens per search**). Boolean value (`0` = false, `1` = true). If specified and set to `1`, the product object will include our existing `RATING` and `COUNT_REVIEWS` history in the `csv` field.
• The extra token will only be consumed if our last update to both data points is less than **14** days ago.
• Using this parameter does not trigger an update to these fields; it only provides access to existing data if available.
• If you need up-to-date data, you have to use the `offers` parameter of a separate [product request](https://env.7xmtools.com/api-docs/product.html).
• Use this if you need access to the rating data, which may be outdated, but do not need any other data fields provided through the `offers` parameter — to save tokens and speed up the request.
**Example:** `&rating=1` (include rating and review count data in the `csv` field) | > **Note:** If there is insufficient historical data for a price type, the actual interval of the weighted mean calculation for the `stats` field may be shorter than specified. All data provided via the `stats` field are calculated using the product object's `csv` history field; no new data is provided through this parameter. ## Token Cost | Component | Cost | | --- | --- | | Product search (up to 20 results) | **10** tokens | | `update` parameter | **0 or 1** extra token per found product (1 extra token only with `update=0` when our last update for the product was less than 1 hour ago) | | `rating` parameter | Up to **1** extra token per found product, **maximum of 5 additional tokens per search** (only consumed if our last update to both data points is less than 14 days ago) | | `stats` parameter | No extra token cost | | `history` parameter | No extra token cost | ## Response An ordered array of [product objects](https://env.7xmtools.com/api-docs/product-object.html) in the `products` field, or an ordered string array of ASINs in the `asinList` field (if the `asins-only` parameter was used). ## Examples ### Example request Search for *wireless mouse* on amazon.com (note the URL-encoded search term): ```bash https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=product&term=wireless%20mouse ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductSearchRequest(AmazonLocale.US, "wireless mouse", null); api.sendRequest(r) .done(result -> { for (Product product : result.products) { System.out.println(product.asin + " " + product.title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductSearchRequest(AmazonLocale::US, "wireless mouse", null)); if ($response->status == ResponseStatus::OK) { foreach ($response->products as $product) { echo $product->asin . " " . $product->title . PHP_EOL; } } ``` **Python** ```python import requests params = { "key": "YOUR_API_KEY", "domain": 1, "type": "product", "term": "wireless mouse", # requests handles the URL encoding } r = requests.get("https://api.keepa.com/search", params=params) data = r.json() for product in data["products"]: print(product["asin"], product["title"]) ``` **Node.js** ```javascript const term = encodeURIComponent("wireless mouse"); const url = `https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=product&term=${term}`; const res = await fetch(url); const data = await res.json(); for (const product of data.products) { console.log(product.asin, product.title); } ``` **cURL** ```bash curl -s "https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=product&term=wireless%20mouse" ``` ### Example response ```json { "timestamp": 1753592460000, "tokensLeft": 268, "refillIn": 32000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 10, "processingTimeInMs": 341, "products": [ { "asin": "B09HM94VDS", "domainId": 1, "title": "Logitech MX Master 3S Wireless Performance Mouse", "trackingSince": 5926110, "listedSince": 5925800, "lastUpdate": 7662540, "lastPriceChange": 7661180, "rootCategory": 172282, "categories": [11036491, 172282], "parentAsin": null, "manufacturer": "Logitech", "brand": "Logitech", "websiteDisplayGroupName": "Personal Computer", "model": "910-006556", "images": [{"l": "61ni3t6ryLL.jpg", "lH": 1500, "lW": 1500, "m": "71fP4WKKvNL.jpg", "mH": 500, "mW": 500}], "csv": [ [7655020, 9999, 7658200, 9499, 7661180, 8999], [7655020, 9899, 7661180, 8999], null ] } ] } ``` Response shortened for readability; illustrative values. A real response contains up to 20 product objects, each with the full set of [product object](https://env.7xmtools.com/api-docs/product-object.html) fields, and the `csv` history arrays cover all price types. Prices are integers in the smallest currency unit (e.g. `8999` = $89.99); history timestamps are in Keepa Time minutes. ### Example: ASINs only With `asins-only=1`, the response contains a plain, ordered ASIN list in `asinList` instead of product objects: **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductSearchRequest(AmazonLocale.US, "wireless mouse", null, 1, false, true) // asinsOnly = true; api.sendRequest(r) .done(result -> { System.out.println(String.join(", ", result.asinList)); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php parameter["asins-only"] = "1"; $response = $api->sendRequestWithRetry($r); if ($response->status == ResponseStatus::OK) { print_r($response->asinList); } ``` **Python** ```python import requests params = { "key": "YOUR_API_KEY", "domain": 1, "type": "product", "term": "wireless mouse", "asins-only": 1, } r = requests.get("https://api.keepa.com/search", params=params) print(r.json()["asinList"]) ``` **Node.js** ```javascript const term = encodeURIComponent("wireless mouse"); const url = `https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=product&term=${term}&asins-only=1`; const res = await fetch(url); const data = await res.json(); console.log(data.asinList); ``` **cURL** ```bash curl -s "https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=product&term=wireless%20mouse&asins-only=1" ``` ```json { "timestamp": 1753592520000, "tokensLeft": 258, "refillIn": 26000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 10, "processingTimeInMs": 112, "asinList": [ "B09HM94VDS", "B07S395RWD", "B003NR57BY", "B01N7KFXKP" ] } ``` Response shortened for readability; illustrative values. > **Tip:** If you only need the ASINs (e.g. to feed them into a batch [product request](https://env.7xmtools.com/api-docs/product.html) later), use `asins-only=1` to keep the response small. If you do need product data but not the price history, add `history=0` to reduce response size and processing time. # Product Finder Source: https://env.7xmtools.com/api-docs/product-finder.html Search for products in the Keepa database that match your specified criteria and receive a Search Insights summary that aggregates KPIs (prices, seller mix, brand counts, etc.) across the entire result set. You can search and sort by nearly all product fields. GET / POST · 10 + 1 per 100 ASINs This request offers the same core functionality as the [Product Finder](https://env.7xmtools.com/finder) on the Keepa website. - The request returns only ASIN lists, not [product objects](https://env.7xmtools.com/api-docs/product-object.html). - Each request consumes 10 tokens plus an additional token per 100 ASINs in the result set. - A query can return up to 10,000 ASINs using paging, with a minimum page size of 50 ASINs. If using paging, initial search results are not cached, so the order of results may be inconsistent between individual pages if there is a delay between consecutive page requests. - Filters are joined by an **AND** condition. - For filters allowing multiple entries (all arrays), each specified entry is considered with an **OR** condition, supporting a maximum of 50 entries. - The product query searches the Keepa database, not Amazon's. It may not find all products on Amazon that match your query. - Product data constantly changes. Running the same query twice may yield different results, as products may be misplaced due to recent changes or updates during the query execution. > **Note:** All API requests execute regardless of your current token balance, as long as it's positive. Requesting large result sets may cause your token balance to go negative. Use with caution! ## Endpoint You can choose between an HTTP GET or POST request. ### GET format ``` GET https://api.keepa.com/query?key=&domain=&selection=[&stats=1] ``` The `` must be **URL-encoded** if the GET format is used. ### POST format ``` POST https://api.keepa.com/query?domain=&key=[&stats=1] ``` The POST payload must contain the ``. ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/product-finder.html#domain-ids) below. | | `selection` | required | The query JSON containing all request parameters (see [below](https://env.7xmtools.com/api-docs/product-finder.html#the-query-json)). URL-encoded as GET parameter, or sent as the POST body. | | `stats` | optional | **Token cost:** 30 tokens + 1 token for every 1,000,000 products returned by the *query as a whole* (not just the current page). If specified and set to `1`, the response will include a [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html). Example: `&stats=1` | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost - **Base cost:** 10 tokens per request + 1 token per 100 ASINs in the result set. - **`stats=1`:** additionally 30 tokens + 1 token for every 1,000,000 products matched by the query as a whole (not just the current page). > **Important:** Requesting large lists may consume more tokens than are available in your bucket, causing your balance to go negative. Use with caution. ## The query JSON The `selection` JSON combines paging, sorting and filters. All filters are optional; the query is valid as long as at least one filter is specified. The scalar and array filters are listed individually below; price/value statistics filters follow systematic naming patterns of the form `__lte|_gte` (see [price-type statistics filters](https://env.7xmtools.com/api-docs/product-finder.html#price-type-stat-filters)). ```json { "page": Integer, "perPage": Integer, "sort": [ [String, String] ], "rootCategory": Long[], "categories_include": Long[], "categories_exclude": Long[], "salesRankReference": Long, "title": String, "manufacturer": String[], "brand": String[], "singleVariation": Boolean, "historicalParentASIN": String, "hasParentASIN": Boolean, "productType": Integer, "availabilityAmazon": Integer[], "returnRate": Integer[], "hasReviews": Boolean, "isLowestOffer": Boolean, "trackingSince_lte": Integer, "trackingSince_gte": Integer, "lastPriceChange_lte": Integer, "lastPriceChange_gte": Integer, "lastOffersUpdate_lte": Integer, "lastOffersUpdate_gte": Integer, "partNumber": String[], "model": String[], "color": String[], "size": String[], "edition": String[], "format": String[], "author": String[], "binding": String[], "genre": String[], "languages": String[], "publisher": String[], "platform": String[], "activeIngredients": String[], "specialIngredients": String[], "itemTypeKeyword": String[], "targetAudienceKeyword": String[], "itemForm": String[], "scent": String[], "unitType": String[], "pattern": String[], "style": String[], "material": String[], "brandStoreName": String[], "brandStoreUrlName": String[], "frequentlyBoughtTogether": String[], "packageHeight_lte": Integer, "packageHeight_gte": Integer, "packageLength_lte": Integer, "packageLength_gte": Integer, "packageWidth_lte": Integer, "packageWidth_gte": Integer, "packageWeight_lte": Integer, "packageWeight_gte": Integer, "itemHeight_lte": Integer, "itemHeight_gte": Integer, "itemLength_lte": Integer, "itemLength_gte": Integer, "itemWidth_lte": Integer, "itemWidth_gte": Integer, "itemWeight_lte": Integer, "itemWeight_gte": Integer, "variationCount_lte": Integer, "variationCount_gte": Integer, "imageCount_lte": Integer, "imageCount_gte": Integer, "videoCount_lte": Byte, "videoCount_gte": Byte, "variationReviewCount_lte": Integer, "variationReviewCount_gte": Integer, "variationRatingCount_lte": Integer, "variationRatingCount_gte": Integer, "buyBoxStatsAmazon30_lte": Integer, "buyBoxStatsAmazon30_gte": Integer, "buyBoxStatsAmazon90_lte": Integer, "buyBoxStatsAmazon90_gte": Integer, "buyBoxStatsAmazon180_lte": Integer, "buyBoxStatsAmazon180_gte": Integer, "buyBoxStatsAmazon365_lte": Integer, "buyBoxStatsAmazon365_gte": Integer, "buyBoxStatsTopSeller30_lte": Integer, "buyBoxStatsTopSeller30_gte": Integer, "buyBoxStatsTopSeller90_lte": Integer, "buyBoxStatsTopSeller90_gte": Integer, "buyBoxStatsTopSeller180_lte": Integer, "buyBoxStatsTopSeller180_gte": Integer, "buyBoxStatsTopSeller365_lte": Integer, "buyBoxStatsTopSeller365_gte": Integer, "buyBoxStatsSellerCount30_lte": Integer, "buyBoxStatsSellerCount30_gte": Integer, "buyBoxStatsSellerCount90_lte": Integer, "buyBoxStatsSellerCount90_gte": Integer, "buyBoxStatsSellerCount180_lte": Integer, "buyBoxStatsSellerCount180_gte": Integer, "buyBoxStatsSellerCount365_lte": Integer, "buyBoxStatsSellerCount365_gte": Integer, "outOfStockPercentage90_lte": Integer, "outOfStockPercentage90_gte": Integer, "outOfStockCountAmazon30_lte": Integer, "outOfStockCountAmazon30_gte": Integer, "outOfStockCountAmazon90_lte": Integer, "outOfStockCountAmazon90_gte": Integer, "deltaPercent90_monthlySold_lte": Integer, "deltaPercent90_monthlySold_gte": Integer, "monthlySold_lte": Integer, "monthlySold_gte": Integer, "couponOneTimeAbsolute_lte": Integer, "couponOneTimeAbsolute_gte": Integer, "couponOneTimePercent_lte": Integer, "couponOneTimePercent_gte": Integer, "couponSNSPercent_lte": Integer, "couponSNSPercent_gte": Integer, "flipability30_lte": Byte, "flipability30_gte": Byte, "flipability90_lte": Byte, "flipability90_gte": Byte, "flipability365_lte": Byte, "flipability365_gte": Byte, "businessDiscount_lte": Byte, "businessDiscount_gte": Byte, "isHazMat": Boolean, "isHeatSensitive": Boolean, "isAdultProduct": Boolean, "isEligibleForSuperSaverShipping": Boolean, "isSNS": Boolean, "isMerchOnDemand": Boolean, "isPrimeExclusive": Boolean, "batteriesRequired": Boolean, "batteriesIncluded": Boolean, "hasMainVideo": Boolean, "hasAPlus": Boolean, "hasAPlusFromManufacturer": Boolean, "buyBoxIsAmazon": Boolean, "buyBoxIsFBA": Boolean, "buyBoxIsUnqualified": Boolean, "buyBoxIsPreorder": Boolean, "buyBoxIsBackorder": Boolean, "buyBoxIsPrimeExclusive": Boolean, "buyBoxSellerId": String[], "buyBoxUsedCondition": Integer[], "buyBoxUsedIsFBA": Boolean, "buyBoxUsedSellerId": String[], "sellerIds": String[], "sellerIdsLowestFBA": String[], "sellerIdsLowestFBM": String[], "dealType": String[], "numberOfItems_lte": Integer, "numberOfItems_gte": Integer, "numberOfPages_lte": Integer, "numberOfPages_gte": Integer, "publicationDate_lte": Integer, "publicationDate_gte": Integer, "releaseDate_lte": Integer, "releaseDate_gte": Integer, "lightningEnd_lte": Integer, "lightningEnd_gte": Integer, "current__lte": Integer, "current__gte": Integer, "delta30__lte": Integer, "delta30__gte": Integer, "delta90__lte": Integer, "delta90__gte": Integer, "deltaPercent30__lte": Integer, "deltaPercent30__gte": Integer, "deltaPercent90__lte": Integer, "deltaPercent90__gte": Integer, "deltaLast__lte": Integer, "deltaLast__gte": Integer, "avg30__lte": Integer, "avg30__gte": Integer, "avg90__lte": Integer, "avg90__gte": Integer, "avg180__lte": Integer, "avg180__gte": Integer, "avg365__lte": Integer, "avg365__gte": Integer, "lastPriceChange__lte": Integer, "lastPriceChange__gte": Integer, "backInStock_": Boolean, "isLowest_": Boolean, "isLowest90_": Boolean } ``` > **Note:** `isLowestOffer` (Boolean) only includes products for which the selected price type is the lowest of all New offers (applicable to Amazon and Marketplace New). Example: `"isLowestOffer": true` ### Paging *Paging is optional; by default, up to 50 results are provided.* | Field | Description | | --- | --- | | `page` | Most queries have more than 50 results (the minimum page size). To retrieve additional results, iterate the `page` parameter while keeping all other parameters identical. Start with `page` 0 and stop when the response contains fewer than 50 results. Each response also includes the `totalResults` field, indicating the number of matched products. When requesting a `page` other than 0, the combination of `page` and `perPage` must not exceed 10,000 results. Example: `0` | | `perPage` | Specifies the number of results to retrieve per page. The default and minimum values are 50 ASINs. If `page` is **0**, `perPage` can be as large as 10,000. If a `page` other than 0 is requested, the combination of `page` and `perPage` must not exceed 10,000 results. | ### Sorting *Sorting is optional; by default, results are sorted ascending by current sales rank.* `sort` can include up to three sorting criteria. Use a two-dimensional array where each entry is in the format `[fieldName, sortDirection]`: - **fieldName**: any filter from the list below that is either a String or Integer, except the filter-only fields listed in the note. The `fieldName` must not include `_lte` or `_gte`. - **sortDirection**: use `"asc"` for ascending or `"desc"` for descending. ```json "sort": [ ["current_SALES", "asc"] ] ``` > **Note:** a few filters can be matched on but not sorted by: `partNumber`, `historicalSellerIds`, `sellerIdsFBA`, `sellerIdsFBM`, `buyBoxStatsTopSellerId30`, `buyBoxStatsTopSellerId90`, `buyBoxStatsTopSellerId180` and `buyBoxStatsTopSellerId365`. Naming one in `sort` does **not** produce an error — the whole `sort` is discarded and the default sort applies instead, the same way an unrecognised field name does. ### Filter basics The following fields act as filters. Only products that **exactly** match all filters will be returned by the query. All string filters are case insensitive and can be used as exclusion filters by using the prefix `✜`. Filters ending in `_gte` restrict the output to values "Greater than or equal" to the specified value, while `_lte` means "Less than or equal". #### minMatch — K-of-N matching on array filters Entries within one array filter are normally joined by **OR**: any one of them may match. `minMatch` raises that bar per field, as a map of filter name to the number of entries that must match. Setting it equal to the number of entries turns that filter into an **AND**. ```json "minMatch": { "sellerIds": 2, "manufacturer": 1 } ``` Here a product must be offered by at least two of the listed `sellerIds`, while `manufacturer` keeps its default OR behaviour. Values are clamped to the number of entries actually supplied for that filter. #### exists — matching on a missing value Every other filter matches on a value being *present*. `exists` is the opposite: a map of filter name to a Boolean, where `false` selects the products we hold no value for, and `true` those we do. ```json "exists": { "brand": false, "color": true } ``` This example returns products that have no brand and do have a colour. Entries combine with every other filter using AND, so `"brand": ["canon"]` together with `"exists": { "brand": false }` matches nothing. An unknown or unsupported filter name is rejected with an `invalidParameter` error rather than ignored, and at most 50 entries are accepted. Filters that always carry a value — `productType` or `hasParentASIN`, for example — are not supported, because asking whether they exist has no meaningful answer. Supported filter names: | Group | Filters | | --- | --- | | Product attributes | `activeIngredients`, `author`, `binding`, `brand`, `brandStoreName`, `brandStoreUrlName`, `color`, `dealType`, `edition`, `format`, `itemForm`, `itemTypeKeyword`, `languages`, `manufacturer`, `material`, `model`, `partNumber`, `pattern`, `scent`, `size`, `specialIngredients`, `style`, `targetAudienceKeyword`, `type`, `unitType` | | Classification | `categories`, `salesRankDisplayGroup`, `websiteDisplayGroup`, `websiteDisplayGroupName` | | Dimensions & packaging | `itemHeight`, `itemLength`, `itemWeight`, `itemWidth`, `numberOfItems`, `numberOfPages`, `packageHeight`, `packageLength`, `packageQuantity`, `packageWeight`, `packageWidth` | | Sales, fees & coupons | `businessDiscount`, `couponOneTimeAbsolute`, `couponOneTimePercent`, `couponSNSPercent`, `deltaPercent90_monthlySold`, `fbaFees`, `monthlySold`, `monthlySoldPeak`, `returnRate` | | Buy Box statistics | `buyBoxShippingCountry`, `buyBoxStandardDeviation30`, `buyBoxStandardDeviation90`, `buyBoxStandardDeviation365`, `buyBoxStatsTopSellerId30`, `buyBoxStatsTopSellerId90`, `buyBoxStatsTopSellerId180`, `buyBoxStatsTopSellerId365`, `flipability30`, `flipability90`, `flipability365` | | Sellers | `historicalSellerIds`, `sellerIds`, `sellerIdsFBA`, `sellerIdsFBM`, `sellerIdsLowestFBA`, `sellerIdsLowestFBM` | | Dates | `listedSince`, `publicationDate`, `releaseDate` | > **Note:** for the numeric filters, missing is not the same as zero. `"monthlySold_gte": 0` with `"monthlySold_lte": 0` matches products whose value is missing *or* zero; `"exists": { "monthlySold": false }` matches only those where it is missing. ### Category & title filters | Filter | Description | | --- | --- | | `rootCategory` | Only include products listed in these root-categories. Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). Example: `[562066]` | | `categories_include` | Only include products listed directly in these sub-categories. Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). Example: `[3010075031, 12950651, 355007011]` | | `categories_exclude` | Exclude products listed directly in these sub-categories. Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). Example: `[77028031, 186606]` | | `salesRankReference` | [Category node id](https://env.7xmtools.com/api-docs/category-object.html) of the product's salesRankReference category. Example: `562066` | | `title` | Title of the product. Works on a keyword basis, meaning the product's title must contain the specified string's keywords, separated by white space. Supports up to 50 keywords. The search is case-insensitive. Partial keyword matches are not supported. Examples:
• *Digital Camera Canon*: title must contain all three keywords, in any order or position.
• *"Digital Camera" Canon*: title must contain the keyword *Digital Camera* and *Canon*.
• *-digital camera*: title must *not* contain the keyword *digital* and must contain *camera*. | ### Product type, variations & state | Filter | Description | | --- | --- | | `productType` | Determines what data is available for the product. Possible filter values:
• **0** — STANDARD: everything accessible
• **1** — DOWNLOADABLE: no marketplace/3rd party price data
• **2** — EBOOK: no marketplace offers data
• **5** — VARIATION\_PARENT: product is a parent ASIN. Only sales rank and `variations` is set. | | `singleVariation` | If set to `true`, only one variation of a product will be returned. | | `historicalParentASIN` | Find historical children ASINs (variations) for any parent ASIN. Example: `B0FJZJ82ZG` | | `hasParentASIN` | Whether or not the product has a parent ASIN. | | `availabilityAmazon` | Availability of the Amazon offer. Possible values:
• **-1**: no Amazon offer exists
• **0**: Amazon offer is in stock and shippable
• **1**: Amazon offer is currently not in stock, but will be in the future (pre-order)
• **2**: Amazon offer availability is "unknown"
• **3**: Amazon offer is currently not in stock, but will be in the future (back-order)
• **4**: Amazon offer shipping is delayed — see the product's `availabilityAmazonDelay` for more details | | `returnRate` | The customer return rate for a product. Possible values:
• **1**: the product has a low return rate
• **2**: the product has a high return rate | | `hasReviews` | Whether or not the product has reviews. | | `trackingSince_lte` / `_gte` | Indicates the time Keepa started tracking this product, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). Example: `3411319` | | `lastPriceChange_lte` / `_gte` | The last time a price change (any price type) was registered, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | | `lastOffersUpdate_lte` / `_gte` | The time when the offers were last updated (see the [product request's](https://env.7xmtools.com/api-docs/product.html) offers parameter), in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). Can be used to retrieve only products with fresh offers-related data. Example: `3411319` | | `monthlySold_lte` / `_gte` | How often this product was bought in the past month. This field represents the *bought past month* metric found on Amazon search result pages. It is not an estimate. *Undefined* if it has no value. Most ASINs do not have this value set. The value is variation specific. Example: `1000` — the ASIN was bought at least 1000 times in the past month. | | `deltaPercent90_monthlySold_lte` / `_gte` | Percentage change in monthly sales over the last 90 days. Examples: max `15`, min `-10` | ### Product attribute filters (String arrays) Most of these are also available to the [`exists`](https://env.7xmtools.com/api-docs/product-finder.html#exists-filter) filter, to find the products that carry no value for one of them at all. | Filter | Description / Example | | --- | --- | | `manufacturer` | Names of manufacturers. Example: *Canon* | | `brand` | Names of brands. Example: *Canon* | | `partNumber` | Names of part numbers. Example: *DSC-H300/BM-RB* | | `model` | Names of models. Example: *2016* | | `color` | Names of colors. Example: *black* | | `size` | Names of sizes. Example: *large* | | `edition` | Names of editions. Example: *first edition* | | `format` | Names of formats. Example: *cd-rom* | | `author` | Names of authors. Example: *anonymous* | | `binding` | Names of bindings. Example: *paperback* | | `genre` | Names of genres. Example: *horror* | | `languages` | Languages available for the item. Example: *english* | | `publisher` | Publisher of the item. Example: *penguin books* | | `platform` | Platforms the item is available on. Example: *windows* | | `activeIngredients` | Active ingredients in the product. Example: *aloe* | | `specialIngredients` | Special or additional ingredients in the product. Example: *fragrance-free* | | `itemTypeKeyword` | Keywords describing the type of item. Example: *road-running-shoes* | | `targetAudienceKeyword` | Keywords indicating the target audience. Example: *dogs* | | `itemForm` | The form of the item. Example: *liquid* | | `scent` | Scent of the product, if applicable. Example: *lavender* | | `unitType` | Type of unit measurement used. Example: *count* | | `pattern` | Pattern design of the item. Example: *striped* | | `style` | Style or design aesthetic of the item. Example: *modern* | | `material` | Material composition of the item. Example: *cotton* | | `brandStoreName` | Name of the brand's store. Example: `["techworld"]` | | `brandStoreUrlName` | URL-friendly name of the brand's store. Example: `["techworld-store"]` | | `frequentlyBoughtTogether` | Specify an ASIN to retrieve products that are often bought together with it. Example: *B06XFTZGV5* | ### Dimensions & media | Filter | Description | | --- | --- | | `packageHeight` / `packageLength` / `packageWidth` `[_lte, _gte]` | The package's height/length/width in millimeters. Example: `144` | | `packageWeight` `[_lte, _gte]` | The package's weight in grams. Example: `1500` (= 1.5 kg) | | `itemHeight` / `itemLength` / `itemWidth` `[_lte, _gte]` | The item's height/length/width in millimeters. Example: `144` | | `itemWeight` `[_lte, _gte]` | The item's weight in grams. Example: `1500` (= 1.5 kg) | | `variationCount` `[_lte, _gte]` | The number of variations of this product. Example: `1` | | `imageCount` `[_lte, _gte]` | The number of images of this product. Example: `1` | | `videoCount` `[_lte, _gte]` | Number of videos associated with the item. Examples: max `10`, min `1` | | `hasMainVideo` | If the item has a main promotional video, which is part of the product image carousel. Example: `true` | | `hasAPlus` | If the item has A+ content. Example: `false` | | `hasAPlusFromManufacturer` | If the A+ content is provided by the manufacturer or vendor. Example: `true` | | `numberOfItems` `[_lte, _gte]` | The number of items of this product. Example: `1` | | `numberOfPages` `[_lte, _gte]` | The number of pages of this product. Example: `514` | | `publicationDate` `[_lte, _gte]` | The item's publication date, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). Example: `3411319` | | `releaseDate` `[_lte, _gte]` | The item's release date, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). Example: `3411319` | | `variationReviewCount` `[_lte, _gte]` | Number of reviews specific to a variation. Examples: max `100`, min `10` | | `variationRatingCount` `[_lte, _gte]` | Number of ratings specific to a variation. Examples: max `200`, min `20` | ### Product flags (Boolean) | Filter | Description | | --- | --- | | `isHazMat` | Indicates whether the product is classified as hazardous material (HazMat). Example: `true` | | `isHeatSensitive` | Indicates whether the product is classified as heat sensitive (e.g. meltable). Example: `true` | | `isAdultProduct` | Indicates if the item is considered to be for adults only. Example: `true` | | `isEligibleForSuperSaverShipping` | Whether or not the product is eligible for super saver shipping by Amazon. Example: `true` | | `isSNS` | If the product's Buy Box is available for [subscribe and save](https://www.amazon.com/b?node=5856181011). Example: `true` | | `isMerchOnDemand` | If the product is a MerchOnDemand. Example: `true` | | `isPrimeExclusive` | A Prime exclusive offer can only be ordered if the buyer has an active Prime subscription. Example: `true` | | `batteriesRequired` | If the item requires batteries. Example: `true` | | `batteriesIncluded` | If batteries are included with the item. Example: `false` | ### Buy Box & seller filters | Filter | Description | | --- | --- | | `buyBoxIsAmazon` | If the Buy Box is held by Amazon. Example: `true` | | `buyBoxIsFBA` | If the Buy Box is fulfilled by Amazon (FBA). Example: `false` | | `buyBoxIsUnqualified` | If the Buy Box is unqualified. Example: `false` | | `buyBoxIsPreorder` | If the product's Buy Box is a preorder. Example: `true` | | `buyBoxIsBackorder` | If the product's Buy Box is backordered. Example: `true` | | `buyBoxIsPrimeExclusive` | If the product's Buy Box is prime exclusive. Example: `true` | | `buyBoxSellerId` | Seller IDs in the Buy Box. Example: `["ATVPDKIKX0DER"]` | | `buyBoxUsedCondition` | The offer sub-condition of the **used** Buy Box. Example: `[2, 3]`
ValueCondition 2Used - Like New 3Used - Very Good 4Used - Good 5Used - Acceptable | | `buyBoxUsedIsFBA` | If the Used Buy Box is fulfilled by Amazon. Example: `true` | | `buyBoxUsedSellerId` | Seller IDs for used items eligible for the Buy Box. Example: `["ATVPDKIKX0DER"]` | | `sellerIds` | List of seller IDs offering the item. Example: `["ATVPDKIKX0DER"]` | | `sellerIdsLowestFBA` | Seller IDs offering the lowest price via FBA. Example: `["ATVPDKIKX0DER"]` | | `sellerIdsLowestFBM` | Seller IDs offering the lowest price via FBM. Example: `["ATVPDKIKX0DER"]` | | `dealType` | The type of the deal badge. Valid values: `PRIME_DAY`, `PRIME_DAY_EARLY`, `EARLY_ACCESS_WITH_PRIME`, `PRIME_EXCLUSIVE`, `SELLING_FAST`, `PRIME_SELLING_FAST`, `LIMITED_TIME_DEAL`, `COUNTDOWN_ENDS_IN`, `APP_ONLY`, `CLEARANCE_NO_RETURNS`, `SPECIAL_EVENT_SALE`, `GENERIC_OFFER_PROMO`, `UNKNOWN`. Example: `["LIMITED_TIME_DEAL"]` | | `buyBoxStatsAmazon` `[30, 90, 180, 365]` `[_lte, _gte]` | The percentage the Amazon offer held the Buy Box in the given interval. Example: `30` | | `buyBoxStatsTopSeller` `[30, 90, 180, 365]` `[_lte, _gte]` | Buy Box Share % of the seller with highest % won (Amazon included). Example: `30` | | `buyBoxStatsSellerCount` `[30, 90, 180, 365]` `[_lte, _gte]` | Number of sellers with Buy Box ownership in the interval. Example: `2` | ### Stock, coupons & scores | Filter | Description | | --- | --- | | `outOfStockPercentage90` `[_lte, _gte]` | 90-day Amazon out-of-stock percentage. Examples: `0` = never out of stock, `100` = out of stock 100% of the time, `25` = out of stock 25% of the time. A per-price-type form also exists for four types: `outOfStockPercentage90_BB`, `outOfStockPercentage90_BB_USED`, `outOfStockPercentage90_NEW` and `outOfStockPercentage90_USED`, each with `_lte` / `_gte`. | | `outOfStockCountAmazon30` `[_lte, _gte]` | Number of times the item was out of stock on Amazon in the last 30 days. Examples: max `2`, min `1` | | `outOfStockCountAmazon90` `[_lte, _gte]` | Number of times the item was out of stock on Amazon in the last 90 days. Examples: max `5`, min `3` | | `couponOneTimeAbsolute` `[_lte, _gte]` | Absolute value for one-time coupons. Examples: max `50`, min `10` | | `couponOneTimePercent` `[_lte, _gte]` | Percentage value for one-time coupons. Examples: max `20`, min `5` | | `couponSNSPercent` `[_lte, _gte]` | Percentage value for SNS (Subscribe & Save) coupons. Examples: max `15`, min `3` | | `flipability30` / `flipability90` / `flipability365` `[_lte, _gte]` | Flipability score over 30 / 90 / 365 days. Examples: `flipability30` max `80`, min `20`; `flipability90` max `85`, min `25`; `flipability365` max `90`, min `30` | | `businessDiscount` `[_lte, _gte]` | Business discount available. Examples: max `15`, min `5` | | `lightningEnd` `[_lte, _gte]` | Find current and upcoming lightning deals that end within the defined range. In [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | ### Update & lifecycle times All values are [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | Filter | Description | | --- | --- | | `lastUpdate` `[_lte, _gte]` | When Keepa last updated the product. If you do not specify this filter, the query is automatically limited to products updated within the last 6 months. | | `listedSince` `[_lte, _gte]` | When the product was first listed on Amazon, as far as Keepa can determine it. | | `lastRatingUpdate` `[_lte, _gte]` | When the rating and review count were last updated. | | `lastBusinessDiscountUpdate` `[_lte, _gte]` | When the business discount was last updated. | | `lightningStart` `[_lte, _gte]` | Start of the product’s Lightning Deal. Pairs with the documented `lightningEnd`. | | `numberOfTrackings` `[_lte, _gte]` | How many Keepa users track this product — a rough popularity signal. | ### Sales rank filters | Filter | Description | | --- | --- | | `salesRankDrops30` `[_lte, _gte]` | Number of sales rank drops in the last 30 days. | | `salesRankDrops90` `[_lte, _gte]` | Number of sales rank drops in the last 90 days. | | `salesRankDrops180` `[_lte, _gte]` | Number of sales rank drops in the last 180 days. | | `salesRankDrops365` `[_lte, _gte]` | Number of sales rank drops in the last 365 days. | | `salesRankDisplayGroup` | String array. The sales rank display group the product belongs to. Example: `["fashion_display_on_website"]` | | `srAvg` `[_lte, _gte]` | Average sales rank during one specific past month, for the rolling last 36 months. `` is the year modulo 3 (`0`–`2`) and `` is the zero-based month (`00` = January … `11` = December) — e.g. `srAvg003` is April of the year whose number is divisible by 3. Same encoding the [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) request uses for historical lists. | ### Offer counts & Buy Box statistics | Filter | Description | | --- | --- | | `totalOfferCount` `[_lte, _gte]` | Total number of marketplace offers. | | `offerCountFBA` `[_lte, _gte]` | Number of FBA offers. | | `offerCountFBM` `[_lte, _gte]` | Number of FBM offers. | | `buyBoxEligibleOfferCountsNewFBA` `[_lte, _gte]` | Buy Box eligible New FBA offer count. | | `buyBoxEligibleOfferCountsNewFBM` `[_lte, _gte]` | Buy Box eligible New FBM offer count. | | `buyBoxEligibleOfferCountsUsedFBA` `[_lte, _gte]` | Buy Box eligible Used FBA offer count. | | `buyBoxEligibleOfferCountsUsedFBM` `[_lte, _gte]` | Buy Box eligible Used FBM offer count. | | `buyBoxStandardDeviation30` `[_lte, _gte]` | Standard deviation of the Buy Box price over the last 30 days. | | `buyBoxStandardDeviation90` `[_lte, _gte]` | Standard deviation of the Buy Box price over the last 90 days. | | `buyBoxStandardDeviation365` `[_lte, _gte]` | Standard deviation of the Buy Box price over the last 365 days. | | `BUY_BOX_SHIPPING_shipping` `[_lte, _gte]` | Shipping cost of the Buy Box offer, as an integer of the locale’s smallest currency unit. | | `buyBoxIsPrimeEligible` | Boolean. Whether the Buy Box offer is Prime eligible. | | `buyBoxShippingCountry` | String array. Default shipping country of the Buy Box seller. Example: `["US"]` | | `buyBoxStatsTopSellerId30` | String array. Seller IDs that held the Buy Box most often in the last 30 days. | | `buyBoxStatsTopSellerId90` | String array. As above, for the last 90 days. | | `buyBoxStatsTopSellerId180` | String array. As above, for the last 180 days. | | `buyBoxStatsTopSellerId365` | String array. As above, for the last 365 days. | | `sellerIdsFBA` | String array. Seller IDs currently offering the product via FBA. | | `sellerIdsFBM` | String array. Seller IDs currently offering the product via FBM. | | `historicalSellerIds` | String array. Seller IDs that have offered the product at any point, not only currently. | | `isHighestOffer` | Boolean. Whether the selected price is at its highest value. | ### Monthly sold, fees & packaging | Filter | Description | | --- | --- | | `monthlySoldPeak` `[_lte, _gte]` | Highest monthly sold value ever recorded for the product. | | `monthlySoldPeakDate` `[_lte, _gte]` | When that peak occurred, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | | `monthlySoldLastKnown` `[_lte, _gte]` | Most recent non-empty monthly sold value. | | `monthlySoldLastKnownDate` `[_lte, _gte]` | When that value was recorded, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | | `fbaFees` `[_lte, _gte]` | Total FBA pick & pack fee, as an integer of the locale’s smallest currency unit. | | `packageQuantity` `[_lte, _gte]` | Number of items in the package. | | `packageDimension` `[_lte, _gte]` | Combined package dimension, derived from the package length, width and height. | | `itemDimension` `[_lte, _gte]` | Combined item dimension, derived from the item length, width and height. | ### Classification & state | Filter | Description | | --- | --- | | `type` | String array. Amazon’s product type for the item. Example: `["SHIRT"]` | | `websiteDisplayGroup` | String array. The product’s website display group. | | `websiteDisplayGroupName` | String array. The friendlier display group name, and the value the [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) request accepts as a product group. | | `warehouseCondition` | Integer array. Condition of the cheapest Amazon Warehouse offer: `1` New, `2` Used - Like New, `3` Used - Very Good, `4` Used - Good, `5` Used - Acceptable. | | `availabilityAmazonMinDelayInDays` `[_lte, _gte]` | Minimum shipping delay in days of the Amazon offer. | | `outOfStockPercentageInInterval` `[_lte, _gte]` | Out-of-stock percentage over the query’s interval, from `0` to `100`. | | `isDeal` | Boolean. Whether the product currently qualifies as a deal. | | `launchpad` | Boolean. Whether the product is part of Amazon Launchpad. | | `newPriceIsMAP` | Boolean. Whether the New price is hidden on Amazon due to MAP restrictions. | ### Price-type statistics filters These filter families exist for every price type (see the list below). The placeholder `` stands for a price type name such as `AMAZON`, `NEW` or `BUY_BOX_SHIPPING` — e.g. `current_AMAZON_gte`, `avg90_NEW_lte`, `isLowest_BUY_BOX_SHIPPING`. | Filter family | Description | | --- | --- | | `current_` `[_lte, _gte]` | Filter for the current price or value. The price is an integer of the respective Amazon locale's smallest currency unit (e.g., euro cents or yen). | | `delta[1, 7, 30, 90]_` `[_lte, _gte]` | Filter for the absolute difference between the current value and the 1, 7, 30 or 90-day average value. The price is an integer of the respective Amazon locale's smallest currency unit. A negative value filters for prices/values that have increased, and a positive value filters for decreased ones. A **0** filters products with no change. | | `deltaPercent[1, 7, 30, 90]_` `[_lte, _gte]` | Filter for the relative difference between the current value and the 1, 7, 30 or 90-day average value. In percentage between 0 and 100%. A positive value filters for prices/values that have decreased, and a negative value filters for increased ones. A **0** filters products with no change. | | `deltaLast_` `[_lte, _gte]` | Filter for the difference between the current value and the previous value. The price is an integer of the respective Amazon locale's smallest currency unit. A positive value filters for prices/values that have decreased, and a negative value filters for increased ones. A **0** filters products with no change. | | `avg[1, 7, 30, 90, 180, 365]_` `[_lte, _gte]` | Filter for the average price or value of the respective last x days. The price is an integer of the respective Amazon locale's smallest currency unit. | | `lastPriceChange_` `[_lte, _gte]` | The last time a price change of this price type was registered, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/product-finder.html#keepa-time-minutes). | | `backInStock_` | Whether or not the price/value was out of stock in the last 60 days and now has an offer again. (Boolean) | | `isLowest_` | Whether or not the current price/value is the lowest ever. (Boolean) | | `isLowest90_` | Whether or not the current price/value is the lowest in the last 90 days. (Boolean) | #### Available price types The standard price type set — available in the `current`, `delta`, `deltaPercent`, `deltaLast`, `avg30/90/180` and `backInStock` families: `AMAZON`, `NEW`, `USED`, `SALES`, `LISTPRICE`, `COLLECTIBLE`, `REFURBISHED`, `NEW_FBM_SHIPPING`, `LIGHTNING_DEAL`, `WAREHOUSE`, `NEW_FBA`, `COUNT_NEW`, `COUNT_USED`, `COUNT_REFURBISHED`, `COUNT_COLLECTIBLE`, `RATING`, `COUNT_REVIEWS`, `BUY_BOX_SHIPPING`, `USED_NEW_SHIPPING`, `USED_VERY_GOOD_SHIPPING`, `USED_GOOD_SHIPPING`, `USED_ACCEPTABLE_SHIPPING`, `REFURBISHED_SHIPPING`, `TRADE_IN` The `avg365`, `lastPriceChange`, `isLowest` and `isLowest90` families additionally support: `BUY_BOX_USED_SHIPPING`, `EBAY_NEW_SHIPPING`, `EBAY_USED_SHIPPING`, `PRIME_EXCL`, `RENT` > **Note:** The price types correspond to the `csv` history types of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html). ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Response ```json { "asinList": String array, "searchInsights": Search Insights Object, "totalResults": Integer } ``` | Field | Description | | --- | --- | | `asinList` | Ordered array with the result ASINs. | | `searchInsights` | Aggregated metrics calculated over matched products: [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html). Requires the `&stats=1` parameter. | | `totalResults` | Estimated count of all matched products. | ## Examples ### Example query Find products in root category `3167641` with a current Amazon price between € 10.00 and € 50.00, 100 results per page: ```json { "rootCategory": 3167641, "current_AMAZON_lte": 5000, "current_AMAZON_gte": 1000, "perPage": 100, "page": 0 } ``` > **Tip:** A query can also be built by using the [Product Finder](https://env.7xmtools.com/finder) interface on the Keepa website. The current query can be reviewed by clicking on "Show API query" above the result table. **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); ProductFinderRequest finder = new ProductFinderRequest(); finder.rootCategory = new String[]{"3167641"}; finder.current_AMAZON_gte = 1000; // prices in cents finder.current_AMAZON_lte = 5000; finder.perPage = 100; finder.page = 0; api.sendRequest(Request.getProductFinderRequest(AmazonLocale.DE, finder)) .done(result -> { System.out.println(result.asinList.length + " ASINs on this page"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php rootCategory = 3167641; $finder->current_AMAZON_gte = 1000; // prices in cents $finder->current_AMAZON_lte = 5000; $finder->perPage = 100; $finder->page = 0; $response = $api->sendRequestWithRetry(Request::getFinderRequest(AmazonLocale::DE, $finder)); if ($response->status == ResponseStatus::OK) { print_r($response->asinList); } ``` **Python** ```python import requests selection = { "rootCategory": 3167641, "current_AMAZON_lte": 5000, "current_AMAZON_gte": 1000, "perPage": 100, "page": 0, } r = requests.post( "https://api.keepa.com/query", params={"domain": 3, "key": "YOUR_API_KEY"}, json=selection, ) data = r.json() print(data["totalResults"], "matches") print(data["asinList"][:10]) ``` **Node.js** ```javascript const selection = { rootCategory: 3167641, current_AMAZON_lte: 5000, current_AMAZON_gte: 1000, perPage: 100, page: 0, }; const res = await fetch("https://api.keepa.com/query?domain=3&key=YOUR_API_KEY", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(selection), }); const data = await res.json(); console.log(data.totalResults, "matches"); console.log(data.asinList.slice(0, 10)); ``` **cURL (GET)** ```bash # GET: the selection JSON must be URL-encoded (--data-urlencode does this) curl -s -G "https://api.keepa.com/query" \ --data-urlencode "key=YOUR_API_KEY" \ --data-urlencode "domain=3" \ --data-urlencode 'selection={"rootCategory":3167641,"current_AMAZON_lte":5000,"current_AMAZON_gte":1000,"perPage":100,"page":0}' ``` **cURL (POST)** ```bash # POST: the selection JSON is the request body curl -s -X POST "https://api.keepa.com/query?domain=3&key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"rootCategory":3167641,"current_AMAZON_lte":5000,"current_AMAZON_gte":1000,"perPage":100,"page":0}' ``` ### Example with Search Insights (stats=1) Same query, but with aggregated KPIs over the whole result set — note the additional token cost: ```bash curl -s -X POST "https://api.keepa.com/query?domain=3&key=YOUR_API_KEY&stats=1" \ -H "Content-Type: application/json" \ -d '{"rootCategory":3167641,"current_AMAZON_gte":1000,"deltaPercent90_AMAZON_gte":20,"sort":[["current_SALES","asc"]]}' ``` ### Example response ```json { "timestamp": 1783382461000, "tokensLeft": 248, "refillIn": 31000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 11, "processingTimeInMs": 342, "asinList": [ "B0BDHWDR12", "B09XS7JWHH", "B08N5WRWNW", "B07YN82X3B", "B01M0AGIKS" ], "totalResults": 18234 } ``` *Response shortened for readability; illustrative values.* With `&stats=1` the response additionally contains the `searchInsights` field — see the [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html) for a full example. # Browsing Deals Source: https://env.7xmtools.com/api-docs/deals.html Find products that recently changed and match your search criteria. A deal query is a JSON object sent via GET or POST; each request returns up to 150 deals, and paging lets a single query provide up to 10,000 ASINs. GET · POST · 5 tokens per request (up to 150 deals) By accessing our [deals](https://env.7xmtools.com/deals), you can find products that recently changed and match your search criteria. A single request will return a maximum of **150** deals. A query can provide up to **10,000** ASINs using paging. We recommend trying out our [deals page](https://env.7xmtools.com/deals) first to familiarize yourself with the options and results before reading this documentation. > **Note:** Our deals only provide products that were updated within the last **12 hours**. ## Endpoint You can choose between an HTTP GET or POST request. Both take the same `queryJSON` object, described below. ### GET format ``` GET https://api.keepa.com/deal?key=&selection= ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `selection` | required | The query JSON contains all request parameters. It must be **URL-encoded** if the GET format is used. | ### POST format ``` POST https://api.keepa.com/deal?key= ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | POST payload | required | Must contain the `queryJSON` (no URL encoding needed). | > **Tip:** To quickly get a valid `queryJSON`, there is a link on the [deals page](https://env.7xmtools.com/deals) below the filters that generates this JSON for the currently active selection. ## The queryJSON Object The query JSON contains all request parameters. Its full structure: ```json { "page": Integer, "domainId": Integer, "excludeCategories": [Long], "includeCategories": [Long], "priceTypes": [Integer], "deltaRange": [Integer], "deltaPercentRange": [Integer], "deltaLastRange": [Integer], "salesRankRange": [Integer], "currentRange": [Integer], "minRating": Integer, "isLowest": Boolean, "isLowest90": Boolean, "isLowestOffer": Boolean, "isHighest": Boolean, "isOutOfStock": Boolean, "isBackInStock": Boolean, "titleSearch": String, "isRangeEnabled": Boolean, "isFilterEnabled": Boolean, "hasReviews": Boolean, "filterErotic": Boolean, "singleVariation": Boolean, "isRisers": Boolean, "isPrimeExclusive": Boolean, "mustHaveAmazonOffer": Boolean, "mustNotHaveAmazonOffer": Boolean, "warehouseConditions": [Integer], "material": [String], "type": [String], "manufacturer": [String], "brand": [String], "model": [String], "color": [String], "size": [String], "unitType": [String], "scent": [String], "itemForm": [String], "pattern": [String], "style": [String], "itemTypeKeyword": [String], "targetAudienceKeyword": [String], "edition": [String], "format": [String], "author": [String], "binding": [String], "languages": [String], "brandStoreName": [String], "brandStoreUrlName": [String], "websiteDisplayGroup": [String], "websiteDisplayGroupName": [String], "salesRankDisplayGroup": [String], "sortType": Integer, "dateRange": Integer } ``` ## Parameters ### Core parameters | Parameter | Required | Description | | --- | --- | --- | | `page` | optional | Most deal queries have more than 150 results (the maximum page size). To browse all deals found by a query (up to the limit of **10,000**), iterate the `page` parameter while keeping all other parameters identical. Start with `page=0` and stop when the response contains fewer than 150 results.
Example: `"page": 0` | | `domainId` | required | The `domainId` of the Amazon locale to retrieve deals for. Not optional. See the domain ID table below for valid values. | | `priceTypes` | required | Determines the deal type. Not optional: exactly one price type must be specified. Though it is an integer array, it can contain **only one entry** — multiple types per query are not supported. Only the price types listed below carry deal data; any other value is rejected as an invalid `priceTypes`.
Example: `"priceTypes": [0]` | | `dateRange` | optional | Our deals are divided into different sets, determined by the time interval in which the product changed. The shorter the interval, the more recent the change, which is good for significant price drops but may miss slow incremental drops. See the interval table below for valid values.
Example: `"dateRange": 0` | #### Valid `domainId` values | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | #### Valid `priceTypes` values | Value | Price Type | | --- | --- | | **0** | AMAZON: Amazon price | | **1** | NEW: Marketplace New price | | **2** | USED: Marketplace Used price | | **3** | SALES: Sales Rank | | **5** | COLLECTIBLE: Collectible price | | **6** | REFURBISHED: Refurbished price | | **7** | NEW\_FBM\_SHIPPING: New FBM with shipping | | **8** | LIGHTNING\_DEAL: Lightning Deal price | | **9** | WAREHOUSE: Amazon Warehouse price | | **10** | NEW\_FBA: New FBA price | | **18** | BUY\_BOX\_SHIPPING: New Buy Box with shipping | | **19** | USED\_NEW\_SHIPPING: Used - Like New with shipping | | **20** | USED\_VERY\_GOOD\_SHIPPING: Used - Very Good with shipping | | **21** | USED\_GOOD\_SHIPPING: Used - Good with shipping | | **22** | USED\_ACCEPTABLE\_SHIPPING: Used - Acceptable with shipping | | **27** | REFURBISHED\_SHIPPING: Refurbished with shipping | | **32** | BUY\_BOX\_USED\_SHIPPING: Used Buy Box with shipping | | **33** | PRIME\_EXCL: Prime Exclusive Price | > **Note (Lightning Deals, Prime Exclusive, and Warehouse Deals):** The `deltaLast`, `delta` and `deltaPercent` entries for these price types are calculated with the Amazon or New price as the reference price (instead of the same price type’s previous price). #### Valid `dateRange` values | Value | Interval | | --- | --- | | **0** | Day (last 24 hours) | | **1** | Week (last 7 days) | | **2** | Month (last 31 days) | | **3** | 3 Months (last 90 days) | ### Filter options | Parameter | Required | Description | | --- | --- | --- | | `isFilterEnabled` | optional | Switch to enable the filter options.
Example: `"isFilterEnabled": true` | | `excludeCategories` | optional | Used to exclude products listed in these categories. If it’s a subcategory, the product must be **directly** listed in this category; products in child categories of the specified ones will not be excluded unless it’s a root category. Array with up to **500** [category node IDs](https://env.7xmtools.com/api-docs/category-object.html).
Example: `"excludeCategories": [77028031, 186606]` | | `includeCategories` | optional | Used to include only products listed in these categories. Same rules as `excludeCategories`.
Example: `"includeCategories": [3010075031, 12950651, 355007011]` | | `minRating` | optional | Limit to products with a minimum rating. A rating is an integer from **0** to **50** (e.g. 45 = 4.5 stars). If `-1`, the filter is inactive.
Example: `"minRating": 20` (minimum rating of 2 stars) | | `isLowest` | optional | Include only products for which the specified price type is at its lowest value (since tracking began).
Example: `"isLowest": true` | | `isLowest90` | optional | Include only products for which the specified price type is at its lowest value in the past 90 days.
Example: `"isLowest90": true` | | `isLowestOffer` | optional | Include only products if the selected price type is the lowest of all New offers (applicable to Amazon and Marketplace New).
Example: `"isLowestOffer": true` | | `isHighest` | optional | Include only products for which the specified price type is at its highest value (since tracking began).
Example: `"isHighest": true` | | `isOutOfStock` | optional | Include only products that were available to order within the last 24 hours and are now out of stock.
Example: `"isOutOfStock": true` | | `isBackInStock` | optional | Include only products that were previously out of stock and have returned to stock within the last 24 hours.
Example: `"isBackInStock": true` | | `hasReviews` | optional | If `true`, exclude all products with no reviews. If `false`, the filter is inactive.
Example: `"hasReviews": false` | | `filterErotic` | optional | Exclude all products listed as adult items.
Example: `"filterErotic": false` | | `singleVariation` | optional | Provide only a single variation if multiple match the query. The one provided is randomly selected.
Example: `"singleVariation": true` | | `isRisers` | optional | Include only products whose price has been rising over the chosen `dateRange` interval.
Example: `"isRisers": true` | | `isPrimeExclusive` | optional | Include only products flagged as Prime Exclusive.
Example: `"isPrimeExclusive": true` | | `mustHaveAmazonOffer` | optional | Include only products that currently have an offer sold and fulfilled by Amazon.
Example: `"mustHaveAmazonOffer": true` | | `mustNotHaveAmazonOffer` | optional | Include only products that currently have no offer sold and fulfilled by Amazon.
Example: `"mustNotHaveAmazonOffer": true` | | `warehouseConditions` | optional | Include only products available under the specified Amazon Warehouse conditions. Use an array of integer condition codes (e.g. 1 = New, 2 = Used - Like New, 3 = Used - Very Good, 24 = Used - Good, 5 = Used - Acceptable).
Example: `"warehouseConditions": [1, 2]` | #### Product attribute filters These filters match products by their listing attributes. Each is an array of strings; the examples below show typical values. | Parameter | Required | Description | | --- | --- | --- | | `material` | optional | Include only products made of the specified material (e.g. “cotton”).
Example: `"material": ["cotton"]` | | `type` | optional | Include only products matching the specified type (e.g. “shirt”, “dress”). | | `manufacturer` | optional | Include only products from the specified manufacturer. | | `brand` | optional | Include only products from the specified brand. | | `model` | optional | Include only products matching the specified model identifier. | | `color` | optional | Include only products matching the specified color attribute. | | `size` | optional | Include only products matching the specified size (e.g. “small”, “one size”). | | `unitType` | optional | Include only products with the specified unit type (e.g. “count”, “ounce”). | | `scent` | optional | Include only products with the specified scent (e.g. “lavender”, “citrus”). | | `itemForm` | optional | Include only products matching the specified item form (e.g. “liquid”, “sheet”). | | `pattern` | optional | Include only products matching the specified pattern (e.g. “striped”, “solid”). | | `style` | optional | Include only products matching the specified style attribute (e.g. “modern”, “vintage”). | | `itemTypeKeyword` | optional | Include only products matching the specified item type keyword (custom search term, e.g. “books”, “prints”). | | `targetAudienceKeyword` | optional | Include only products targeting the specified audience (e.g. “kids”, “professional”). | | `edition` | optional | Include only products matching the specified edition (e.g. “first edition”, “standard edition”). | | `format` | optional | Include only products in the specified format (e.g. “kindle ebook”, “import”, “dvd”). | | `author` | optional | Include only products by the specified author (applicable to books, music, etc.). | | `binding` | optional | Include only products with the specified binding type (e.g. “paperback”). | | `languages` | optional | Include only products available in the specified languages. Use an array of language names. | | `brandStoreName` | optional | Include only products sold under the specified brand store name on Amazon. | | `brandStoreUrlName` | optional | Include only products sold under the specified URL-friendly brand store identifier. | | `websiteDisplayGroup` | optional | Include only products in the specified website display group. | | `websiteDisplayGroupName` | optional | Include only products in the specified website display group name (a more user-friendly label). | | `salesRankDisplayGroup` | optional | Include only products belonging to the specified sales rank display group (e.g. “fashion\_display\_on\_website”). | ### Range options All range options are integer arrays with two entries: `[min, max]`. | Parameter | Required | Description | | --- | --- | --- | | `isRangeEnabled` | optional | Switch to enable the range options.
Example: `"isRangeEnabled": true` | | `currentRange` | optional | Limit the range of the current value of the price type.
Example: `"currentRange": [105, 50000]` (min price $1.05, max price $500) | | `deltaRange` | optional | Limit the range of the difference between the weighted average value and the current value over the chosen `dateRange` interval.
Example: `"deltaRange": [0, 999]` (max difference of $9.99) | | `deltaPercentRange` | optional | Same as `deltaRange`, but in percent. Minimum percent is **10%**; for Sales Rank, it is **80%**.
Example: `"deltaPercentRange": [30, 80]` (between 30% and 80%) | | `deltaLastRange` | optional | Limit the range of the absolute difference between the previous value and the current one.
Example: `"deltaLastRange": [100, 500]` (last change between $1 and $5 price decrease) | | `salesRankRange` | optional | Limit the Sales Rank range of the product. Identical to `currentRange` if the price type is set to Sales Rank. If you want to keep the upper bound open, you can specify `-1` (which translates to the maximum integer value).
**Important:** once this range option is used, all products with no Sales Rank will be excluded. Set it to `null` or leave it out to not use it.
Examples: `"salesRankRange": [0, 5000]` (Sales Rank between 0 and 5000), `"salesRankRange": [5000, -1]` (Sales Rank higher than 5000) | ### Search and sort options | Parameter | Required | Description | | --- | --- | --- | | `titleSearch` | optional | Select deals by a keyword-based product title search. The search is case-insensitive and supports up to **50** keywords. If multiple keywords are specified (separated by a space), all must match.
Example: `"titleSearch": "samsung galaxy"` (matches products with both “samsung” AND “galaxy” in the title) | | `sortType` | optional | Determines the sort order of the retrieved deals. To invert the sort order, use negative values. See the sort type table below for valid values. | #### Valid `sortType` values | Value | Sort By | Order | | --- | --- | --- | | **1** | Deal age | Newest deals first (not invertible) | | **2** | Absolute delta | Highest delta to lowest | | **3** | Sales Rank | Lowest rank to highest | | **4** | Percentage delta | Highest percent to lowest | ## Token Cost **5 tokens** per request, providing up to **150** deals. To retrieve more than 150 results, issue additional requests with an incremented `page` parameter (5 tokens each); a single query can provide up to 10,000 ASINs this way. ## Response The response contains a `deals` field with the following content: ```json { "dr": [deal objects], "categoryIds": [Long], "categoryNames": [String], "categoryCount": [Integer] } ``` | Field | Description | | --- | --- | | `dr` | Ordered array of all [deal objects](https://env.7xmtools.com/api-docs/deal-object.html) matching your query. | | `categoryIds` | Includes all root `categoryIds` of the matched deal products. The returned categories will update based on any filters used in your query, except for category filters. If category filters are applied, they will not affect the returned category information. | | `categoryNames` | Includes all root category names of the matched deal products. The returned category names will update based on any filters used, other than category filters. If category filters are used, they will not affect the returned category information. | | `categoryCount` | Indicates the number of deal products found in each respective root category. This count updates based on any filters used except for category filters. Applying category filters will not affect the returned category information. | > **Note:** Each deal product is listed in a single root category. The arrays `categoryIds`, `categoryNames` and `categoryCount` are related by their index positions. If the root category of a product cannot be determined, it will be listed in the category with the name `"?"` and the ID `9223372036854775807`. Example of one index: ID `165793011`, name `"Toys & Games"`, count `40`. For more information about categories, visit the [Category Object](https://env.7xmtools.com/api-docs/category-object.html) page. ## Examples ### Example queryJSON A complete query selecting Amazon-price deals on amazon.com from one included root category, sorted by percentage delta over the last week: ```json { "page": 0, "domainId": 1, "excludeCategories": [1064954, 11091801], "includeCategories": [16310101], "priceTypes": [0], "deltaRange": [0, 10000], "deltaPercentRange": [20, 100], "deltaLastRange": null, "salesRankRange": [0, 40000], "currentRange": [500, 40000], "minRating": -1, "isLowest": false, "isLowestOffer": false, "isOutOfStock": false, "titleSearch": null, "isRangeEnabled": true, "isFilterEnabled": false, "filterErotic": true, "hasReviews": false, "singleVariation": true, "sortType": 4, "dateRange": 1 } ``` ### Example request Using GET, the `queryJSON` must be URL-encoded and passed in the `selection` parameter. A minimal query `{"page":0,"domainId":1,"priceTypes":[0],"dateRange":1}` becomes: ```bash curl -s "https://api.keepa.com/deal?key=YOUR_API_KEY&selection=%7B%22page%22%3A0%2C%22domainId%22%3A1%2C%22priceTypes%22%3A%5B0%5D%2C%22dateRange%22%3A1%7D" ``` Using POST, the query is sent as the request payload — usually the more convenient option for larger queries: **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); DealRequest dealQuery = new DealRequest(); dealQuery.page = 0; dealQuery.domainId = 1; // amazon.com dealQuery.priceTypes = new int[]{0}; // AMAZON price type dealQuery.dateRange = 1; // interval: last week dealQuery.isRangeEnabled = true; dealQuery.currentRange = new int[]{500, 40000}; dealQuery.deltaPercentRange = new int[]{20, 100}; dealQuery.sortType = 4; api.sendRequest(Request.getDealsRequest(dealQuery)) .done(result -> { for (Deal deal : result.deals.dr) { System.out.println(deal.asin + " " + deal.title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php page = 0; $dealQuery->domainId = 1; // amazon.com $dealQuery->priceTypes = [0]; // AMAZON price type $dealQuery->dateRange = 1; // interval: last week $dealQuery->isRangeEnabled = true; $dealQuery->currentRange = [500, 40000]; $dealQuery->deltaPercentRange = [20, 100]; $dealQuery->sortType = 4; $response = $api->sendRequestWithRetry(Request::getDealsRequest($dealQuery)); if ($response->status == ResponseStatus::OK) { foreach ($response->deals->dr as $deal) { echo $deal->asin . " " . $deal->title . PHP_EOL; } } ``` **Python** ```python import requests query = { "page": 0, "domainId": 1, "priceTypes": [0], "dateRange": 1, "isRangeEnabled": True, "currentRange": [500, 40000], "deltaPercentRange": [20, 100], "sortType": 4, } r = requests.post("https://api.keepa.com/deal", params={"key": "YOUR_API_KEY"}, json=query) data = r.json() for deal in data["deals"]["dr"]: print(deal["asin"], deal["title"]) ``` **Node.js** ```javascript const query = { page: 0, domainId: 1, priceTypes: [0], dateRange: 1, isRangeEnabled: true, currentRange: [500, 40000], deltaPercentRange: [20, 100], sortType: 4 }; const res = await fetch("https://api.keepa.com/deal?key=YOUR_API_KEY", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(query) }); const data = await res.json(); for (const deal of data.deals.dr) console.log(deal.asin, deal.title); ``` **cURL** ```bash curl -s -X POST "https://api.keepa.com/deal?key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"page":0,"domainId":1,"priceTypes":[0],"dateRange":1,"isRangeEnabled":true,"currentRange":[500,40000],"deltaPercentRange":[20,100],"sortType":4}' ``` ### Paging through all results Iterate `page` starting at 0, keeping all other parameters identical, and stop once a response contains fewer than 150 deals (5 tokens per request, up to 10,000 ASINs in total): ```python page = 0 all_deals = [] while True: query["page"] = page r = requests.post("https://api.keepa.com/deal", params={"key": "YOUR_API_KEY"}, json=query) dr = r.json()["deals"]["dr"] all_deals.extend(dr) if len(dr) < 150: break # last page reached page += 1 ``` ### Example response ```json { "timestamp": 1753651260000, "tokensLeft": 55, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 5, "processingTimeInMs": 91, "deals": { "dr": [ { "asin": "B0F3GWXLTS", "title": "Stainless Steel Insulated Water Bottle, 32 oz", "creationDate": 7663480, "categories": [16310101, 2251595011], "rootCat": 16310101, "current": [1999, 2499, -1, 4123], "currentSince": [7663480, 7660110, -1, 7663465], "delta": [[500, 350, -1, 1200], [780, 410, -1, 2050]], "deltaPercent": [[20, 12, -1, 23], [28, 14, -1, 33]], "deltaLast": [-500, 0, -1, 0], "avg": [[2499, 2849, -1, 5323], [2779, 2910, -1, 6173]], "lastUpdate": 7663510, "lightningEnd": 0, "image": [54, 49, 107, 51, 76, 97, 121, 55, 74, 85, 76, 46, 106, 112, 103] } ], "categoryIds": [16310101, 165793011], "categoryNames": ["Grocery & Gourmet Food", "Toys & Games"], "categoryCount": [97, 40] } } ``` Response shortened for readability; illustrative values. Prices are integers in the smallest currency unit (e.g. `1999` = $19.99), timestamps like `creationDate` are in Keepa Time minutes, and `image` is an array of US-ASCII character codes (here decoding to `61k3Lay7JUL.jpg`). See the [Deal Object](https://env.7xmtools.com/api-docs/deal-object.html) page for the full structure of the entries in `dr`. # Best Sellers Source: https://env.7xmtools.com/api-docs/best-sellers.html Retrieve an ASIN list of the most popular products based on sales in a specific category or product group, ordered starting with the best-selling product. GET · 50 tokens per request The Best Sellers request returns an ASIN list of the most popular products based on sales in a specific category or product group. > **Note:** Keepa cannot always correctly identify the sales rank reference category, so some products may be misplaced. ## List types & behavior - **Root category lists** (e.g., “Home & Kitchen”) contain up to **500,000** ASINs. For a list of all available root categories, use the [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html) with the `categoryId` **0**. - **Sub-category lists** (e.g., “Home Entertainment Furniture”) contain up to **10,000** ASINs. By default, sub-category lists are created based on the product’s primary sales rank and do not reflect the actual ordering on Amazon. See the [`sublist` parameter](https://env.7xmtools.com/api-docs/best-sellers.html#param-sublist). - **Product group lists** (e.g., “Beauty”) contain up to **500,000** ASINs. A product group is identified by the `websiteDisplayGroupName` field of the [product object](https://env.7xmtools.com/api-docs/product-object.html). - **Updates:** Lists are usually updated hourly. - **Ordering:** Lists are ordered starting with the best-selling product. Since lists are cached for up to one hour, the ordering may be outdated. - **Exclusions:** Products without an accessible sales rank are not included. ## Endpoint ``` GET https://api.keepa.com/bestsellers?key=&domain=&category=&range= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/best-sellers.html#domain-ids) below. | | `category` | required | The category node ID for which you want the best sellers list. You can find category node IDs via the [Category Search](https://env.7xmtools.com/api-docs/category-search.html), the [Deals](https://env.7xmtools.com/deals) page (select the category and click on “Show API query”), or directly on Amazon. Alternatively, you can provide a product group (e.g., `Beauty`), which can be found in the `websiteDisplayGroupName` field of the [product object](https://env.7xmtools.com/api-docs/product-object.html). | | `range` | optional | Retrieve a best seller list based on a sales rank average instead of the current sales rank. Valid values: **0** (use current rank), **30** (30-day average), **90** (90-day average), **180** (180-day average). | | `month` & `year` | optional | Request a historical best seller list for a specific month. Both parameters must be specified together; must not be combined with `range`. See [details](https://env.7xmtools.com/api-docs/best-sellers.html#param-month-year). | | `variations` | optional | Controls whether items with multiple variations are returned as a single representative variation or as all variations. See [details](https://env.7xmtools.com/api-docs/best-sellers.html#param-variations). | | `sublist` | optional | Create the best seller list based on the sub-category sales rank instead of the primary sales rank. See [details](https://env.7xmtools.com/api-docs/best-sellers.html#param-sublist). | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ### `month` & `year` Request a historical best seller list for a specific month, based on the average rank during that month. Keepa maintains lists for the last **36 months**. Requests for the current calendar month or any month beyond 36 months ago are not permitted. > **Note:** If using these parameters, both `month` and `year` must be specified. The `range` parameter must not be used concurrently. | Parameter | Valid values | | --- | --- | | `month` | Integer between **1** and **12**, representing January to December. | | `year` | 4-digit year (e.g., **2024**). | Examples: `month=6&year=2024` (June 2024), `month=11&year=2023` (November 2023). ### `variations` Controls whether items with multiple variations are returned as a single representative variation or as all variations. By default, one variation per parent is returned, restricting list entries to a single variation. If the variations share the same sales rank, the representative is the variation with the highest monthly units sold (if that data point is available). If monthly sold data is missing or tied, the representative falls back to a randomly picked one. | Value | Behavior | | --- | --- | | **0** | Collapse to one variation per parent (default). Selection rule: sales rank, then highest monthly units sold. | | **1** | Return all variations. | ### `sublist` By default, the best seller list for sub-categories is created based on the product’s primary sales rank, if available. To request a best seller list based on the sub-category sales rank (classification rank), use the `sublist` parameter with the value **1**. The `range`, `month`, and `year` parameters must not be used concurrently. > **Note:** Not all products have a primary sales rank or a sub-category sales rank, and not all sub-category levels have sales ranks. | Value | Behavior | | --- | --- | | **0** | List is based on the primary rank (default). | | **1** | List is based on the sub-category rank. | ## Token Cost A Best Sellers request costs a flat **50 tokens**. - If **no list** for the specified category and locale exists in Keepa’s system, the response will be empty and **no tokens** will be consumed. - If a **valid list** is found but contains zero products (an empty list), the token cost of **50** will still be deducted from your account. Tokens are consumed based on the successful execution and delivery of the query results, regardless of the number of ASINs returned in the list. ## Response The response contains a `bestSellersList` field with a [Best Sellers object](https://env.7xmtools.com/api-docs/best-sellers-object.html). If no list for the specified category and locale exists in Keepa’s system, the response will be empty and no tokens will be consumed. ## Examples ### Best sellers of a category Retrieve the current best sellers list of the “Camera & Photo” category (node `281052`) on amazon.com: ``` https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=281052 ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getBestSellersRequest(AmazonLocale.US, 281052); api.sendRequest(r) .done(result -> { String[] asins = result.bestSellersList.asinList; System.out.println("Best seller: " + asins[0]); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getBestSellerRequest(AmazonLocale::US, "281052")); if ($response->status == ResponseStatus::OK) { print_r($response->bestSellersList->asinList); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "category": 281052} r = requests.get("https://api.keepa.com/bestsellers", params=params) data = r.json() best_sellers = data["bestSellersList"]["asinList"] print(f"Top ASIN: {best_sellers[0]} ({len(best_sellers)} ASINs total)") ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=281052"); const data = await res.json(); const bestSellers = data.bestSellersList.asinList; console.log(`Top ASIN: ${bestSellers[0]} (${bestSellers.length} ASINs total)`); ``` **cURL** ```bash curl -s "https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=281052" ``` ### Example response ```json { "timestamp": 1753641000000, "tokensLeft": 4250, "refillIn": 32000, "refillRate": 300, "tokenFlowReduction": 0, "tokensConsumed": 50, "processingTimeInMs": 21, "bestSellersList": { "domainId": 1, "lastUpdate": 7663320, "categoryId": 281052, "asinList": [ "B0F3GWXLTS", "B0BDHWDR12", "B07XJ8C8F5", "B08N5WRWNW", "B09G9FPHY6", "B01M8L5Z3Y", "B07PGL2ZSL", "B0863TXGM3" ] } } ``` *Response shortened for readability; illustrative values.* A real root category list can contain up to 500,000 ASINs. `lastUpdate` is in Keepa Time minutes. ### Other request modes Best sellers based on the **90-day sales rank average** instead of the current rank: ``` https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=281052&range=90 ``` **Historical** best sellers list for June 2024 (average rank during that month; `range` must not be used concurrently): ``` https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=281052&month=6&year=2024 ``` Best sellers of a **product group**, passing the `websiteDisplayGroupName` value from the [product object](https://env.7xmtools.com/api-docs/product-object.html) instead of a category node ID: ``` https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=Beauty ``` Sub-category list based on the **sub-category sales rank** (classification rank) instead of the primary rank, including **all variations**: ``` https://api.keepa.com/bestsellers?key=YOUR_API_KEY&domain=1&category=3236451011&sublist=1&variations=1 ``` # Category Lookup Source: https://env.7xmtools.com/api-docs/category-lookup.html Retrieve [category objects](https://env.7xmtools.com/api-docs/category-object.html) and optionally their parent tree using a category ID. GET · 1 token per request (up to 10 categories) Given one or more Amazon category node IDs, this request returns the matching [category objects](https://env.7xmtools.com/api-docs/category-object.html). If requested, it also returns every category on the path from each category up to the root of the category tree, so you can reconstruct the full tree by traversing the parents. > **Note:** We cannot provide any data for promotional categories (e.g., Launchpad). ## Endpoint ``` GET https://api.keepa.com/category?key=&domain=&category=&parents= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/category-lookup.html#domain-ids) below. | | `category` | required | The category node ID of the category you want to request.
• For batch requests, use a comma-separated list of IDs (up to **10**). **Token cost remains the same.**
• Alternatively, you can specify the value **0** to retrieve a list of all root categories. | | `parents` | required | Whether or not to include the category tree for each category. Valid values:
• `1` — include parent categories.
• `0` — do not include parent categories. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost A category lookup costs **1 token** per request. Batch requests with a comma-separated list of up to 10 category IDs cost the same 1 token, as does requesting all root categories with `category=0`. ## Response *Identical to the [Category Search](https://env.7xmtools.com/api-docs/category-search.html) response.* The response contains: - A `categories` field with all found [category objects](https://env.7xmtools.com/api-docs/category-object.html). - If the `parents` parameter was set to `1`, a `categoryParents` field with all category objects found on the way to the tree's root. You can construct a category tree by traversing the parents. Both fields are maps in the format ``: ```json { "": categoryObject, "": categoryObject, ... } ``` ## Examples ### Example request Look up the category *Digital Cameras* (node ID `281052`) on amazon.com, including its parent tree: ```bash https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052&parents=1 ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getCategoryLookupRequest(AmazonLocale.US, true, 281052); api.sendRequest(r) .done(result -> { System.out.println(result.categories.get(281052L).name); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getCategoryLookupRequest(AmazonLocale::US, true, "281052")); if ($response->status == ResponseStatus::OK) { print_r($response->categories); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "category": 281052, "parents": 1} r = requests.get("https://api.keepa.com/category", params=params) data = r.json() category = data["categories"]["281052"] print(category["name"], "- parent:", category["parent"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052&parents=1"); const data = await res.json(); const category = data.categories["281052"]; console.log(category.name, "- parent:", category.parent); ``` **cURL** ```bash curl -s "https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052&parents=1" ``` ### Example response ```json { "timestamp": 1783382461000, "tokensLeft": 299, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 1, "processingTimeInMs": 12, "categories": { "281052": { "domainId": 1, "catId": 281052, "name": "Digital Cameras", "websiteDisplayGroup": "photo_display_on_website", "children": [3109924011, 7242008011, 3017941, 2476680011, 330405011, 2476681011, 3109925011], "parent": 502394, "isBrowseNode": true, "highestRank": 2452122, "lowestRank": 1, "productCount": 148632, "avgBuyBox": 45999, "avgBuyBox90": 46750, "avgBuyBox365": 47210, "avgBuyBoxDeviation": 2450, "avgReviewCount": 235, "avgRating": 43, "isFBAPercent": 65.5, "soldByAmazonPercent": 22.4, "hasCouponPercent": 10.2, "avgOfferCountNew": 3.5, "avgOfferCountUsed": 1.2, "sellerCount": 452, "brandCount": 120, "avgDeltaPercent30BuyBox": 2.1, "avgDeltaPercent90BuyBox": 3.4, "avgDeltaPercent30Amazon": 0.8, "avgDeltaPercent90Amazon": 1.5, "relatedCategories": [672123011, 281407, 11057241], "topBrands": ["Sony", "Canon", "Panasonic"] } }, "categoryParents": { "502394": { "domainId": 1, "catId": 502394, "name": "Camera & Photo", "children": [281052, 499532, 3347871], "parent": 172282, "isBrowseNode": true }, "172282": { "domainId": 1, "catId": 172282, "name": "Electronics", "websiteDisplayGroup": "ce_display_on_website", "children": [502394, 172623, 172541], "parent": 0, "isBrowseNode": true } } } ``` *Response shortened for readability; illustrative values.* The `categoryParents` entries are abridged category objects here — the API returns full [category objects](https://env.7xmtools.com/api-docs/category-object.html) for each entry. A `parent` value of `0` marks a root category. ### Other request variants Batch lookup of up to 10 categories in one request (still 1 token): ```bash https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052,502394,172282&parents=0 ``` List all root categories of a locale by passing `category=0`: ```bash https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=0&parents=0 ``` > **Tip:** The keys of the `categories` and `categoryParents` maps are the category IDs as JSON object keys (strings), while each object's `catId` field holds the numeric ID. # Category Search Source: https://env.7xmtools.com/api-docs/category-search.html Search for Amazon category names. Retrieves up to 50 matching [category objects](https://env.7xmtools.com/api-docs/category-object.html). GET · 1 token per search The category search finds Amazon categories whose names match your search term and returns up to **50** matching [category objects](https://env.7xmtools.com/api-docs/category-object.html). It uses the same `/search` endpoint as the [product search](https://env.7xmtools.com/api-docs/product-search.html), selected via the `type=category` parameter. ## Endpoint ``` GET https://api.keepa.com/search?key=&domain=&type=category&term= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/category-search.html#domain-ids) below. | | `type` | required | Must be set to `category` to perform a category search. | | `term` | required | The term you want to search for. Should be [URL encoded](https://en.wikipedia.org/wiki/Percent-encoding). Multiple space-separated keywords are possible, and all provided keywords must match. The minimum length of a keyword is **3** characters. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost A category search costs **1 token** per request. ## Response *Identical to the [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html) response.* The response contains a `categories` field with all matching [category objects](https://env.7xmtools.com/api-docs/category-object.html) (up to 50) in the format: ```json { "": categoryObject, "": categoryObject, ... } ``` ## Examples ### Example request Search the amazon.com locale (`domain=1`) for categories matching the term `camera`: ```bash https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=category&term=camera ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getCategorySearchRequest(AmazonLocale.US, "camera", false); api.sendRequest(r) .done(result -> { result.categories.forEach((id, category) -> System.out.println(id + " " + category.name)); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getCategorySearchRequest(AmazonLocale::US, "camera", false)); if ($response->status == ResponseStatus::OK) { print_r($response->categories); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "type": "category", "term": "camera"} r = requests.get("https://api.keepa.com/search", params=params) data = r.json() for cat_id, category in data["categories"].items(): print(cat_id, category["name"]) ``` **Node.js** ```javascript const term = encodeURIComponent("camera"); const res = await fetch(`https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=category&term=${term}`); const data = await res.json(); for (const [catId, category] of Object.entries(data.categories)) { console.log(catId, category.name); } ``` **cURL** ```bash curl -s "https://api.keepa.com/search?key=YOUR_API_KEY&domain=1&type=category&term=camera" ``` > **Tip:** To search with multiple keywords, URL encode the spaces — e.g. `term=digital%20cameras` for *digital cameras*. All provided keywords must match, and each keyword must be at least 3 characters long. HTTP libraries such as Python's `requests` (via `params`) or JavaScript's `encodeURIComponent` handle the encoding for you. ### Example response ```json { "timestamp": 1783382461000, "tokensLeft": 299, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 1, "processingTimeInMs": 14, "categories": { "281052": { "domainId": 1, "catId": 281052, "name": "Digital Cameras", "websiteDisplayGroup": "photo_display_on_website", "children": [3109924011, 7242008011, 3017941, 2476680011, 330405011, 2476681011, 3109925011], "parent": 502394, "isBrowseNode": true, "highestRank": 2452122, "lowestRank": 1, "productCount": 148632, "avgBuyBox": 45999, "avgBuyBox90": 46750, "avgBuyBox365": 47210, "avgBuyBoxDeviation": 2450, "avgReviewCount": 235, "avgRating": 43, "isFBAPercent": 65.5, "soldByAmazonPercent": 22.4, "hasCouponPercent": 10.2, "avgOfferCountNew": 3.5, "avgOfferCountUsed": 1.2, "sellerCount": 452, "brandCount": 120, "avgDeltaPercent30BuyBox": 2.1, "avgDeltaPercent90BuyBox": 3.4, "avgDeltaPercent30Amazon": 0.8, "avgDeltaPercent90Amazon": 1.5, "relatedCategories": [672123011, 281407, 11057241], "topBrands": ["Sony", "Canon", "Panasonic"] }, "502394": { "domainId": 1, "catId": 502394, "name": "Camera & Photo", "children": [281052, 499532, 3347871], "parent": 172282, "isBrowseNode": true, "highestRank": 3187540, "lowestRank": 1, "productCount": 812345 } } } ``` *Response shortened for readability; illustrative values.* A real search returns up to 50 matching categories, each as a full [category object](https://env.7xmtools.com/api-docs/category-object.html) (the second entry is abridged here). Prices such as `avgBuyBox` are integers in the smallest currency unit (e.g. cents); the keys of the `categories` map are the category IDs as JSON object keys (strings), while each object's `catId` field holds the numeric ID. # Seller Information Source: https://env.7xmtools.com/api-docs/seller.html Retrieve [seller objects](https://env.7xmtools.com/api-docs/seller-object.html) by seller ID — optionally including the seller's storefront, a list of ASINs the merchant is listing on Amazon. GET · 1 token per seller (+9 for storefront) This API retrieves the [seller object](https://env.7xmtools.com/api-docs/seller-object.html) using the seller ID. If a seller is not found in our database, no tokens will be consumed and no data will be provided. > **Looking for seller IDs?** The [Seller Finder](https://env.7xmtools.com/api-docs/seller-finder.html) searches the seller database by name, business details, ratings, fulfilment and catalogue profile, and returns the seller IDs this request expects. ## Endpoint ``` GET https://api.keepa.com/seller?key=&domain=&seller= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the table of valid domain IDs below. | | `seller` | required | The seller ID of the merchant you want to request. For batch requests, provide a comma-separated list of seller IDs (up to **100**). The seller ID is part of the [offer object](https://env.7xmtools.com/api-docs/offer-object.html) and can also be found on Amazon's seller profile pages in the `seller` parameter of the URL. Example: seller ID **A2L77EE7U53NWQ** — [Amazon.com Warehouse Deals](https://www.amazon.com/sp?marketplaceID=ATVPDKIKX0DER&seller=A2L77EE7U53NWQ). | | `storefront` | optional | Include an ASIN list of the items the seller is listing. Valid values: **0** (false), **1** (true). Additional token cost: **9**. Example: `&storefront=1`. See [the storefront parameter](https://env.7xmtools.com/api-docs/seller.html#storefront-parameter) below for details. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ### The `storefront` parameter If specified and set to `1`, the seller object will contain additional information about the items the seller is listing on Amazon, including: - A list of ASINs (`asinList`) - Last-seen timestamps for each ASIN (`asinListLastSeen`) If no data is available, no additional tokens will be consumed. - The ASIN list can contain up to **100,000** items. - Using the `storefront` parameter does **not** trigger any new data collection and does **not** increase the processing time of the request. > **Important:** Seller ID batch requests are **not allowed** when requesting the storefront and will cause an error if submitted. ### About the storefront The storefront of a seller is a list of items the merchant is offering on Amazon. Keepa provides ASINs that are currently listed, as well as ASINs this merchant has listed within the past 7 days. #### Collection through the Keepa database - Seller ASINs are collected daily by scanning the Keepa database for products sold by the seller. - Popular ASINs and competitive offers are more likely to be included. - Utilizing Keepa's vast offers database allows collecting more ASINs than Amazon's storefront page displays. - However, the fewer items a seller is listing, the less likely Keepa has recently tracked any of their offers. - The ASIN lists may be incomplete, and data may be outdated. - If the storefront is requested via the `storefront` parameter, this list will always be included in the seller object unless there is no data or the seller has no items. - A storefront ASIN list can contain up to **100,000** ASINs, sorted by the last time an active offer by the seller was verified (freshest first). - Each ASIN in the list comes with a last-seen timestamp. ## Token Cost - **1 token** per requested seller. - If a seller is not found in the database, **no tokens** are consumed and no data is provided. - Requesting the storefront (`storefront=1`) costs an additional **9 tokens**. If no storefront data is available, no additional tokens are consumed. **Total token cost with `storefront=1`:** - If storefront data is available and contains at least 2 ASINs: **1** (seller object) + **9** (storefront data) = **10** tokens. - Otherwise: **1** token for the seller object. ## Response The response contains a `sellers` field with a map of [seller objects](https://env.7xmtools.com/api-docs/seller-object.html). Within this map: - Each **key** corresponds to a `sellerId`. - Each **value** is the associated seller object. - If no sellers are found, this map will be empty. - If any specified `sellerId` is invalid, an error will be indicated within the error field. ## Examples ### Basic seller request Request the seller object for the Amazon.com Warehouse Deals merchant (seller ID `A2L77EE7U53NWQ`, domain 1 = amazon.com): ```bash https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getSellerRequest(AmazonLocale.US, "A2L77EE7U53NWQ"); api.sendRequest(r) .done(result -> { Seller seller = result.sellers.get("A2L77EE7U53NWQ"); System.out.println(seller.sellerName); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getSellerRequest(AmazonLocale::US, ["A2L77EE7U53NWQ"])); if ($response->status == ResponseStatus::OK) { print_r($response->sellers); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "seller": "A2L77EE7U53NWQ"} r = requests.get("https://api.keepa.com/seller", params=params) data = r.json() print(data["sellers"]["A2L77EE7U53NWQ"]["sellerName"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ"); const data = await res.json(); console.log(data.sellers["A2L77EE7U53NWQ"].sellerName); ``` **cURL** ```bash curl -s "https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ" ``` For a batch request, pass a comma-separated list of up to 100 seller IDs (not allowed together with `storefront`): ```bash https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ,A3EX3RPFGJNC29 ``` ### Example response ```json { "timestamp": 1753560000000, "tokensLeft": 273, "refillIn": 32000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 1, "processingTimeInMs": 12, "sellers": { "A2L77EE7U53NWQ": { "sellerId": "A2L77EE7U53NWQ", "sellerName": "Amazon Warehouse", "domainId": 1, "trackingSince": 5236320, "lastUpdate": 7661520, "hasFBA": true } } } ``` Response shortened for readability; illustrative values. Timestamps such as `trackingSince` and `lastUpdate` are in Keepa Time minutes. All seller object fields are described on the [Seller Object](https://env.7xmtools.com/api-docs/seller-object.html) page. ### Storefront request Request the same seller including its storefront ASIN list (`storefront=1`, costs up to 10 tokens in total): ```bash https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ&storefront=1 ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getSellerRequest(AmazonLocale.US, "A2L77EE7U53NWQ", true) // storefront; api.sendRequest(r) .done(result -> { Seller seller = result.sellers.get("A2L77EE7U53NWQ"); System.out.println(seller.asinList.length + " storefront ASINs"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getSellerRequest(AmazonLocale::US, ["A2L77EE7U53NWQ"], true)); if ($response->status == ResponseStatus::OK) { $seller = $response->sellers["A2L77EE7U53NWQ"]; echo count($seller->asinList) . " storefront ASINs"; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "seller": "A2L77EE7U53NWQ", "storefront": 1} r = requests.get("https://api.keepa.com/seller", params=params) seller = r.json()["sellers"]["A2L77EE7U53NWQ"] print(len(seller["asinList"]), "storefront ASINs") ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ&storefront=1"); const data = await res.json(); const seller = data.sellers["A2L77EE7U53NWQ"]; console.log(seller.asinList.length, "storefront ASINs"); ``` **cURL** ```bash curl -s "https://api.keepa.com/seller?key=YOUR_API_KEY&domain=1&seller=A2L77EE7U53NWQ&storefront=1" ``` ### Example response with storefront ```json { "timestamp": 1753560060000, "tokensLeft": 263, "refillIn": 28000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 10, "processingTimeInMs": 18, "sellers": { "A2L77EE7U53NWQ": { "sellerId": "A2L77EE7U53NWQ", "sellerName": "Amazon Warehouse", "domainId": 1, "trackingSince": 5236320, "lastUpdate": 7661520, "hasFBA": true, "asinList": ["B0F3GWXLTS", "B07PGL2ZSL", "B08N5WRWNW"], "asinListLastSeen": [7662840, 7662710, 7661950] } } } ``` Response shortened for readability; illustrative values. A real storefront `asinList` can contain up to 100,000 ASINs, sorted freshest first; `asinListLastSeen` holds the matching last-seen timestamps in Keepa Time minutes. # Seller Finder Source: https://env.7xmtools.com/api-docs/seller-finder.html Search for Amazon marketplace sellers in the Keepa database that match your specified criteria — by name and business details, rating history, fulfilment activity, storefront size, Buy Box performance or catalogue profile. The request returns seller ID lists. GET / POST · 10 + 1 per 100 seller IDs This request is the seller counterpart of the [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html). It uses the same request grammar — the same paging rules, the same `_gte` / `_lte` range syntax, the same array/exclusion semantics — but it searches the merchant database instead of the product database. - The request returns only seller ID lists, not [seller objects](https://env.7xmtools.com/api-docs/seller-object.html). Use the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request to resolve the returned IDs into seller objects (up to 100 per request). - Each request consumes 10 tokens plus an additional token per 100 seller IDs in the result set. - A query can return up to 10,000 seller IDs using paging, with a minimum page size of 50. If using paging, initial search results are not cached, so the order of results may be inconsistent between individual pages if there is a delay between consecutive page requests. - Filters are joined by an **AND** condition. - For filters allowing multiple entries (all arrays), each specified entry is considered with an **OR** condition, supporting a maximum of 50 entries. - At least one filter must be specified. A query without any filter criteria is rejected, since it would match the entire merchant database. - Seller data constantly changes. Running the same query twice may yield different results, as sellers may be misplaced due to recent changes or updates during the query execution. > **Note:** Unlike the [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html), this request has no `stats` parameter and never returns a [Search Insights Object](https://env.7xmtools.com/api-docs/search-insights-object.html). > **Note:** All API requests execute regardless of your current token balance, as long as it's positive. Requesting large result sets may cause your token balance to go negative. Use with caution! ## Endpoint You can choose between an HTTP GET or POST request. ### GET format ``` GET https://api.keepa.com/sellerquery?key=&domain=&selection= ``` The `` must be **URL-encoded** if the GET format is used. ### POST format ``` POST https://api.keepa.com/sellerquery?domain=&key= ``` The POST payload must contain the ``. ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the [valid domain IDs](https://env.7xmtools.com/api-docs/seller-finder.html#domain-ids) below. Can be overridden per query with the `domainId` filter, which is the only way to search several marketplaces at once. | | `selection` | required | The seller query JSON containing all request parameters (see [below](https://env.7xmtools.com/api-docs/seller-finder.html#the-query-json)). URL-encoded as GET parameter, or sent as the POST body. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost - **Base cost:** 10 tokens per request + 1 token per 100 seller IDs in the result set (rounded up). - A query that matches nothing still costs the 10 base tokens. - A request rejected as a bad request (invalid or missing query JSON, a rejected paging combination, a filter array that is too large, or a query without filter criteria) does not run and consumes no result-based tokens. > **Important:** Requesting large lists may consume more tokens than are available in your bucket, causing your balance to go negative. Use with caution. ## The seller query JSON The `selection` JSON combines paging, sorting and filters. All filters are optional individually, but the query must contain at least one of them. ```json { "page": Integer, "perPage": Integer, "sort": [ [String, String] ], "minMatch": { String: Integer }, "search": String, "activeOnly": Boolean, "domainId": Byte[], "sellerId": String[], "sellerName": String, "businessName": String, "isAmazon": Boolean, "businessType": String[], "representative": String[], "vatID": String[], "tradeNumber": String[], "phoneNumber": String[], "email": String[], "address": String, "addressCountry": String[], "customerServicesAddressCountry": String[], "hasBusinessDetails": Boolean, "currentRating_lte": Integer, "currentRating_gte": Integer, "currentRatingCount_lte": Integer, "currentRatingCount_gte": Integer, "ratingCount30_lte": Integer, "ratingCount30_gte": Integer, "ratingCount90_lte": Integer, "ratingCount90_gte": Integer, "ratingCount365_lte": Integer, "ratingCount365_gte": Integer, "ratingCountLifetime_lte": Integer, "ratingCountLifetime_gte": Integer, "positiveRating30_lte": Integer, "positiveRating30_gte": Integer, "positiveRating90_lte": Integer, "positiveRating90_gte": Integer, "positiveRating365_lte": Integer, "positiveRating365_gte": Integer, "positiveRatingLifetime_lte": Integer, "positiveRatingLifetime_gte": Integer, "neutralRating30_lte": Integer, "neutralRating30_gte": Integer, "neutralRating90_lte": Integer, "neutralRating90_gte": Integer, "neutralRating365_lte": Integer, "neutralRating365_gte": Integer, "neutralRatingLifetime_lte": Integer, "neutralRatingLifetime_gte": Integer, "negativeRating30_lte": Integer, "negativeRating30_gte": Integer, "negativeRating90_lte": Integer, "negativeRating90_gte": Integer, "negativeRating365_lte": Integer, "negativeRating365_gte": Integer, "negativeRatingLifetime_lte": Integer, "negativeRatingLifetime_gte": Integer, "ratingCountDelta30_lte": Integer, "ratingCountDelta30_gte": Integer, "ratingCountDelta90_lte": Integer, "ratingCountDelta90_gte": Integer, "ratingCountDelta365_lte": Integer, "ratingCountDelta365_gte": Integer, "ratingDelta30_lte": Integer, "ratingDelta30_gte": Integer, "ratingDelta90_lte": Integer, "ratingDelta90_gte": Integer, "ratingDelta365_lte": Integer, "ratingDelta365_gte": Integer, "lastRatingUpdate_lte": Integer, "lastRatingUpdate_gte": Integer, "lastFeedbackDate_lte": Integer, "lastFeedbackDate_gte": Integer, "hasFBA": Boolean, "isNotFound": Boolean, "lastSeenOffer_lte": Integer, "lastSeenOffer_gte": Integer, "lastSeenFbaOffer_lte": Integer, "lastSeenFbaOffer_gte": Integer, "totalStorefrontAsins_lte": Integer, "totalStorefrontAsins_gte": Integer, "avgBuyBoxCompetitors_lte": Integer, "avgBuyBoxCompetitors_gte": Integer, "buyBoxNewOwnershipRate_lte": Integer, "buyBoxNewOwnershipRate_gte": Integer, "buyBoxUsedOwnershipRate_lte": Integer, "buyBoxUsedOwnershipRate_gte": Integer, "rootCategories_include": Long[], "rootCategories_exclude": Long[], "primaryRootCategory": Long[], "brands": String[], "primaryBrand": String[], "competitorSellerIds": String[], "topCompetitorSellerId": String[], "primaryRootCategoryProductCount_lte": Integer, "primaryRootCategoryProductCount_gte": Integer, "primaryBrandProductCount_lte": Integer, "primaryBrandProductCount_gte": Integer, "topCompetitorPercent_lte": Integer, "topCompetitorPercent_gte": Integer, "productCountWithAmazonOffer_lte": Integer, "productCountWithAmazonOffer_gte": Integer, "avg30SalesRank_lte": Integer, "avg30SalesRank_gte": Integer, "trackedSince_lte": Integer, "trackedSince_gte": Integer } ``` ### Paging *Paging is optional; by default, up to 50 results are provided.* | Field | Description | | --- | --- | | `page` | Most queries have more than 50 results (the minimum page size). To retrieve additional results, iterate the `page` parameter while keeping all other parameters identical. Start with `page` 0 and stop when the response contains fewer than `perPage` results. Each response also includes the `totalResults` field, indicating the number of matched sellers. When requesting a `page` other than 0, `perPage` × `page` must stay below 10,000. Example: `0` | | `perPage` | Specifies the number of results to retrieve per page. The default is 50 and the minimum is 50; an explicitly supplied `0` is treated as 100. If `page` is **0**, `perPage` can be as large as 10,000. If a `page` other than 0 is requested, the combination of `page` and `perPage` must not exceed 10,000 results; a page whose window would reach past 10,000 is shortened, so ask for the exact page size you want rather than relying on the last page. | ### Sorting *Sorting is optional; by default, results are sorted descending by `currentRatingCount` — the largest sellers first. If the query contains a `search` term, results are sorted by relevance first and by `currentRatingCount` only as a tie-breaker.* `sort` can include up to three sorting criteria. Use a two-dimensional array where each entry is in the format `[fieldName, sortDirection]`: - **fieldName**: any filter field from the lists below. The `fieldName` must not include `_lte` or `_gte`. - **sortDirection**: use `"asc"` for ascending or `"desc"` for descending. Any other value is treated as `"desc"`. - Sellers for which the sort field has no value are always placed last, in both directions. ```json "sort": [ ["currentRatingCount", "desc"] ] ``` > **Note:** An unrecognised sort field does **not** produce an error — the whole `sort` is discarded and the default sort applies instead. The free-text fields `address` and `customerServicesAddress` cannot be sorted on and fall back the same way; `sellerName` and `businessName` can be sorted on and are ordered by their exact (unanalyzed, lowercased) value. ### Filter basics The following fields act as filters. Only sellers that **exactly** match all filters will be returned by the query. All string filters are case insensitive — every term is lowercased before it is matched, and the stored values are lowercase too. Filters ending in `_gte` restrict the output to values "Greater than or equal" to the specified value, while `_lte` means "Less than or equal". Supplying the same value for both bounds of a field turns it into an exact match. String array filters can be used as exclusion filters by prefixing an entry with `-` or `✜`. Excluded and included entries can be mixed within one array. ```json "addressCountry": ["cn", "hk", "-de"] ``` Boolean filters match sellers that carry the flag when set to `true`, and sellers that do *not* carry it when set to `false`. > **Note on missing values:** A seller for which Keepa has no value for a field is not indexed for that field at all, so it never matches a filter on it — not even a wide range. This is deliberate: "no rating yet" and "a rating of 0%" must not answer the same query. #### minMatch — K-of-N matching on array filters Entries within one array filter are normally joined by **OR**: any one of them may match. `minMatch` raises that bar per field, as a map of filter name to the number of entries that must match. Setting it equal to the number of entries turns that filter into an **AND**. ```json "minMatch": { "brands": 2 } ``` Here a seller must carry at least two of the listed `brands`. Values are clamped to the number of entries actually supplied for that filter, and exclusion entries do not count towards it. ### Free-text search `search` takes a single free-text term and matches it against every merchant field a human would type into a lookup box. It is what backs the seller lookup on the Keepa website. A seller is a hit if **any one** of the following matches: | Matched field | How it is matched | | --- | --- | | `sellerName`, `businessName`, `address` | As analyzed text, type-ahead style: every word of the term but the last must match a whole word, and the last word matches as a prefix. All words must match, and all of them must land in the *same* field. The words need not be adjacent or in order. | | `sellerId`, `vatID`, `tradeNumber`, `email`, `representative` | As an exact term — these hold identifiers, and half a VAT ID is not a VAT ID. Partial matches do not work here. | Because all words must land in the same field, a term that mixes a word from the seller name with a word from the business name finds nothing. Typing more narrows the result set rather than widening it. Terms longer than 300 characters are truncated rather than rejected. `search` combines with the other filters by **AND**: `"search"` together with `"hasFBA": true` requires both. ```json { "search": "thrift", "hasFBA": true } ``` ### Restricting to active sellers `activeOnly` (Boolean) restricts the result to merchants that were seen offering something recently. The cutoff is resolved on the server at request time — currently the last **31 days** — so that this filter cannot drift apart from the active-seller counts shown elsewhere, and so a stale client cannot pin an old cutoff. It is equivalent to setting `lastSeenOffer_gte` to that cutoff yourself. Both may be set at the same time; they constrain the same field, so the tighter bound wins. Setting `activeOnly` to `false` has no effect. ### Identity | Filter | Description | | --- | --- | | `domainId` | Byte array. An explicit list of Amazon locales to search. When set, it **overrides** the `domain` request parameter and is the only way to search several marketplaces in one request. The same merchant is a separate seller per locale. Example: `[1, 2, 3]` | | `sellerId` | String array. Seller IDs. Example: `["A2L77EE7U53NWQ"]` | | `sellerName` | Free text over the seller's public display name. Works on a keyword basis: all specified keywords must be contained, in any order. Wrap the value in double quotes for a phrase match. Values longer than 300 characters are truncated. Example: `"warehouse deals"` | | `businessName` | Free text over the legal business name from the seller information block, which is often unrelated to `sellerName`. Same keyword/phrase behaviour as `sellerName`. | | `isAmazon` | Boolean. Whether the seller is the marketplace's own Amazon seller account. Example: `false` | ### Business & legal details These come from the seller information block Amazon publishes on the seller profile page. They are only available for sellers where Keepa was able to parse that block. | Filter | Description | | --- | --- | | `businessType` | String array. The declared legal form of the business. Example: `["privately owned"]` | | `representative` | String array. The named legal representative of the business. | | `vatID` | String array. VAT identification numbers. | | `tradeNumber` | String array. Trade register / company registration numbers. | | `phoneNumber` | String array. Business phone numbers. | | `email` | String array. Business e-mail addresses. | | `address` | Free text over the seller's business address, with all address lines joined into one string. Same keyword/phrase behaviour as `sellerName`. Example: `shenzhen` | | `addressCountry` | String array. Country of the business address as an ISO 3166 alpha-2 code. Example: `["cn", "hk"]` | | `customerServicesAddressCountry` | String array. Country of the separate customer services address, where the seller declares one. Same format as `addressCountry`. | | `hasBusinessDetails` | Boolean. Whether any part of the seller information block could be parsed at all. A cheap way to restrict a query to sellers with legal details on file. | ### Ratings & feedback | Filter | Description | | --- | --- | | `currentRating` `[_lte, _gte]` | The seller's current feedback percentage, 0 to 100. Example: `95` | | `currentRatingCount` `[_lte, _gte]` | The seller's current lifetime feedback count. Example: `1000` | | `ratingCount` `[30, 90, 365, Lifetime]` `[_lte, _gte]` | Number of ratings the seller received in the last 30 / 90 / 365 days, or over their lifetime, as reported by Amazon. Example: `ratingCount90_gte` `50` | | `positiveRating` `[30, 90, 365, Lifetime]` `[_lte, _gte]` | Percentage of positive ratings over the respective window, 0 to 100. | | `neutralRating` `[30, 90, 365, Lifetime]` `[_lte, _gte]` | Percentage of neutral ratings over the respective window, 0 to 100. | | `negativeRating` `[30, 90, 365, Lifetime]` `[_lte, _gte]` | Percentage of negative ratings over the respective window, 0 to 100. | | `ratingCountDelta` `[30, 90, 365]` `[_lte, _gte]` | Growth of the lifetime feedback count over the last 30 / 90 / 365 days, derived from the seller's rating count history. A seller whose history does not reach back over the full window has no value here, so a young seller is never reported as having gained its entire feedback count in the window. Example: `ratingCountDelta30_gte` `100` | | `ratingDelta` `[30, 90, 365]` `[_lte, _gte]` | Change of the current feedback percentage over the last 30 / 90 / 365 days, in percentage points. Negative values are drops. Same "not enough history" rule as `ratingCountDelta`. Example: `ratingDelta90_lte` `-5` | | `lastRatingUpdate` `[_lte, _gte]` | When Keepa last updated this seller's rating data, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-finder.html#keepa-time-minutes). | | `lastFeedbackDate` `[_lte, _gte]` | Date of the newest feedback entry Keepa has recorded for this seller — the last time a buyer actually rated them, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-finder.html#keepa-time-minutes). | ### Fulfilment & offer activity | Filter | Description | | --- | --- | | `hasFBA` | Boolean. Whether the seller was seen using Fulfillment by Amazon. Example: `true` | | `lastSeenOffer` `[_lte, _gte]` | The last time Keepa saw any offer of this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-finder.html#keepa-time-minutes). See also [`activeOnly`](https://env.7xmtools.com/api-docs/seller-finder.html#active-only). | | `lastSeenFbaOffer` `[_lte, _gte]` | The last time Keepa saw an FBA offer of this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-finder.html#keepa-time-minutes). | | `isNotFound` | Boolean. Whether Amazon returns a 404 for the seller's profile page — the seller is tracked but no longer exists. **Such sellers are excluded from every query by default.** Set this filter explicitly (to `true` to search only them, or to `false` to keep the default exclusion in a query that documents it) to take control of that. | ### Storefront scale | Filter | Description | | --- | --- | | `totalStorefrontAsins` `[_lte, _gte]` | The number of verified listings of this seller — the same value the "Verified Listings" column of a seller export reports. Where Keepa has no verified count it falls back to the sum over the seller's tracked root categories, which is bounded by their top 10 categories and therefore understates sellers with a very broad catalogue. Example: `1000` | ### Buy Box performance | Filter | Description | | --- | --- | | `avgBuyBoxCompetitors` `[_lte, _gte]` | The average number of sellers this merchant competes with for the Buy Box across their listings. Example: `3` | | `buyBoxNewOwnershipRate` `[_lte, _gte]` | Percentage of the time the seller holds the New Buy Box across their listings, 0 to 100. Example: `50` | | `buyBoxUsedOwnershipRate` `[_lte, _gte]` | Percentage of the time the seller holds the Used Buy Box across their listings, 0 to 100. | ### Catalogue profile These describe what a seller sells, derived from the products Keepa has seen them offer. Categories and brands are tracked for the seller's top 10 by product count; competitors for the top 10 by listing overlap. | Filter | Description | | --- | --- | | `rootCategories_include` | Only include sellers active in these root categories. Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). Example: `[3167641]` | | `rootCategories_exclude` | Exclude sellers active in these root categories. Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). | | `primaryRootCategory` | Array with up to 50 [category node ids](https://env.7xmtools.com/api-docs/category-object.html). The seller's single largest root category by product count. | | `primaryRootCategoryProductCount` `[_lte, _gte]` | How many products the seller lists in that primary root category. | | `brands` | String array. Brands the seller carries. Example: `["canon"]` | | `primaryBrand` | String array. The seller's single largest brand by product count. | | `primaryBrandProductCount` `[_lte, _gte]` | How many products the seller lists under that primary brand. | | `competitorSellerIds` | String array. Seller IDs that share the most listings with this seller. Use it to find the competitors of a given merchant. Example: `["A2L77EE7U53NWQ"]` | | `topCompetitorSellerId` | String array. The single seller ID with the largest listing overlap. | | `topCompetitorPercent` `[_lte, _gte]` | Share of the seller's listings that the top competitor also offers, 0 to 100. | | `productCountWithAmazonOffer` `[_lte, _gte]` | How many of the seller's tracked products also carry an Amazon offer — how much this seller competes with Amazon directly. | | `avg30SalesRank` `[_lte, _gte]` | The product-count weighted mean 30-day sales rank across the seller's tracked categories. Lower is better selling. Example: `50000` | ### Tracking time | Filter | Description | | --- | --- | | `trackedSince` `[_lte, _gte]` | When Keepa started tracking this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-finder.html#keepa-time-minutes). Example: `3411319` | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Errors A rejected request answers with HTTP **400** and an `error` field. The possible messages are: | Message | Cause | | --- | --- | | `The sellerQueryJSON is missing or invalid.` | No `selection` parameter and no request body, or the payload does not parse as a seller query JSON. | | `combination of perPage and page exeeds limit or is too small` | `perPage` below 50, a negative `page`, or a `perPage`/`page` combination that reaches past 10,000 results. | | `too many sort directions, limit is 3.` | More than three entries in `sort`. | | `too many filters. maximum of 50 entries per filter are supported.` | More than 50 category node ids in `rootCategories_include`, `rootCategories_exclude` or `primaryRootCategory`. | | `too many entries in filter string array, limit is 50 per array.` | More than 50 entries in any string array filter. | | `the query has no filter criteria.` | The query contains no usable filter, or the `domain` parameter is not a valid marketplace and the query carries no `domainId` of its own. An unconstrained query would return the entire merchant database and is rejected rather than executed. | ```json { "timestamp": 1783382461000, "tokensLeft": 248, "refillIn": 31000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 0, "processingTimeInMs": 3, "error": { "type": "invalidParameter", "message": "the query has no filter criteria." } } ``` ## Response ```json { "sellerIdList": String array, "totalResults": Integer } ``` | Field | Description | | --- | --- | | `sellerIdList` | Ordered array with the result seller IDs. Pass them to the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request (up to 100 per call) to retrieve the matching [seller objects](https://env.7xmtools.com/api-docs/seller-object.html). | | `totalResults` | Count of all matched sellers, across all pages. | ## Examples ### Example query Find sellers on amazon.de with a business address in China or Hong Kong, at least 1,000 lifetime ratings, that were seen offering something recently — largest first, 100 results per page: ```json { "addressCountry": ["cn", "hk"], "currentRatingCount_gte": 1000, "activeOnly": true, "sort": [["currentRatingCount", "desc"]], "perPage": 100, "page": 0 } ``` > **Tip:** The returned `sellerIdList` contains IDs only. Feed them to the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request in batches of up to 100 to get the full [seller objects](https://env.7xmtools.com/api-docs/seller-object.html). **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); SellerFinderRequest finder = new SellerFinderRequest(); finder.addressCountry = new String[]{"cn", "hk"}; finder.currentRatingCount_gte = 1000; finder.activeOnly = true; finder.sort = new String[][]{{"currentRatingCount", "desc"}}; finder.perPage = 100; finder.page = 0; api.sendRequest(Request.getSellerFinderRequest(AmazonLocale.DE, finder)) .done(result -> { System.out.println(result.sellerIdList.length + " seller IDs on this page"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php ["cn", "hk"], "currentRatingCount_gte" => 1000, "activeOnly" => true, "sort" => [["currentRatingCount", "desc"]], "perPage" => 100, "page" => 0, ]; $url = "https://api.keepa.com/sellerquery?key=YOUR_API_KEY&domain=3"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($selection)); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = json_decode(curl_exec($ch), true); curl_close($ch); echo $data["totalResults"] . " matches"; print_r($data["sellerIdList"]); ``` **Python** ```python import requests selection = { "addressCountry": ["cn", "hk"], "currentRatingCount_gte": 1000, "activeOnly": True, "sort": [["currentRatingCount", "desc"]], "perPage": 100, "page": 0, } r = requests.post( "https://api.keepa.com/sellerquery", params={"domain": 3, "key": "YOUR_API_KEY"}, json=selection, ) data = r.json() print(data["totalResults"], "matches") print(data["sellerIdList"][:10]) ``` **Node.js** ```javascript const selection = { addressCountry: ["cn", "hk"], currentRatingCount_gte: 1000, activeOnly: true, sort: [["currentRatingCount", "desc"]], perPage: 100, page: 0, }; const res = await fetch("https://api.keepa.com/sellerquery?domain=3&key=YOUR_API_KEY", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(selection), }); const data = await res.json(); console.log(data.totalResults, "matches"); console.log(data.sellerIdList.slice(0, 10)); ``` **cURL (GET)** ```bash # GET: the selection JSON must be URL-encoded (--data-urlencode does this) curl -s -G "https://api.keepa.com/sellerquery" \ --data-urlencode "key=YOUR_API_KEY" \ --data-urlencode "domain=3" \ --data-urlencode 'selection={"addressCountry":["cn","hk"],"currentRatingCount_gte":1000,"activeOnly":true,"perPage":100,"page":0}' ``` **cURL (POST)** ```bash # POST: the selection JSON is the request body curl -s -X POST "https://api.keepa.com/sellerquery?domain=3&key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"addressCountry":["cn","hk"],"currentRatingCount_gte":1000,"activeOnly":true,"perPage":100,"page":0}' ``` ### Example: free-text lookup Look a seller up the way the website's seller search does — one term across name, business name, address and the identifier fields, best match first: ```bash curl -s -X POST "https://api.keepa.com/sellerquery?domain=1&key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"search":"thriftbooks","activeOnly":true,"perPage":50}' ``` ### Example: a seller's competitors Find the merchants whose catalogue overlaps most with a given seller, restricted to those still active: ```bash curl -s -X POST "https://api.keepa.com/sellerquery?domain=1&key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"competitorSellerIds":["A2L77EE7U53NWQ"],"activeOnly":true,"sort":[["totalStorefrontAsins","desc"]],"perPage":50}' ``` ### Example response ```json { "timestamp": 1783382461000, "tokensLeft": 238, "refillIn": 31000, "refillRate": 5, "tokenFlowReduction": 0.0, "tokensConsumed": 11, "processingTimeInMs": 128, "sellerIdList": [ "A2L77EE7U53NWQ", "A3EX3RPFGJNC29", "A1X6FK5RDHNB96", "AN1VRQENFRJN5", "A3DWYIK6Y9EEQB" ], "totalResults": 4821 } ``` *Response shortened for readability; illustrative values.* The response contains no seller objects and no `searchInsights` field — resolve the IDs through the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request. # Most Rated Sellers Source: https://env.7xmtools.com/api-docs/most-rated-sellers.html Retrieve a list of seller IDs for the most rated Amazon marketplace sellers of a locale. Lists are ordered by rating count and updated daily. GET · 50 tokens per request The Most Rated Seller List request retrieves a list of seller IDs for the most rated Amazon marketplace sellers: - **Ordering:** lists are ordered starting with the most rated seller. - **Updates:** lists are updated daily and contain up to **100,000** seller IDs. ## Endpoint ``` GET https://api.keepa.com/topseller?key=&domain= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API access key (``). | | `domain` | required | Integer value for the Amazon locale you want to access (``). See the valid values below. | ### Valid `domain` values | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost Each Most Rated Seller List request has a fixed cost of **50 tokens**. ## Response The response contains an ordered string array field `sellerIdList` containing [seller IDs](https://env.7xmtools.com/api-docs/seller-object.html), starting with the most rated seller. > **Tip:** You can use the [Request Seller Information](https://env.7xmtools.com/api-docs/seller.html) endpoint to look up more information about a seller ID from this list. Response format: ```json { "sellerIdList": [ "A1PA6795UKMFR9", "A1RKKUPIHCS9HS", "A3KYXGYZHZZIOF", "...", "ANOTHER_SELLER_ID" ] } ``` ## Examples ### Example request Retrieve the most rated sellers on Amazon.com (`domain=1`): ```bash https://api.keepa.com/topseller?key=YOUR_API_KEY&domain=1 ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getTopSellerRequest(AmazonLocale.US); api.sendRequest(r) .done(result -> { System.out.println(result.sellerIdList.length + " seller IDs"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getTopSellerRequest(AmazonLocale::US)); if ($response->status == ResponseStatus::OK) { print_r($response->sellerIdList); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1} r = requests.get("https://api.keepa.com/topseller", params=params) data = r.json() seller_ids = data["sellerIdList"] print(f"Received {len(seller_ids)} seller IDs") print("Most rated seller:", seller_ids[0]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/topseller?key=YOUR_API_KEY&domain=1"); const data = await res.json(); const sellerIds = data.sellerIdList; console.log(`Received ${sellerIds.length} seller IDs`); console.log("Most rated seller:", sellerIds[0]); ``` **cURL** ```bash curl -s "https://api.keepa.com/topseller?key=YOUR_API_KEY&domain=1" ``` ### Example response ```json { "timestamp": 1753620120000, "tokensLeft": 250, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 50, "processingTimeInMs": 18, "sellerIdList": [ "A1PA6795UKMFR9", "A1RKKUPIHCS9HS", "A3KYXGYZHZZIOF", "A2L77EE7U53NWQ", "A11IL2PNWYJU7H", "A3P5ROKL5A1OLE", "A1X6FK5RDHNB96" ] } ``` Response shortened for readability; illustrative values. A full response contains up to 100,000 seller IDs, ordered starting with the most rated seller. # Lightning Deals Source: https://env.7xmtools.com/api-docs/lightning-deals.html Access current Amazon Lightning Deals — request a single deal by ASIN or the complete list of lightning deals from the past four days, optionally filtered by deal state. GET · 1 token per ASIN · 500 tokens for the full list This API request provides access to current lightning deals. You can specify an ASIN to inquire about a specific deal (token cost: **1**), or request the complete list for an overview (token cost: **500**). The comprehensive list includes lightning deals from the past **four days**, encompassing both active and expired deals. > **Note:** This request covers lightning deals exclusively, excluding other types of deals. For regular price-drop deals, see the [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) request. ## Endpoint ``` GET https://api.keepa.com/lightningdeal?key=&domain=&asin= ``` ## Parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the table of valid values below. | | `asin` | optional | The ASIN of the lightning deal you want to request (token cost: 1). If not specified, the entire list will be provided (token cost: 500). | | `state` | optional | Limit the returned lightning deals by their state. Possible values: `AVAILABLE`, `WAITLIST`, `SOLDOUT`, `WAITLISTFULL`, `EXPIRED`, `SUPPRESSED`. Example: `&state=AVAILABLE` | ### Valid domain values | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Token Cost | Request | Token Cost | | --- | --- | | Specific lightning deal (with `asin` parameter) | 1 | | Complete list (no `asin` parameter) | 500 (10 when the list holds 10 deals or fewer) | ## Response An array of [lightning deal objects](https://env.7xmtools.com/api-docs/lightning-deal-object.html) in the `lightningDeals` field. ## Examples ### Example request — single deal by ASIN Requests the lightning deal for ASIN `B00M0QVG3W` on Amazon.com (domain `1`). Token cost: 1. **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getLightningDealRequest(AmazonLocale.US, "B00M0QVG3W"); api.sendRequest(r) .done(result -> { for (LightningDeal deal : result.lightningDeals) { System.out.println(deal.dealState + " " + deal.dealPrice); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getLightningDealRequest(AmazonLocale::US, "B00M0QVG3W")); if ($response->status == ResponseStatus::OK) { print_r($response->lightningDeals); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B00M0QVG3W"} r = requests.get("https://api.keepa.com/lightningdeal", params=params) data = r.json() deal = data["lightningDeals"][0] print(deal["title"], deal["dealState"], deal["dealPrice"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/lightningdeal?key=YOUR_API_KEY&domain=1&asin=B00M0QVG3W"); const data = await res.json(); const deal = data.lightningDeals[0]; console.log(deal.title, deal.dealState, deal.dealPrice); ``` **cURL** ```bash curl -s "https://api.keepa.com/lightningdeal?key=YOUR_API_KEY&domain=1&asin=B00M0QVG3W" ``` ### Example response ```json { "timestamp": 1753651380000, "tokensLeft": 4495, "refillIn": 42000, "refillRate": 5, "tokenFlowReduction": 0, "tokensConsumed": 1, "processingTimeInMs": 18, "lightningDeals": [ { "domainId": 1, "lastUpdate": 7663523, "asin": "B00M0QVG3W", "title": "Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)", "sellerId": "A2L77EE7U53NWQ", "sellerName": "Amazon Warehouse Deals", "dealId": "76fbc441", "dealPrice": 6999, "currentPrice": 9999, "image": "51InzcaVqrL.jpg", "isPrimeEligible": true, "isFulfilledByAmazon": true, "rating": 45, "totalReviews": 1834, "dealState": "AVAILABLE", "startTime": 7663200, "endTime": 7663620, "percentClaimed": 37, "percentOff": 30, "variation": [ { "dimension": "Color", "value": "Black" } ] } ] } ``` Response shortened for readability; illustrative values. Prices are integers in the smallest currency unit (here: US cents), timestamps like `lastUpdate`, `startTime` and `endTime` are in Keepa Time minutes. See the [Lightning Deal Object](https://env.7xmtools.com/api-docs/lightning-deal-object.html) for all field semantics. ### Example request — complete list with state filter Requests the complete lightning deal list for Amazon.de (domain `3`), limited to deals that are currently `AVAILABLE`. Token cost: 500. Without the `state` filter, the list covers all lightning deals from the past four days, both active and expired. **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getLightningDealRequest(AmazonLocale.DE, null); // the state filter has no dedicated factory parameter — // set it via the public parameter map: r.parameter.put("state", "AVAILABLE"); api.sendRequest(r) .done(result -> { System.out.println(result.lightningDeals.length + " deals"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php parameter["state"] = "AVAILABLE"; $response = $api->sendRequestWithRetry($r); if ($response->status == ResponseStatus::OK) { echo count($response->lightningDeals) . " deals"; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 3, "state": "AVAILABLE"} r = requests.get("https://api.keepa.com/lightningdeal", params=params) data = r.json() for deal in data["lightningDeals"]: print(deal["asin"], deal["percentOff"], deal["percentClaimed"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/lightningdeal?key=YOUR_API_KEY&domain=3&state=AVAILABLE"); const data = await res.json(); for (const deal of data.lightningDeals) { console.log(deal.asin, deal.percentOff, deal.percentClaimed); } ``` **cURL** ```bash curl -s "https://api.keepa.com/lightningdeal?key=YOUR_API_KEY&domain=3&state=AVAILABLE" ``` # Graph Image API Source: https://env.7xmtools.com/api-docs/graph-image.html Retrieve a price history graph of a product as a ready-to-display PNG image. Choose which data series to draw, set the time range and image size, and customize every chart color. GET · 1 token per image The Graph Image API renders the price history of a product as a static chart image in PNG format. The image is generated server-side from the requested data series, time range, size and colors, so it can be displayed anywhere an image can be shown. The *Response* section below describes what the generated PNG contains. > **Note:** Graph images are cached for **90 minutes** on a per-user basis. Submitting the exact same request within this time frame will not consume any tokens. > **Important:** Make sure you do **not** embed the images directly, as this will make your API key publicly accessible and open to misuse. Always put the Graph Image requests behind a proxy to secure your API key. > **Note:** This API call returns PNG images as a response and does not provide your token status information. Any other API request returns your current token status in its response envelope (see [Response Format](https://env.7xmtools.com/api-docs/request-basics.html#response-format)). ## Endpoint ``` GET https://api.keepa.com/graphimage?key=&domain=&asin= ``` ## Parameters ### Required parameters | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `domain` | required | Integer value for the Amazon locale you want to access. See the valid values below. | | `asin` | required | The ASIN of the product. | Valid values for `domain`: | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ### Selecting series Keepa offers three graph types. Each one has its own axes and value space, so a single image can only ever contain series from **one** of them: | # | Graph | Shows | Selected with | | --- | --- | --- | --- | | 1 | Price history | Price trends and root category Sales Rank. | [`types`](https://env.7xmtools.com/api-docs/graph-image.html#param-types) | | 2 | Category Sales Ranks & Monthly Sales | Sales ranks by category and monthly sales data. | [`subranks`, `monthlysold`](https://env.7xmtools.com/api-docs/graph-image.html#rank-graphs) | | 3 | Offer Counts and Ratings | Number of offers, star rating and rating counts. | [`types`](https://env.7xmtools.com/api-docs/graph-image.html#param-types) | Graphs 1 and 3 are made of [csv types](https://env.7xmtools.com/api-docs/product-object.html#csv-array) and are selected with the `types` parameter. Graph 2 is not built from csv types — it is drawn from the product’s per-category rank histories and monthly sold — so it has its own parameters. > **Important:** `types` and the sales rank parameters are **mutually exclusive**. A request naming both returns the bad-request image. > **Default:** a request that selects no series at all draws the Amazon and New price series of graph 1. That defaulting does not apply once `types` or the sales rank parameters are used — those select the series completely. ### `types` — select by csv type index Comma-separated [csv type indexes](https://env.7xmtools.com/api-docs/product-object.html#csv-array), each optionally followed by `:` and a six-digit hex color. A leading `#` is accepted (URL-encode it as `%23`) but is not required. Omitting the color uses the type’s default. ``` &types=16,17,11 &types=11:8888dd,12:444444,34:ff5722 ``` All requested types must belong to the same graph. Every drawable type, by index: | Graph | csv types | | --- | --- | | 1 — Price history | • `0` AMAZON
• `1` NEW
• `2` USED
• `3` SALES
• `4` LISTPRICE
• `5` COLLECTIBLE
• `6` REFURBISHED
• `7` NEW\_FBM\_SHIPPING
• `8` LIGHTNING\_DEAL
• `9` WAREHOUSE
• `10` NEW\_FBA
• `15` EXTRA\_INFO\_UPDATES
• `18` BUY\_BOX\_SHIPPING
• `19` USED\_NEW\_SHIPPING
• `20` USED\_VERY\_GOOD\_SHIPPING
• `21` USED\_GOOD\_SHIPPING
• `22` USED\_ACCEPTABLE\_SHIPPING
• `23` COLLECTIBLE\_NEW\_SHIPPING
• `24` COLLECTIBLE\_VERY\_GOOD\_SHIPPING
• `25` COLLECTIBLE\_GOOD\_SHIPPING
• `26` COLLECTIBLE\_ACCEPTABLE\_SHIPPING
• `27` REFURBISHED\_SHIPPING
• `28` EBAY\_NEW\_SHIPPING
• `29` EBAY\_USED\_SHIPPING
• `30` TRADE\_IN
• `32` BUY\_BOX\_USED\_SHIPPING
• `33` PRIME\_EXCL | | 3 — Offer Counts and Ratings | • `11` COUNT\_NEW
• `12` COUNT\_USED
• `13` COUNT\_REFURBISHED
• `14` COUNT\_COLLECTIBLE
• `16` RATING
• `17` COUNT\_REVIEWS
• `34` COUNT\_NEW\_FBA
• `35` COUNT\_NEW\_FBM | See the [csv History Array](https://env.7xmtools.com/api-docs/product-object.html#csv-array) for what each type contains. > **Important:** A request naming both graphs — e.g. `&types=16,18` — is rejected. So is a malformed index, an unknown type, or a color that is not six hex digits. These are refused rather than silently dropped, because a dropped series is indistinguishable from missing data. ### Category Sales Ranks & Monthly Sales Drawn from the product’s per-category rank histories and monthly sold — not from csv types, which is why it has its own parameters. ``` &subranks=0&monthlysold=1 &subranks=1&cRanks=8fbc8f&monthlysold=1&cMonthlysold=f6d500 ``` | Parameter | Required | Description | Valid values | Example | | --- | --- | --- | --- | --- | | `subranks` | optional | The **presence** of this parameter requests this graph. `0` draws the reference category only; `1` also draws the product’s other categories. | `0`, `1` | `&subranks=1` | | `cRanks` | optional | Base color for the rank series. Additional categories are drawn in progressively darker shades derived from it, so one color covers however many categories a product has. Category selection is not exposed: which categories a product is ranked in is a property of the product. | hex color, e.g. `8fbc8f` | `&cRanks=8fbc8f` | | `monthlysold` | optional | Draw the monthly sold series, on its own axis. Can be requested with or without ranks. | `1` | `&monthlysold=1` | | `cMonthlysold` | optional | Color of the monthly sold series. | hex color, default `f6d500` | `&cMonthlysold=f6d500` | Each category is scaled on its own axis. A product ranked #400 in a sub-category and #180,000 overall would otherwise draw the sub-rank as a flat line; independent scaling is what makes the shapes comparable. ### Display parameters | Parameter | Required | Description | Valid values | Default | Example | | --- | --- | --- | --- | --- | --- | | `range` | optional | The range of the chart in days. | Suggested values: `1`, `2`, `7`, `31`, `90`, `365` | `90` | `&range=90` | | `yzoom` | optional | Enable Close-up View (y-axis zoom). | `1` (zoom), `0` (no zoom) | `1` | `&yzoom=0` | | `width` | optional | Width of the chart image in pixels. Values below the minimum are raised to it. | `300` to `1800` | `500` | `&width=500` | | `height` | optional | Height of the chart image in pixels. Values below the minimum are raised to it. | `150` to `1800` | `200` | `&height=200` | | `title` | optional | Include the product title. | `1` (show), `0` (hide) | `1` | `&title=0` | | `legend` | optional | Include the chart legend. | `1` (show), `0` (hide) | `1` | `&legend=0` | | `lw` | optional | Width of the drawn series lines. Applied proportionally to each series’ own weight, so their relative thicknesses are preserved. Applies to all three graph types. A value outside the valid range is **rejected**, not clamped. | `0.5` to `3.0` | `1.5` | `&lw=2` | ### Color parameters The following parameters allow you to customize the colors of various chart elements. All color parameters are hexadecimal color codes (e.g., `ff0000`). These parameters are optional. These apply to every request. Per-series colors are set through the parameter that selects the series: `types=:` for graphs 1 and 3, or `cRanks` / `cMonthlysold` for graph 2. | Parameter | Required | Description | Example | | --- | --- | --- | --- | | `cBackground` | optional | Chart background color. | `&cBackground=ffffff` | | `cFont` | optional | Font color. | `&cFont=444444` | ## Token Cost **1 token per image.** Because graph images are cached for 90 minutes on a per-user basis, repeating the exact same request (with identical parameters) within that time frame does not consume any tokens. ## Response The response is a binary **PNG image** (not JSON). It does *not* include token-bucket status fields such as `tokensLeft`; those are returned by any other API request in its [response envelope](https://env.7xmtools.com/api-docs/request-basics.html#response-format). The generated PNG contains a chart for the requested product: - Which series are drawn is controlled by [series selection](https://env.7xmtools.com/api-docs/graph-image.html#series-selection) — `types` for graph 1 (Price history) and graph 3 (Offer Counts and Ratings), or `subranks` / `monthlysold` for graph 2 (Category Sales Ranks & Monthly Sales). A request that selects nothing draws the Amazon and New price series. - The chart covers the time range set via `range` in days (default `90`). - The product title and the legend are included unless disabled with `title=0` and `legend=0`, and the Close-up View y-axis zoom is enabled by default (`yzoom=1`). - Background and font color can be customized via `cBackground` and `cFont`; per-series colors are set through the selecting parameter. - Image dimensions follow `width` (300–1800 px, default 500) and `height` (150–1800 px, default 200), and the series line width follows `lw` (0.5–3.0, default 1.5). ## Try it Build a request from every supported parameter, see the URL update as you go, and render the chart against the live API. Your [stored API key](https://env.7xmtools.com/api-docs/settings.html) is used for the request and is never shown in the URL below. ## Examples ### Basic request Draws the default series (Amazon and New prices) for the last 90 days as a 500×200 px PNG: ```bash https://api.keepa.com/graphimage?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS ``` ### Customized request Selects the Amazon, New, Sales Rank and Buy Box series of graph 1 with `types`, widens the range to one year, enlarges the image, and overrides the Amazon series and background colors: ```bash https://api.keepa.com/graphimage?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&types=0:FFA500,1,3,18&range=365&width=800&height=300&cBackground=ffffff ``` **Java** ```java // The official SDKs have no dedicated /graphimage helper — // request the PNG directly: String url = "https://api.keepa.com/graphimage?key=YOUR_API_KEY" + "&domain=1&asin=B0F3GWXLTS&types=0:FFA500,1,3,18&range=365" + "&width=800&height=300&cBackground=ffffff"; try (InputStream in = new URL(url).openStream()) { Files.copy(in, Paths.get("graph.png"), StandardCopyOption.REPLACE_EXISTING); } ``` **PHP** ```php Keepa price history graph ``` > **Tip:** A minimal proxy only needs to forward the whitelisted graph parameters (e.g. `asin`, `range`) to `api.keepa.com/graphimage`, append your secret `key` server-side, and stream the PNG back. Combined with Keepa's 90-minute per-user cache, repeated views of the same chart cost no additional tokens. # Tracking API Source: https://env.7xmtools.com/api-docs/tracking.html Let Keepa track product changes and notify you — via webhook push or API pull. This page covers all tracking operations: adding, retrieving and removing trackings, named tracking lists, notifications and the webhook setup. GET · varies per tracked product Keepa can track product changes and notify you. Tracking through our API uses a separate list than your Keepa account. You can only view and manage the products you track through API calls. > **Important:** > > - Each tracked product **decreases your token refill rate**. Once your refill rate reaches **0**, you will not be able to track any more products or make any API requests that require tokens. > - If your API access is terminated, your tracking list will be deactivated and removed after **7 days**, unless access is restored. > - If you switch to a lower-tier API plan that doesn't provide enough tokens for your current tracking list, the necessary amount of trackings will be deactivated and slated for removal after 7 days, unless they are reactivated in the interim. > - To manage your tracking expenses separately from other API uses, consider operating two separate Keepa accounts, each with its own API subscription. ## Endpoint All tracking operations use the `/tracking` endpoint. The `type` parameter selects the operation. [Add Tracking](https://env.7xmtools.com/api-docs/tracking.html#add-tracking) additionally supports HTTP POST. ``` GET https://api.keepa.com/tracking?key=&type= ``` To manage your API tracking, use the following commands: | Operation | `type` | Token cost | Purpose | | --- | --- | --- | --- | | [Add Tracking](https://env.7xmtools.com/api-docs/tracking.html#add-tracking) | `add` | 1 per tracking | Add a new tracking to your list. | | [Remove Tracking](https://env.7xmtools.com/api-docs/tracking.html#remove-tracking) | `remove` / `removeAll` | 0 | Remove a tracking from your list or clear your entire list. | | [Get Tracking](https://env.7xmtools.com/api-docs/tracking.html#get-tracking) | `get` / `list` | 0 | Retrieve tracking information for a product on your list or the whole list. | | [Get Notifications](https://env.7xmtools.com/api-docs/tracking.html#get-notifications) | `notification` | 0 | Retrieve recent notifications. | | [Get Named Lists](https://env.7xmtools.com/api-docs/tracking.html#get-named-lists) | `listNames` | 0 | Retrieve a list of all your named tracking lists. | | [Set Webhook](https://env.7xmtools.com/api-docs/tracking.html#set-webhook) | `webhook` | 0 | Update your webhook URL to receive push notifications. | ## Types of Tracking There are two types of tracking: ### 1. Regular Tracking Allows tracking of the following price types: - Amazon - New - Used - List Price - Collectible - Refurbished - Lightning Deal - All offer counts - Sales Rank ### 2. Marketplace Tracking Includes all data covered by Regular Tracking. Additionally tracks: - Warehouse Deals - Buy Box New & Used - New 3rd Party FBA & FBM - Rating - Prime Exclusive - Review Counts - All Used and Collectible conditions with shipping costs The first 20 offers of a product will be used for the tracking. ## Token Cost Each tracked ASIN can have notification rules for multiple Amazon locales and have a different update interval. These factors determine how much your token refill rate is reduced for each tracking: | Tracking type | Refill rate reduction | | --- | --- | | Regular Tracking | **0.9 tokens** per update per locale tracked | | Marketplace Tracking | **9 tokens** per update per locale tracked | Since the token refill rate is an integer, the tracking reduction rate is rounded. Your current reduction rate is part of every API response in the `tokenFlowReduction` field alongside other token stats. > **Note:** Your `tokenFlowReduction` will be updated every 5 minutes — not immediately after adding or removing trackings. ### Token cost examples - **2000 Regular Trackings** on a single locale with an update interval of 1 hour:\ 2000 × 0.9 tokens/hour = 1800 tokens/hour = 30 tokens/minute → **decreased refill rate: 30 tokens** - **700 Marketplace Trackings** on a single locale with an update interval of 12 hours:\ 700 × 9 tokens / 12 hours = 525 tokens/hour = 8.75 tokens/minute → **decreased refill rate: 9 tokens** You can track as many products as your token rate allows. Besides the refill rate reduction, the request itself costs tokens only for [Add Tracking](https://env.7xmtools.com/api-docs/tracking.html#add-tracking) (**1 token per tracking**); all other tracking operations cost **0** tokens. ## Named Tracking Lists It is possible to use named tracking lists, which act as a logical separation of your tracking objects. This enables you to have multiple, different trackings for the same ASIN. By default, all trackings are managed in an unnamed list. - All tracking requests (except [Set Webhook](https://env.7xmtools.com/api-docs/tracking.html#set-webhook)) support the additional parameter `list` to specify the name of the list the request should act on (e.g., `&list=user123`). - A list name can be up to **64** characters long. - You can manage up to **100,000** lists (contact us if you need more). - Lists are created implicitly with the first added tracking and can be deleted by the [Remove All](https://env.7xmtools.com/api-docs/tracking.html#remove-tracking) request. - If a tracking is added to a named list, the [tracking object](https://env.7xmtools.com/api-docs/tracking-object.html) will have the list name set in the `trackingListName` field. The same applies to [notification objects](https://env.7xmtools.com/api-docs/notification-object.html). - You can retrieve a list of all your named lists using the [Get Named Lists](https://env.7xmtools.com/api-docs/tracking.html#get-named-lists) request. ## Operations ### Add Tracking **Token cost:** 1 per tracking Adds a new tracking to your list. If you already have an existing tracking for the ASIN on your list, it will be overridden, and if it was deactivated, it will be reactivated. You can batch up to **3,000** trackings in a single request to significantly speed up the process of adding multiple trackings. You can choose between an HTTP GET or POST request. #### GET format ``` GET https://api.keepa.com/tracking?key=&type=add&tracking= ``` #### POST format ``` POST https://api.keepa.com/tracking?key=&type=add ``` The **POST payload** must contain a single or an array of [tracking creation objects](https://env.7xmtools.com/api-docs/tracking-creation-object.html). You can specify up to **3,000** tracking creation objects in a single request in JSON array notation: `[object, object, ...]`. | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | Must be `add`. | | `tracking` | required (GET format only) | The tracking JSON contains an array of [tracking creation objects](https://env.7xmtools.com/api-docs/tracking-creation-object.html). It must be URL-encoded if the GET format is used. Due to URL length limitations, do not use the GET method for batch requests. | | `list` | optional | Name of the [named tracking list](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists) this request should act on, e.g. `&list=user123`. | **Response:** - A `trackings` array field containing the created or updated [tracking object(s)](https://env.7xmtools.com/api-docs/tracking-object.html). - If an error occurred, the `error` field is set. - If a tracking could not be added in a batch request, the `error` field will include a comma-separated list of all failed ASINs. #### Example Add a price watch for ASIN `B00M0QVG3W` on amazon.de (domain 3), notifying via API when the Amazon price drops to 49.99 € (4999 euro cents) or the product comes back in stock: **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); TrackingRequest tracking = new TrackingRequest("B00M0QVG3W", AmazonLocale.DE, 1); tracking.ttl = 0; // never expires tracking.expireNotify = false; tracking.desiredPricesInMainCurrency = true; // thresholdValues / notifyIf can be set on the tracking object as needed api.sendRequest(Request.getTrackingAddRequest(tracking)) .done(result -> { for (Tracking t : result.trackings) System.out.println(t.asin); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php "B00M0QVG3W", "ttl" => 0, "expireNotify" => false, "desiredPricesInMainCurrency" => true, "mainDomainId" => 3, "updateInterval" => 1, "thresholdValues" => [ ["thresholdValue" => 4999, "domain" => 3, "csvType" => 0, "isDrop" => true] ], "notificationType" => [false, false, false, false, false, true, false] ]; $response = $api->sendRequestWithRetry(Request::getTrackingAddRequest($tracking)); if ($response->status == ResponseStatus::OK) { print_r($response->trackings); } ``` **Python** ```python import requests tracking = { "asin": "B00M0QVG3W", "ttl": 0, "expireNotify": False, "desiredPricesInMainCurrency": True, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "thresholdValues": [ {"thresholdValue": 4999, "domain": 3, "csvType": 0, "isDrop": True} ], "notifyIf": [{"domain": 3, "csvType": 0, "notifyIfType": 1}], "notificationType": [False, False, False, False, False, True, False], "individualNotificationInterval": -1, } r = requests.post( "https://api.keepa.com/tracking", params={"key": "YOUR_API_KEY", "type": "add"}, json=[tracking], ) data = r.json() print(data["trackings"][0]["asin"], data["trackings"][0]["isActive"]) ``` **Node.js** ```javascript const tracking = { asin: "B00M0QVG3W", ttl: 0, expireNotify: false, desiredPricesInMainCurrency: true, mainDomainId: 3, updateInterval: 1, metaData: "customer-42", thresholdValues: [{ thresholdValue: 4999, domain: 3, csvType: 0, isDrop: true }], notifyIf: [{ domain: 3, csvType: 0, notifyIfType: 1 }], notificationType: [false, false, false, false, false, true, false], individualNotificationInterval: -1, }; const res = await fetch("https://api.keepa.com/tracking?key=YOUR_API_KEY&type=add", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify([tracking]), }); const data = await res.json(); console.log(data.trackings[0].asin, data.trackings[0].isActive); ``` **cURL** ```bash curl -s -X POST "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=add" \ -H "Content-Type: application/json" \ -d '[{ "asin": "B00M0QVG3W", "ttl": 0, "expireNotify": false, "desiredPricesInMainCurrency": true, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "thresholdValues": [ { "thresholdValue": 4999, "domain": 3, "csvType": 0, "isDrop": true } ], "notifyIf": [ { "domain": 3, "csvType": 0, "notifyIfType": 1 } ], "notificationType": [false, false, false, false, false, true, false], "individualNotificationInterval": -1 }]' ``` #### Example response ```json { "timestamp": 1753651200000, "tokensLeft": 4994, "refillIn": 43000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 1, "processingTimeInMs": 18, "trackings": [ { "asin": "B00M0QVG3W", "createDate": 7663520, "isActive": true, "ttl": 0, "expireNotify": false, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "trackingListName": null, "thresholdValues": [ { "thresholdValueCSV": [7663520, 4999], "domain": 3, "csvType": 0, "isDrop": true } ], "notifyIf": [ { "domain": 3, "csvType": 0, "notifyIfType": 1 } ], "notificationType": [false, false, false, false, false, true, false], "notificationCSV": null, "individualNotificationInterval": -1 } ] } ``` Response shortened for readability; illustrative values. See the [Tracking Object](https://env.7xmtools.com/api-docs/tracking-object.html) for all field semantics. ### Remove Tracking **Token cost:** 0 Removes a single tracking from your list. ``` GET https://api.keepa.com/tracking?key=&type=remove&asin= ``` To remove all your trackings with a single call: ``` GET https://api.keepa.com/tracking?key=&type=removeAll ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | `remove` to remove a single tracking, or `removeAll` to remove all your trackings with a single call. `removeAll` can also be used to delete a [named list](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists). | | `asin` | required (for `remove`) | The ASIN of the product you want to remove from your tracking list. | | `list` | optional | Name of the [named tracking list](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists) this request should act on, e.g. `&list=user123`. | **Response:** - Only token bucket information. - If you did not have a tracking for the specified ASIN, the `error` field is set. > **Note:** Your `tokenFlowReduction` will not be updated immediately upon removing a tracking. #### Example **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getTrackingRemoveRequest("B00M0QVG3W"); api.sendRequest(r) .done(result -> { System.out.println("tracking removed"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getTrackingRemoveRequest("B00M0QVG3W")); if ($response->status == ResponseStatus::OK) { echo "tracking removed"; } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "type": "remove", "asin": "B00M0QVG3W"} r = requests.get("https://api.keepa.com/tracking", params=params) data = r.json() print(data.get("error"), data["tokensLeft"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/tracking?key=YOUR_API_KEY&type=remove&asin=B00M0QVG3W"); const data = await res.json(); console.log(data.error ?? "removed", data.tokensLeft); ``` **cURL** ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=remove&asin=B00M0QVG3W" ``` #### Example response ```json { "timestamp": 1753651260000, "tokensLeft": 4994, "refillIn": 43000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 4 } ``` Illustrative values. ### Get Tracking **Token cost:** 0 Retrieves a single tracking from your list. ``` GET https://api.keepa.com/tracking?key=&type=get&asin= ``` #### Retrieve your list ``` GET https://api.keepa.com/tracking?key=&type=list[&asins-only=1][&page=&perPage=] ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | `get` to retrieve a single tracking, or `list` to retrieve your whole list. | | `asin` | required (for `get`) | The ASIN of the product you want to retrieve your tracking for. | | `asins-only` | optional (`list` only) | `asins-only=1` returns only the ASINs you track (fast, lightweight). Pagination parameters are **ignored** in this mode because the call always returns the full list. | | `page` | optional (`list` only) | Page of the batch you want (first page = `0`). | | `perPage` | optional (`list` only) | Number of tracking records to return in one batch. If you supply this parameter, the highest accepted value is **100,000** — larger values are capped to it. If you omit it, the whole list is returned in one batch (up to **500,000** records). | | `list` | optional | Name of the [named tracking list](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists) this request should act on, e.g. `&list=user123`. | > **Pagination details:** The default is `page=0` with no page size limit, which returns the whole list in one batch (up to **500,000** records). To page through a larger list, supply `perPage` (maximum **100,000**) and increment `page` until the response array is empty. **Response:** - A `trackings` field containing the [tracking object(s)](https://env.7xmtools.com/api-docs/tracking-object.html) (always an array). - If you did not have a tracking for the specified ASIN, the `error` field is set. - In case of the `list` operation with the `asins-only` parameter, an `asinList` field containing a string array of all tracked ASINs. #### Example **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getTrackingGetRequest("B00M0QVG3W"); api.sendRequest(r) .done(result -> { System.out.println(result.trackings[0].asin); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getTrackingGetRequest("B00M0QVG3W")); if ($response->status == ResponseStatus::OK) { print_r($response->trackings); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "type": "get", "asin": "B00M0QVG3W"} r = requests.get("https://api.keepa.com/tracking", params=params) data = r.json() tracking = data["trackings"][0] print(tracking["asin"], tracking["isActive"], tracking["updateInterval"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/tracking?key=YOUR_API_KEY&type=get&asin=B00M0QVG3W"); const data = await res.json(); const tracking = data.trackings[0]; console.log(tracking.asin, tracking.isActive, tracking.updateInterval); ``` **cURL** ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=get&asin=B00M0QVG3W" ``` #### Example response ```json { "timestamp": 1753651320000, "tokensLeft": 4998, "refillIn": 22000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 6, "trackings": [ { "asin": "B00M0QVG3W", "createDate": 7663520, "isActive": true, "ttl": 0, "expireNotify": false, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "trackingListName": null, "thresholdValues": [ { "thresholdValueCSV": [7663520, 4999], "domain": 3, "csvType": 0, "isDrop": true } ], "notifyIf": [ { "domain": 3, "csvType": 0, "notifyIfType": 1 } ], "notificationType": [false, false, false, false, false, true, false], "notificationCSV": [3, 0, 5, 1, 7663890], "individualNotificationInterval": -1 } ] } ``` Response shortened for readability; illustrative values. Retrieving only the ASINs of your entire list: ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=list&asins-only=1" ``` ```json { "timestamp": 1753651380000, "tokensLeft": 4998, "refillIn": 22000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 3, "asinList": ["B00M0QVG3W", "B0F3GWXLTS", "B07FZ8S74R"] } ``` ### Get Notifications **Token cost:** 0 Retrieves your recent [notification objects](https://env.7xmtools.com/api-docs/notification-object.html). A notification will be marked as read once delivered through this call or pushed to your webhook. Notifications are deleted **24 hours** after creation. Use this request if you do not want to use push notifications via webhook or if your webhook endpoint was offline. ``` GET https://api.keepa.com/tracking?key=&type=notification&since=&revise= ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | Must be `notification`. | | `since` | required | Retrieve all available notifications that occurred since this date, in KeepaTime minutes. | | `revise` | required | Boolean value (`0` = false, `1` = true). Whether or not to request notifications already marked as read. | | `all` | optional | Boolean value (`0` = false, `1` = true). By default a single call returns at most **2,000** notifications, newest first. Set `all=1` to lift that limit and return every notification matching the request.
Example: `&all=1` | | `readOnly` | optional | Boolean value (`0` = false, `1` = true). If set to `1`, the returned notifications are *not* marked as read, so a later call without `revise` still returns them. Use this to inspect notifications without consuming them.
Example: `&readOnly=1` | | `list` | optional | Name of the [named tracking list](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists) this request should act on, e.g. `&list=user123`. | **Response:** - A `notifications` field containing [notification object(s)](https://env.7xmtools.com/api-docs/notification-object.html), sorted by most recent first. Always an array. - At most **2,000** notifications per call unless `all=1` is used. If you receive exactly 2,000, request the remainder with `all=1` or by paging on `since`. #### Example Fetch all unread notifications created since KeepaTime minute 7,662,080: **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getTrackingNotificationRequest(7662080, false); api.sendRequest(r) .done(result -> { for (Notification n : result.notifications) { System.out.println(n.asin + " " + n.trackingNotificationCause); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getTrackingNotificationRequest(7662080, false)); if ($response->status == ResponseStatus::OK) { print_r($response->notifications); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "type": "notification", "since": 7662080, "revise": 0} r = requests.get("https://api.keepa.com/tracking", params=params) data = r.json() for n in data["notifications"]: print(n["asin"], n["csvType"], n["trackingNotificationCause"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/tracking?key=YOUR_API_KEY&type=notification&since=7662080&revise=0"); const data = await res.json(); for (const n of data.notifications) { console.log(n.asin, n.csvType, n.trackingNotificationCause); } ``` **cURL** ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=notification&since=7662080&revise=0" ``` #### Example response ```json { "timestamp": 1753651440000, "tokensLeft": 4998, "refillIn": 12000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 7, "notifications": [ { "asin": "B00M0QVG3W", "title": "Example Product Title", "image": "61vXG3m1KWL.jpg", "ttl": 1440, "createDate": 7663480, "domainId": 3, "notificationDomainId": 3, "csvType": 0, "trackingNotificationCause": 1, "currentPrices": [4899, 4750, 4210, 15230, 6999, -1], "sentNotificationVia": [false, false, false, false, false, true, false], "metaData": "customer-42", "trackingListName": null } ] } ``` Response shortened for readability; illustrative values. See the [Notification Object](https://env.7xmtools.com/api-docs/notification-object.html) for all field semantics. ### Get Named Lists **Token cost:** 0 Retrieves a list of all the names of your [named lists](https://env.7xmtools.com/api-docs/tracking.html#named-tracking-lists). ``` GET https://api.keepa.com/tracking?key=&type=listNames ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | Must be `listNames`. | **Response:** - A `trackingListNames` field containing the names of all your named lists. Always an array. #### Example **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); // type=listNames has no dedicated factory method — build it directly. // (Request.getTrackingListRequest(false) covers type=list.) Request r = new Request(); r.path = "tracking"; r.parameter.put("type", "listNames"); api.sendRequest(r) .done(result -> System.out.println(result)) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php path = "tracking"; $r->parameter["type"] = "listNames"; $response = $api->sendRequestWithRetry($r); if ($response->status == ResponseStatus::OK) { print_r($response); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "type": "listNames"} r = requests.get("https://api.keepa.com/tracking", params=params) data = r.json() print(data["trackingListNames"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/tracking?key=YOUR_API_KEY&type=listNames"); const data = await res.json(); console.log(data.trackingListNames); ``` **cURL** ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=listNames" ``` #### Example response ```json { "timestamp": 1753651500000, "tokensLeft": 4998, "refillIn": 2000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 3, "trackingListNames": ["user123", "user456", "watchlist-electronics"] } ``` Illustrative values. ### Set Webhook **Token cost:** 0 Updates the webhook URL our service will call whenever a notification is triggered. The URL can also be updated and tested via the [website](https://env.7xmtools.com/api). ``` GET https://api.keepa.com/tracking?key=&type=webhook&url= ``` | Parameter | Required | Description | | --- | --- | --- | | `key` | required | Your private API key. | | `type` | required | Must be `webhook`. | | `url` | required | The new webhook URL. | > **Note:** Set Webhook is the only tracking request that does *not* support the `list` parameter. #### Push notification details - A push notification will be an HTTP POST call with a single [notification object](https://env.7xmtools.com/api-docs/notification-object.html) as its content. - Your server must respond with a status code of **200** to confirm successful retrieval. - If delivery fails, a second attempt will be made with a **15-second** delay. > **Important:** The content type of the POST is `application/json` and **not** `application/x-www-form-urlencoded`. If you use PHP, you have to use `file_get_contents('php://input')` or `$HTTP_RAW_POST_DATA` to access the content. **Response:** - Only token bucket information if the update was successful. - If the specified URL is of invalid format, the `error` field is set. #### Example **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getTrackingWebhookRequest("https://example.com/keepa/notify"); api.sendRequest(r) .done(result -> { System.out.println("webhook set"); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getTrackingWebhookRequest("https://example.com/keepa/notify")); if ($response->status == ResponseStatus::OK) { echo "webhook set"; } ``` **Python** ```python import requests params = { "key": "YOUR_API_KEY", "type": "webhook", "url": "https://example.com/keepa/notify", } r = requests.get("https://api.keepa.com/tracking", params=params) data = r.json() print(data.get("error") or "webhook updated") ``` **Node.js** ```javascript const webhookUrl = encodeURIComponent("https://example.com/keepa/notify"); const res = await fetch(`https://api.keepa.com/tracking?key=YOUR_API_KEY&type=webhook&url=${webhookUrl}`); const data = await res.json(); console.log(data.error ?? "webhook updated"); ``` **cURL** ```bash curl -s "https://api.keepa.com/tracking?key=YOUR_API_KEY&type=webhook&url=https%3A%2F%2Fexample.com%2Fkeepa%2Fnotify" ``` #### Example response ```json { "timestamp": 1753651560000, "tokensLeft": 4998, "refillIn": 55000, "refillRate": 300, "tokenFlowReduction": 30.6, "tokensConsumed": 0, "processingTimeInMs": 2 } ``` Illustrative values. # Product Object Source: https://env.7xmtools.com/api-docs/product-object.html The product object contains all of Keepa’s price history data and basic product information. This page documents every field, the `csv` history array with all history types, how to decode the price history and how to convert Keepa Time timestamps. JSON Object · Returned by: Product Request & Product Searches The product object contains all of our price history data and basic product information. **Returned by:** the product object is returned by the following requests: [Product Searches](https://env.7xmtools.com/api-docs/product-search.html) and [Product Request](https://env.7xmtools.com/api-docs/product.html). > **Important:** Always evaluate the `productType` field first. This field determines what data for the product is available. ## Format ```json { "productType": Integer, "asin": String, "domainId": Integer, "title": String, "itemHighlights": String, "trackingSince": Integer, "listedSince": Integer, "lastUpdate": Integer, "lastRatingUpdate": Integer, "lastPriceChange": Integer, "lastEbayUpdate": Integer, "lastStockUpdate": Integer, "images": Image array, "rootCategory": Integer, "categories": Long array, "categoryTree": Object array, "parentAsin": String, "parentAsinHistory": String array, "parentTitle": String, "parentHighlights": String, "frequentlyBoughtTogether": String array, "bundleItems": String array, "eanList": String array, "upcList": String array, "gtinList": String array, "manufacturer": String, "brand": String, "brandStoreName": String, "brandStoreUrl": String, "brandStoreUrlName": String, "websiteDisplayGroup": String, "websiteDisplayGroupName": String, "salesRankDisplayGroup": String, "type": String, "partNumber": String, "binding": String, "scent": String, "shortDescription": String, "activeIngredients": String, "specialIngredients": String, "itemForm": String, "itemTypeKeyword": String, "recommendedUsesForProduct": String, "pattern": String, "specificUsesForProduct": String array, "businessDiscount": Integer, "lastBusinessDiscountUpdate": Integer, "safetyWarning": String, "productBenefit": String, "batteriesRequired": Boolean, "batteriesIncluded": Boolean, "targetAudienceKeyword": String, "style": String, "includedComponents": String, "material": String, "materials": String array, "specialFeatures": String array, "numberOfItems": Integer, "numberOfPages": Integer, "publicationDate": Integer, "releaseDate": Integer, "contributors": two dimensional String array, "languages": two dimensional String array, "model": String, "color": String, "size": String, "edition": String, "format": String, "features": String array, "description": String, "hazardousMaterials": Object array, "videos": Object array, "aPlus": Object array, "deals": Deal Details Object array, "packageHeight": Integer, "packageLength": Integer, "packageWidth": Integer, "packageWeight": Integer, "packageQuantity": Integer, "itemHeight": Integer, "itemLength": Integer, "itemWidth": Integer, "itemWeight": Integer, "availabilityAmazon": Integer, "availabilityAmazonDelay": Integer array, "buyBoxEligibleOfferCounts": Integer array, "competitivePriceThreshold": Integer, "suggestedLowerPrice": Integer, "ebayListingIds": Long array, "isAdultProduct": Boolean, "isHeatSensitive": Boolean, "isMerchOnDemand": Boolean, "isHaul": Boolean, "launchpad": Boolean, "audienceRating": String, "ingredients": String, "urlSlug": String, "returnRate": Integer, "isEligibleForSuperSaverShipping": Boolean, "fbaFees": Object, "variableClosingFee": Integer, "referralFeePercentage": Double, "variations": Object array, "historicalVariations": String array, "coupon": Integer array, "couponHistory": Integer array, "promotions": Promotion Object array, "unitCount": Object, "stats": Statistics Object, "salesRankReference": Long, "salesRankReferenceHistory": Long array, "salesRanks": Object, "lastSoldUpdate": Integer, "monthlySold": Integer, "monthlySoldHistory": Integer array, "reviews": Review Object, "offers": Marketplace Offer Object array, "liveOffersOrder": Integer array, "buyBoxSellerIdHistory": String array, "buyBoxUsedHistory": String array, "isRedirectASIN": Boolean, "isSNS": Boolean, "offersSuccessful": Boolean, "csv": two dimensional Integer array } ``` ## Fields All timestamps are given in **Keepa Time minutes** (see [Keepa Time Minutes](https://env.7xmtools.com/api-docs/product-object.html#keepa-time) below). All price and fee values are integers in the respective Amazon locale’s smallest currency unit (e.g. euro cents or yen). The fields are grouped below for readability; the group order follows the API response. ### Identification & product type | Field | Type | Description | | --- | --- | --- | | `productType` | Integer | Must always be evaluated first. Determines what data for the product is available. Possible values:
• **0** – STANDARD: Everything accessible.
• **1** – DOWNLOADABLE: No price, rating and offers data accessible. Data is updated less frequently.
• **2** – EBOOK: No price, rating and offers data accessible. Data is updated less frequently.
• **3** – INACCESSIBLE: No price, rating and offers data accessible. Sales rank and offer count data is updated less frequently. Some fields may be missing.
• **4** – INVALID: No current data available due to invalid or deprecated ASIN, or other issues. Might be temporary.
• **5** – VARIATION\_PARENT: Product is a parent ASIN. `variations` is set. | | `asin` | String | The ASIN of the product.
Example: *B00M0QVG3W* | | `domainId` | Integer | The domainId of the product’s Amazon locale. Possible values: \[ **1**: com \| **2**: co.uk \| **3**: de \| **4**: fr \| **5**: co.jp \| **6**: ca \| **8**: it \| **9**: es \| **10**: in \| **11**: com.mx \| **12**: com.br \] | | `title` | String | Title of the product. Amazon limits titles to **75 characters**, including spaces, in all categories except media. Descriptive content that does not fit into the title is published separately in `itemHighlights`, so read both fields if you need the full descriptive text. Caution: may contain unescaped HTML markup in rare cases.
Example: *Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)* | | `itemHighlights` | String | Amazon’s *Item Highlights*: up to **125 characters** of descriptive content in addition to the `title` – typically materials or recommended use cases that help customers compare options. Amazon treats this content as searchable and displays it together with the title in search results and on the product detail page. **undefined** if not available.
Example: *Machine washable cotton blend, for indoor and outdoor use* | ### Tracking & update timestamps | Field | Type | Description | | --- | --- | --- | | `trackingSince` | Integer | States the time we have started tracking this product, in **Keepa Time minutes**.
Example: *2711319* | | `listedSince` | Integer | States the time the item was first listed on Amazon, in **Keepa Time minutes**. This timestamp is only available for some products. If not available, the field has the value **0** or **-1**.
Example: *2711319* | | `lastUpdate` | Integer | States the last time we have updated the information for this product, in **Keepa Time minutes**.
Example: *2711319* | | `lastRatingUpdate` | Integer | States the last time we have updated the product rating and review count, in **Keepa Time minutes**.
Example: *2711319* | | `lastPriceChange` | Integer | States the last time we have registered a price change (any price type), in **Keepa Time minutes**.
Example: *2711319* | | `lastEbayUpdate` | Integer | States the last time we have updated the eBay prices for this product, in **Keepa Time minutes**. If no matching products were found, the integer is negative.
Example: *2711319* | | `lastStockUpdate` | Integer | The most recent update of the stock data for this product’s offers, in **Keepa Time minutes**. This field is **undefined** unless the *stock* parameter was used and stock data was collected at least once. Not all offers are necessarily updated. Refer to the *lastStockUpdate* field of the individual offers.
Example: *2711319* | ### Images & categories | Field | Type | Description | | --- | --- | --- | | `images` | Object array | Provides metadata for images associated with the product. The `images` field is an array of image objects, each containing up to two resolutions for the same image (if available). These are used in the product image carousel on Amazon. **undefined** if unavailable. Each object in the array represents the metadata for a single image in various sizes (large and medium):
• `l` (String): Large image filename.
• `lH` (Integer): Height of the large image, in pixels.
• `lW` (Integer): Width of the large image, in pixels.
• `m` (String): Medium image filename.
• `mH` (Integer): Height of the medium image, in pixels.
• `mW` (Integer): Width of the medium image, in pixels.
• `variant` (String): Amazon’s image variant code, identifying the role of this image within the listing (for example *MAIN* or *PT01*).
Full Amazon image path: `https://m.media-amazon.com/images/I/` | | `rootCategory` | Integer | Category node ID of the product’s root category. **0** if no root category known. The ID 9223372036854775807 (max signed long value) denotes a blank category with the name “?”. We use this in cases where a product is listed in no or non-existent categories.
Example: *562066* | | `categories` | Long array | Array of Amazon category node IDs this product is listed in. Can be empty.
Example: *\[569604\]* | | `categoryTree` | Object array | Represents the category tree as an ordered array of objects, each consisting of two fields:
• `catId` – *Long* – the category ID
• `name` – *String* – the name of the category | Example `images` entry: ```json "images": [{ "l": "81bRlmLRyPL.jpg", "lH": 1500, "lW": 1500, "m": "g1dlEmb2mq3.jpg", "mH": 500, "mW": 500, "variant": "MAIN" }] ``` ### Parent ASIN & variations | Field | Type | Description | | --- | --- | --- | | `parentAsin` | String | The ASIN of the parent product (if the product has variations, otherwise **null**).
Example: *B00M0QVG3W* | | `parentAsinHistory` | String array | The history of the *parentAsin* field. This array has the format: \[keepaTime, previous parent ASIN, …\]. The timestamp indicates when the previously associated *parentAsin* ceased to be valid. For the current parent ASIN, use the `parentAsin` field. **undefined** if the *parentAsin* field never changed. We started tracking parentAsin changes on March 18th 2024.
Example: *\[2711319, B00M0QVG3W\]* | | `parentTitle` | String | The `title` of the parent product, resolved from the ASIN in `parentAsin` so a variation can be labelled with its parent’s wording without requesting the parent separately. It is a snapshot of the parent’s current title, taken while answering the request – there is no history for this field. Provided for variations only: a parent product references itself in `parentAsin` and therefore has no *parentTitle*. **undefined** if the product has no parent or the parent could not be resolved.
Example: *Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)* | | `parentHighlights` | String | The `itemHighlights` of the parent product, resolved in the same way and under the same conditions as `parentTitle`. **undefined** if the product has no parent, the parent could not be resolved, or the parent itself has no item highlights.
Example: *Machine washable cotton blend, for indoor and outdoor use* | | `variations` | Object array | Contains up to 4000 variations of this product. Each object in the array represents a single variation. A variation object consists of the variation ASIN, a swatch image, and an attributes array, where each entry represents one variation theme, including a dimension and its corresponding value. To request live data for this field, the *offers* parameter must be used. Not all variations have a swatch image. **Only available variations are provided.** | | `historicalVariations` | String array | Provides unlisted (historical and out of stock) variation ASINs of this product. **undefined** if no data is available or the `historical-variations` parameter was not specified. | Example `variations` entry: ```json "variations": [{ "asin": "B07GFPNJL9", "image": "55DVdLc1oBC.jpg", "attributes": [{ "dimension": "Size", "value": "7.24 LB" }, { "dimension": "FlavorName", "value": "Cheddar" }] }] ``` ### Videos & A+ content | Field | Type | Description | | --- | --- | --- | | `videos` | Object array | Provides metadata for videos associated with the product. The *videos* parameter is mandatory for access. Each object in the array represents the metadata for a single video. Metadata can be retrieved for all image carousel videos and up to 10 (community) videos from the product listing’s *Videos* section. To request live data for this field, the *offers* parameter must also be included. **undefined** if unavailable. | | `aPlus` | Object array | Provides enhanced A+ content from Amazon product listings. The *aplus* parameter is mandatory for access. Each A+ content object consists of one or more modules containing descriptive text, images, and videos to further illustrate product features. **undefined** if unavailable. | Example `videos` entry: ```javascript "videos": [{ "title": "Compressed Air Duster", // string "image": "31XBcVI7oTL.jpg", // string "duration": 36, // short, in seconds "creator": "Seller", // string "name": "Innovation", // string, public name of the creator "url": "https://m.media-amazon.com/images/S/vse-vms-transcoding-artifact-us-east-1-prd/d8d8f97e-aa42-42d2-aa4c-6ab1b006edb5/default.jobtemplate.hls.m3u8" // string }] ``` > **Note:** The `creator` field represents the creator type and can have the following values: *Main, Customer, Seller, Influencer, Vendor, ThirdParty, Amazon, Merchant* and *Brand*. *Main* is used for all product image carousel videos for which no duration, title and name are available. Example `aPlus` entry: ```javascript "aPlus": [{ "module": [{ "text": [ "Experience premium quality and design.", "Engineered for performance and style." ], // array of strings, each representing a block of descriptive text "image": [ "https://m.media-amazon.com/images/S/aplus-media-library-service-media/47ac6642-83d5-4ebf-867b-ae890ef135d4.png" ], // array of strings, each representing a full image URL "imageAltText": [ "Healthy delicious recipes" ], // array of strings, each the alt text of the image "video": [ "https://m.media-amazon.com/images/S/aplus-media/vc/e07d60fa-d3dd-49fa-90d0-b07e05a3f783.mp4" ], // array of strings, each representing a full video URL "asin": [ "B000K11CAA" ] // array of strings, each representing a comparison table module's product ASIN }], "fromManufacturer": true // boolean; indicates whether the A+ content is provided by the manufacturer/vendor }] ``` > **Note:** The *module* array contains one or more A+ content modules. Each module object includes: **text** – an array of strings with descriptive text blocks; **image** – an array of strings, each a full URL to an image; **imageAltText** – an array of strings, each the alt text of the corresponding image (same index as *image*); **video** – an array of strings, each a full URL to a video. The *fromManufacturer* field is a boolean that indicates if the A+ content originates from the manufacturer or vendor (`true`) or from another source (`false`). ### Deal badges (`deals`) The `deals` field provides metadata for active deals associated with the product’s buy box. **undefined** if unavailable. Only updated when the *offers* parameter is used. Each entry is a Deal Details Object with the following fields: | Field | Type | Description | | --- | --- | --- | | `accessType` | String | Who can access the deal. New access types can be added at any time. Currently one of:
• ALL
• PRIME\_EARLY\_ACCESS
• PRIME\_EXCLUSIVE | | `dealType` | String | The type of the deal badge. New deal types can be added at any time. Currently one of:
• PRIME\_DAY
• PRIME\_DAY\_EARLY
• EARLY\_ACCESS\_WITH\_PRIME
• PRIME\_EXCLUSIVE
• SELLING\_FAST
• PRIME\_SELLING\_FAST
• LIMITED\_TIME\_DEAL
• COUNTDOWN\_ENDS\_IN
• APP\_ONLY
• CLEARANCE\_NO\_RETURNS
• SPECIAL\_EVENT\_SALE
• GENERIC\_OFFER\_PROMO
• UNKNOWN | | `badge` | String | The badge string as shown on the product page.
Example: *“Early Prime Deal”* | Example: ```json "deals": [ { "accessType": "PRIME_EXCLUSIVE", "badge": "Early Prime Deal", "dealType": "EARLY_ACCESS_WITH_PRIME" } ] ``` ### Related products & identifiers | Field | Type | Description | | --- | --- | --- | | `frequentlyBoughtTogether` | String array | One or two “Frequently Bought Together” ASINs. **null** if not available. Field is updated when the *offers* parameter was used.
Example: *\[ "B00M0QVG3W", "B00T85PMWY" \]* | | `bundleItems` | String array | A list of ASINs this product bundle consists of. Only available for virtual product bundles. **null** if not available.
Example: *\[ "B00M0QVG3W", "B00T85PMWY" \]* | | `eanList` | String array | A list of EANs assigned to this product. The first index is the primary EAN. **null** if not available.
Example: *\[ "8806088624952" \]* | | `upcList` | String array | A list of UPCs assigned to this product. The first index is the primary UPC. **null** if not available.
Example: *\[ "045496590086" \]* | | `gtinList` | String array | A list of GTINs assigned to this product. The first index is the primary GTIN. **null** if not available.
Example: *\[ "00614141000012" \]* | ### Brand & manufacturer | Field | Type | Description | | --- | --- | --- | | `manufacturer` | String | Name of the manufacturer. **null** if not available.
Example: *Canon* | | `brand` | String | An item’s brand. **null** if not available.
Example: *Sony* | | `brandStoreName` | String | The store name of the item’s brand. Never available for digital products, movie rentals, product bundles, Amazon Fresh, and Amazon Pantry. **undefined** if not available.
Example: *Hot Wheels* | | `brandStoreUrl` | String | The brand store URL path. To get the full URL, prepend the Amazon domain of the respective locale (e.g. https://www.amazon.com). Never available for digital products, movie rentals, product bundles, Amazon Fresh, and Amazon Pantry. **undefined** if not available.
Example: */stores/LEGO/page/017EF856-965D-4B56-A171-EA61CAFF45DD* | | `brandStoreUrlName` | String | The brand store name from the URL path. Never available for digital products, movie rentals, product bundles, Amazon Fresh, and Amazon Pantry. **undefined** if not available.
Example: *LEGO* (from the URL: /stores/LEGO/page/…) | ### Classification & display groups | Field | Type | Description | | --- | --- | --- | | `websiteDisplayGroup` | String | A categorization of products that behave similarly, influencing how sales rank is calculated and displayed, especially for product variations.
Example: *apparel\_display\_on\_website* | | `websiteDisplayGroupName` | String | A categorization name of products that behave similarly, influencing how sales rank is calculated and displayed, especially for product variations.
Example: *apparel* | | `salesRankDisplayGroup` | String | The categorization of products for which the primary sales rank is based on.
Example: *apparel\_display\_on\_website* | | `type` | String | The item’s productType. **null** if not available.
Example: *VIDEO\_GAME\_CONTROLLER* | | `partNumber` | String | The item’s partNumber. **null** if not available.
Example: *DSC-H300/BM-RB* | | `binding` | String | The item’s binding. **null** if not available. If the item is not a book, it is usually the product category instead.
Example: *Hardcover* | ### Product attributes | Field | Type | Description | | --- | --- | --- | | `scent` | String | The scent of the product. Describes the fragrance associated with the product.
Example: *"Lavender"* | | `shortDescription` | String | A brief description of the product.
Example: *"A soothing lavender-scented candle."* | | `activeIngredients` | String | Active ingredients present in the product.
Example: *"Lavender essential oil, Soy wax"* | | `specialIngredients` | String | Special ingredients used in the product that may have unique properties.
Example: *"Beeswax blend, Natural dyes"* | | `itemForm` | String | The form or physical state of the item.
Example: *"Liquid"* | | `itemTypeKeyword` | String | Keywords describing the type or category of the item.
Example: *"body-lotions"* | | `recommendedUsesForProduct` | String | Recommended uses for the product to guide customers.
Example: *"Aromatherapy, Home Decoration"* | | `pattern` | String | The pattern or design featured on the product. **undefined** if not available.
Example: *"Striped", "Floral"* | | `materials` | String array | The materials of the product. **undefined** if not available.
Example: *\[ "Steel", "Wood" \]* | | `specialFeatures` | String array | The special features of the product. **undefined** if not available.
Example: *\[ "Fast Charging", "Lightweight" \]* | | `specificUsesForProduct` | String array | Specific uses for the product, providing detailed applications.
Example: *\[ "Relaxation", "Decoration" \]* | | `businessDiscount` | Integer | The highest business discount percentage. **undefined** if no business discount data is available.
*Note:* The business discount data is often outdated and may not reflect current offers.
Example: *14* | | `lastBusinessDiscountUpdate` | Integer | States the last time we have updated the `businessDiscount` field, in **Keepa Time minutes**. **undefined** if the businessDiscount has no value.
Example: *2711319* | | `safetyWarning` | String | Safety warnings associated with the product to inform users of potential hazards.
Example: *"Keep away from open flames."* | | `productBenefit` | String | Benefits of using the product, highlighting its advantages.
Example: *"Promotes relaxation and stress relief."* | | `batteriesRequired` | Boolean | Indicates whether batteries are required for the product to function.
Example: *true* | | `batteriesIncluded` | Boolean | Indicates whether batteries are included with the product upon purchase.
Example: *false* | | `targetAudienceKeyword` | String | Keywords describing the target audience for the product.
Example: *"Adults, Gift for Her"* | | `style` | String | The style of the product, which may influence its aesthetic appeal.
Example: *"Modern", "Vintage"* | | `includedComponents` | String | Components included with the product, detailing what is provided upon purchase.
Example: *"Candle, Wick, Box"* | | `material` | String | Material of the product, specifying the primary substances used in its construction.
Example: *"Soy Wax, Cotton"* | ### Editions, formats & content details | Field | Type | Description | | --- | --- | --- | | `numberOfItems` | Integer | The number of items of this product. **-1** if not available.
Example: *1* | | `numberOfPages` | Integer | The number of pages of this product. **-1** if not available.
Example: *514* | | `publicationDate` | Integer | The item’s publication date in one of the following three formats: YYYY or YYYYMM or YYYYMMDD (Y = year, M = month, D = day). **-1** if not available.
Examples: *1978* = the year 1978; *200301* = January 2003; *20150409* = April 9th, 2015 | | `releaseDate` | Integer | The item’s release date. Same format as `publicationDate`. **-1** if not available. | | `contributors` | Two-dimensional String array | The contributors of the item. A contributor can be an author, actor, director, etc. Each contributor entry has a name and a role type.
Example: *\[ \[ "Vin Diesel", "actor" \] \]* | | `languages` | Two-dimensional String array | An item can have one or more languages. Each language entry has a name and most also have a type. **null** if not available.
Examples: *\[ \[ "English" \], \[ "English", "Original Language" \] \]* | | `model` | String | The item’s model. **null** if not available.
Example: *DSC-H300/BM* | | `color` | String | The item’s color. **null** if not available.
Example: *Black* | | `size` | String | The item’s size. **null** if not available.
Example: *S* | | `edition` | String | The item’s edition. **null** if not available.
Example: *Standard Edition* | | `format` | String | The item’s format. **null** if not available.
Example: *AC-3* | | `features` | String array | A list of up to 5 product features / bullet points. **null** if not available. An entry can contain HTML markup in rare cases. We currently limit each entry to a maximum of 1000 characters (if the feature is longer it will be cut off). This limitation may change in the future without prior notice.
Example: *\[ "6 Universal outlets, 6 ft in Length", "Will accept most of the plug types from around the world!", … \]* | | `description` | String | A description of the product. **null** if not available. May contain HTML markup and `\n` newlines. We limit the product description to a maximum of 4000 characters (if the description is longer it will be cut off). This limitation may change in the future without prior notice. To request live data for this field the *offers* parameter must be used.
Example (excerpt): `

Why should you buy our Universal Surge Protector?

• Professional series Universal Surge Protector will accept most of the plug types from around the world, including: UK, US, all of Europe, China, Australian and more!
• The AC surge suppression for full protection of 220-250V workstations`… | | `hazardousMaterials` | Object array | The hazardous material types of the product. **undefined** if not available. Each entry consists of two fields:
• `aspect` – *String*
• `value` – *String* | Example `hazardousMaterials` entries: ```json { "value": "AEROSOLS", "aspect": "proper_shipping_name" }, { "value": "UN1950", "aspect": "united_nations_regulatory_id" } ``` ### Package & item dimensions | Field | Type | Description | | --- | --- | --- | | `packageHeight` | Integer | The package’s height in millimeters. **0 or -1** if not available.
Example: *144* | | `packageLength` | Integer | The package’s length in millimeters. **0 or -1** if not available.
Example: *144* | | `packageWidth` | Integer | The package’s width in millimeters. **0 or -1** if not available.
Example: *144* | | `packageWeight` | Integer | The package’s weight in grams. **0 or -1** if not available.
Example: *1500 (= 1.5 kg)* | | `packageQuantity` | Integer | Quantity of items in the package. **0 or -1** if not available.
Example: *4* | | `itemHeight` | Integer | The item’s height in millimeters. **0 or -1** if not available.
Example: *144* | | `itemLength` | Integer | The item’s length in millimeters. **0 or -1** if not available.
Example: *144* | | `itemWidth` | Integer | The item’s width in millimeters. **0 or -1** if not available.
Example: *144* | | `itemWeight` | Integer | The item’s weight in grams. **0 or -1** if not available.
Example: *1500 (= 1.5 kg)* | ### Availability & buy box eligibility | Field | Type | Description | | --- | --- | --- | | `availabilityAmazon` | Integer | Availability of the sold by Amazon offer. Possible values:
• **-1**: no Amazon offer exists
• **0**: Amazon offer is in stock and shippable
• **1**: Amazon offer is currently not in stock, but will be in the future (pre-order)
• **2**: Amazon offer availability is “unknown”
• **3**: Amazon offer is currently not in stock, but will be in the future (back-order)
• **4**: Amazon offer shipping is delayed – see `availabilityAmazonDelay` for more details | | `availabilityAmazonDelay` | Integer array | If `availabilityAmazon` has the value *4*, this field will provide the delay interval in hours. **null** if no data is available.
Examples: *\[ 24, 48 \]* (= Available to ship in 1-2 days.), *\[ 0, 288 \]* (= Usually dispatched within 12 days.), *\[ 732, 1464 \]* (= In stock. Usually ships within 1 to 2 months.) | | `buyBoxEligibleOfferCounts` | Integer array | If available, an array of integers, each entry indicating the total number of offers eligible for the Buy Box across specified offer conditions and fulfillment channels. This array contains eight elements, indexed as follows:
• **0**: New FBA
• **1**: New FBM
• **2**: Used FBA
• **3**: Used FBM
• **4**: Collectible FBA
• **5**: Collectible FBM
• **6**: Refurbished FBA
• **7**: Refurbished FBM | | `competitivePriceThreshold` | Integer | A price based on competitive prices from other retailers (excluding other Amazon sellers). The offer may be ineligible for the Buy Box if the seller’s price + shipping is greater than this competitive price. **undefined** if it has no value. | | `suggestedLowerPrice` | Integer | The suggested lower price of the item, including shipping. The suggested lower price is based on a range of factors, including historical selling prices, recent Buy Box-eligible prices, and input from customers. **undefined** if it has no value. | | `ebayListingIds` | Long array | Contains the lowest priced matching eBay listing Ids. Always contains two entries, the first one is the listing id of the lowest priced listing in new condition, the second in used condition. **null or 0** if not available.
Example: *\[ 273344490183, 0 \]* | ### Flags & miscellaneous | Field | Type | Description | | --- | --- | --- | | `isAdultProduct` | Boolean | Indicates if the item is considered to be for adults only.
Example: *true* | | `isHeatSensitive` | Boolean | Indicates if the item is heat sensitive (e.g. meltable).
Example: *true* | | `isMerchOnDemand` | Boolean | True if this product is an Amazon Merch on Demand product. **undefined** otherwise.
Example: *true* | | `isHaul` | Boolean | True if this product is an Amazon Haul product. **undefined** otherwise. Only basic product information is available for Amazon Haul products.
Example: *true* | | `ingredients` | String | The ingredient list of the product. **undefined** if not available.
Example: *Purified Carbonated Water, Natural Flavors* | | `launchpad` | Boolean | Indicates if the item is listed in the launchpad category. If so, the `salesRankReference` will not be available.
Example: *true* | | `audienceRating` | String | Audience rating. The rating suggests the age for which the media is appropriate.
Example: *PG-13 (Parents Strongly Cautioned)* | | `urlSlug` | String | The product listing URL slug.
Example: *Ring-Video-Doorbell-Satin-Nickel-2020-Release* | | `returnRate` | Integer | This field provides information about the customer return rate for a product. The possible values are:
• **null**: The return rate is either unavailable or considered average.
• **1**: The product has a low return rate.
• **2**: The product has a high return rate. | | `isEligibleForSuperSaverShipping` | Boolean | Whether or not the product’s buy box is eligible for free shipping.
Example: *true* | ### FBA & referral fees | Field | Type | Description | | --- | --- | --- | | `fbaFees` | Object | Object containing the FBA pick & pack fee for this product and the timestamp of the last update. The fee corresponds to the FBA pick & pack charge for this product, based on its dimensions and weight, assuming a selling price equal to the current offer price. If there is no current offer, the last known offer price is assumed; if neither is available, a default selling price of 100.00 is used. Values are integers in the marketplace’s smallest currency unit (for example euro cents or yen). **null** if not available. | | `variableClosingFee` | Integer | The variable closing fee for this product. Values are integers in the marketplace’s smallest currency unit (for example euro cents or yen). **undefined** if not applicable.
Example: *81* | | `referralFeePercentage` | Double | The Amazon referral fee percentage at the assumed selling price. The selling price is taken from the current offer price, otherwise the last known offer price, otherwise a default of 100.00. **null** if not available.
Example: *12* | Example `fbaFees` object: ```javascript "fbaFees": { "lastUpdate": keepaTime, "pickAndPackFee": 259 } ``` ### Coupons, promotions & unit count | Field | Type | Description | | --- | --- | --- | | `coupon` | Integer array | Contains coupon details for the buy box offer of the product, if available. **null** if not available. An integer array with two entries:
• The first entry is the discount for a one-time coupon (single purchase).
• The second entry is a Subscribe & Save first-order coupon (S&S initial order only). The Subscribe & Save value represents a clickable one-time coupon that applies only to the first Subscribe & Save order. It does not represent an ongoing Subscribe & Save discount for subsequent deliveries.
Entry value is either **0** if no coupon of that type is offered, **positive** for an absolute discount, or **negative** for a percentage discount. The `coupon` field is always accessible, but only updated if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html).
Examples: *\[ 200, -15 \]* – both coupon types available: $2 one time discount or 15% for subscribe and save. *\[ -7, 0 \]* – only the *one time coupon* type is available, offering a 7% discount. | | `couponHistory` | Integer array | Contains historical values for the `coupon` field, if available. **null** if not available. We started tracking coupon history on June 15th 2024.
Format: \[ keepaTime, one-time coupon, subscribe and save coupon, keepaTime, … \]
Example: *\[2711319, 200, -15, …\]* | | `promotions` | Object array | Contains an array of active promotions. Not all product promotions can be provided. Requires the *offers* parameter to be updated. A promotion object consists of:
• `type` – *String* – The type of promotion: SNS
• `amount` – *Integer* – The discounted price
• `discountPercent` – *Integer* – The discount percent
• `snsBulkDiscountPercent` – *Integer* – The bulk discount percent for repeat SNS deliveries. **undefined** if no data available, **0** if no bulk discount provided. | | `unitCount` | Object | Object that contains unit count data. **undefined** if it has no value.
• `unitValue` – *Double* – The field returns the specified weight or volume to facilitate per unit pricing. For products measured by volume, weight, or linear dimensions, it provides the total net quantity shipped for a single ASIN (e.g., a 12-pack of 6 fl oz bottles of water = 72 fl oz, or a single 2-liter bottle = 2 liters). For products sold as individual units, it returns the total number of units (e.g., a pack of 12 pens = 12).
• `unitType` – *String* – In cases where the product being sold is measured in units that are relevant to the customer’s purchasing decision, the *unitType* specifies the type of measurement used. For example, a bottle of soda may be measured in fluid ounces, while a box of screws is measured by the number of screws in the box.
• `eachUnitCount` – *Double* – The number of units in an ‘each’; where an ‘each’ refers to the smallest component of a product with a UPC, and a unit defines how this ‘each’ is measured. | ### Sales rank, sold & review statistics | Field | Type | Description | | --- | --- | --- | | `stats` | Statistics Object | Optional field, set only if the *stats* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Contains a [Statistics Object](https://env.7xmtools.com/api-docs/statistics-object.html). | | `salesRankReference` | Long | The category node id of the main sales rank. **-1** if not available, **-2** if listed in launchpad.
Example: *281052* – [http://www.amazon.com/b/?node=281052](http://www.amazon.com/b/?node=281052) | | `salesRankReferenceHistory` | Long array | A long array containing the historical category node id(s) of the main sales rank. This data, if available, can be used to match historical sales ranks provided in the `csv` field to their reference category. The category id has the value **-1** if not available or **-2** if listed in launchpad.
Format: \[ keepaTime, category node id, … \]
Example: *\[2711319, 281052, …\]* | | `salesRanks` | Object | An object containing sales rank histories. Each key represents the categoryId of the rank, with the history in the corresponding value. | | `lastSoldUpdate` | Integer | States the last time we have updated the `monthlySold` field, in **Keepa Time minutes**. **undefined** if the monthlySold has no value.
Example: *2711319* | | `monthlySold` | Integer | How often this product was bought in the past month. This field represents the *bought past month* metric found on Amazon search result pages. It is not an estimate. Amazon only provides the data in bracketed ranges such as “10+” or “100+”, rather than as exact figures. **undefined** if it has no value. Most ASINs do not have this value set. The value is variation specific.
Example: *1000* – the ASIN was bought at least 1000 times in the past month. | | `monthlySoldHistory` | Integer array | Contains historical values of the `monthlySold` field. **undefined** if it has no value.
Format: \[ keepaTime, monthlySold, … \] | | `reviews` | Review Object | This object contains **variation specific** review and rating counts histories as well as a last update timestamp. **null** if not available. It is not possible to force an update to the reviews object data. For non-variation specific ratings and review data access the `csv` field. Accessible only if the *rating* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). The *ratingCount* history has not been updated since April 9th 2025 as that data point was removed by Amazon. | Example `salesRanks` object: ```javascript "salesRanks": { "281052": [ keepaTime, salesRank, ... ], "123112042": [ keepaTime, salesRank, ... ] } ``` Format of the `reviews` object: ```javascript "reviews": { "lastUpdate": keepaTime, "ratingCount": [ keepaTime, ratingCount, ... ], "reviewCount": [ keepaTime, reviewCount, ... ] } ``` ### Offers & buy box | Field | Type | Description | | --- | --- | --- | | `offers` | Marketplace Offer Object array | Optional field, set only if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Contains [Marketplace Offer Objects](https://env.7xmtools.com/api-docs/offer-object.html). | | `liveOffersOrder` | Integer array | Optional field, set only if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Contains an ordered array of index positions in the `offers` array for all [Marketplace Offer Objects](https://env.7xmtools.com/api-docs/offer-object.html) retrieved for this call. If no offers were found, the field will be **null**. The sequence of integers reflects the ordering of the offers on the Amazon offer page (for all conditions). Since the `offers` field contains historical offers as well as current offers, one can use this array to look up all offers that are currently listed on Amazon in the correct order.
**Note:** If there are identical offers (same seller, same condition, same shipping type, and same condition text) we only track the lowest-priced one. If this happens, there will be duplicate offer indexes in the *liveOffersOrder* field at the position of the omitted duplicate (higher-priced) offer – all pointing to the lowest-priced offer’s index.
Example: *\[ 3, 5, 2, 18, 15 \]* – the offer with the array index 3 of the `offers` field is currently the first one listed on the offer listings page on Amazon, followed by the offer with the index **5**, and so on.
Example with duplicates: *\[ 3, 5, 2, 18, 5 \]* – the second offer, as listed on Amazon, is a lower-priced duplicate of the 5th offer on Amazon. The lower-priced one is included in the `offers` field at index 5. | | `buyBoxSellerIdHistory` | String array | Optional field, set only if the *offers* or *buybox* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Contains a history of [sellerIds](https://env.7xmtools.com/api-docs/seller.html) that held the Buy Box in the format: **Keepa time minutes, sellerId, \[…\]**. If no seller qualified for the Buy Box, the sellerId **“-1”** is used (suppressed Buy Box). If we were unable to identify the seller or if the product was out of stock (no seller), the sellerId is **“-2”**.
Example: *\["2860926", "ATVPDKIKX0DER", …\]* | | `buyBoxUsedHistory` | String array | Optional field, set only if the *offers* or *buybox* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). A history of **used** buy box winners, containing the [sellerIds](https://env.7xmtools.com/api-docs/seller.html), offer sub-condition, and FBA status in the format: **Keepa time minutes, seller id, condition, isFBA, \[…\]**. If no seller qualified for the used buy box, the sellerId **“”** (empty String) is used.
• *condition* can have the following values: **“2”** – Used - Like New, **“3”** – Used - Very Good, **“4”** – Used - Good, **“5”** – Used - Acceptable
• *isFBA* is either **“1”** – offer is FBA or **“0”** – offer is merchant fulfilled.
Example: *\["2860926", "ATVPDKIKX0DER", "4", "1", …\]* | | `isRedirectASIN` | Boolean | Valid only if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Boolean indicating if the ASIN will be redirected to another one on Amazon (example: the ASIN has the color black variation, which is not available and is redirected on Amazon to the color red). | | `isSNS` | Boolean | Boolean indicating if the product’s Buy Box is available for [subscribe and save](https://www.amazon.com/b?node=5856181011). | | `offersSuccessful` | Boolean | Valid only if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html). Boolean indicating if the system was able to retrieve fresh offer information. A product with no marketplace offers at all still counts as a successful retrieval and returns `true` — there is simply no offer page to fetch (compare COUNT\_\* `csv` entries). | ## The csv History Array The `csv` field is a two-dimensional history array containing the product’s historical data. Access the first dimension index using the following enum/constants: | Index | History type | Entry format | Description | | --- | --- | --- | --- | | **0** | `AMAZON` | time, value | Amazon price history | | **1** | `NEW` | time, value | Marketplace New price history | | **2** | `USED` | time, value | Marketplace Used price history | | **3** | `SALES` | time, value | Sales Rank history (not every product has a Sales Rank; variation items usually don’t have individual sales ranks) | | **4** | `LISTPRICE` | time, value | List Price (MSRP) history | | **5** | `COLLECTIBLE` | time, value | Collectible price history | | **6** | `REFURBISHED` | time, value | Refurbished price history | | **7** | `NEW_FBM_SHIPPING` | time, price, shipping | 3rd party (not including Amazon) New price history including shipping costs, only fulfilled by merchant (FBM). Requires the *offers* parameter. | | **8** | `LIGHTNING_DEAL` | time, value | Lightning Deal price history (special handling required – see the Lightning Deals note below) | | **9** | `WAREHOUSE` | time, value | Amazon Warehouse price history. Requires the *offers* parameter. | | **10** | `NEW_FBA` | time, value | Price history of the lowest 3rd party (not including Amazon/Warehouse) New offer that is fulfilled by Amazon. Requires the *offers* parameter. | | **11** | `COUNT_NEW` | time, value | New offer count history (= count of marketplace merchants selling the product as new) | | **12** | `COUNT_USED` | time, value | Used offer count history | | **13** | `COUNT_REFURBISHED` | time, value | Refurbished offer count history | | **14** | `COUNT_COLLECTIBLE` | time, value | Collectible offer count history | | **15** | `EXTRA_INFO_UPDATES` | time, value | History of past updates to all *offers*-parameter related data: offers, aPlus, videos, isSNS, isRedirectASIN, and the csv types NEW\_FBM\_SHIPPING, WAREHOUSE, NEW\_FBA, RATING, COUNT\_REVIEWS, USED\_\*\_SHIPPING, COLLECTIBLE\_\*\_SHIPPING, BUY\_BOX\_USED\_SHIPPING, PRIME\_EXCL and REFURBISHED\_SHIPPING. As updates to those fields are infrequent, it is essential to know when our system updated them. The absolute value indicates the number of offers fetched at the given time. If the value is positive, it means all available offers were fetched. If negative, there were more offers than fetched. | | **16** | `RATING` | time, value | The product’s rating history (an integer from 0 to 50, e.g., 45 = 4.5 stars). Requires the *offers* parameter. | | **17** | `COUNT_REVIEWS` | time, value | The product’s rating count history. Requires the *offers* parameter. | | **18** | `BUY_BOX_SHIPPING` | time, price, shipping | The New buy box price history, including shipping costs. If no offer qualified for the buy box (or if the buy box is a used offer), the price has the value **-1**. Requires the *offers* parameter. | | **19** | `USED_NEW_SHIPPING` | time, price, shipping | “Used - Like New” price history, including shipping costs. Requires the *offers* parameter. | | **20** | `USED_VERY_GOOD_SHIPPING` | time, price, shipping | “Used - Very Good” price history, including shipping costs. Requires the *offers* parameter. | | **21** | `USED_GOOD_SHIPPING` | time, price, shipping | “Used - Good” price history, including shipping costs. Requires the *offers* parameter. | | **22** | `USED_ACCEPTABLE_SHIPPING` | time, price, shipping | “Used - Acceptable” price history, including shipping costs. Requires the *offers* parameter. | | **23** | `COLLECTIBLE_NEW_SHIPPING` | time, price, shipping | “Collectible - Like New” price history, including shipping costs. Requires the *offers* parameter. | | **24** | `COLLECTIBLE_VERY_GOOD_SHIPPING` | time, price, shipping | “Collectible - Very Good” price history, including shipping costs. Requires the *offers* parameter. | | **25** | `COLLECTIBLE_GOOD_SHIPPING` | time, price, shipping | “Collectible - Good” price history, including shipping costs. Requires the *offers* parameter. | | **26** | `COLLECTIBLE_ACCEPTABLE_SHIPPING` | time, price, shipping | “Collectible - Acceptable” price history, including shipping costs. Requires the *offers* parameter. | | **27** | `REFURBISHED_SHIPPING` | time, price, shipping | Refurbished price history, including shipping costs. Requires the *offers* parameter. | | **28** | `EBAY_NEW_SHIPPING` | time, price, shipping | Price history of the lowest new price on the respective eBay locale, including shipping costs | | **29** | `EBAY_USED_SHIPPING` | time, price, shipping | Price history of the lowest used price on the respective eBay locale, including shipping costs | | **30** | `TRADE_IN` | time, value | [Trade-in](https://www.amazon.com/Amazon-Trade-In/b?ie=UTF8&node=9187220011) price history (Amazon trade-in is not available for every locale) | | **31** | `RENT` | time, value | Not provided. This index is retired and is never populated; it is listed only so the positions of the following types are unambiguous. | | **32** | `BUY_BOX_USED_SHIPPING` | time, price, shipping | The Used buy box price history (any sub-condition), including shipping costs. If no offer qualified for the used buy box, the price has the value **-1**. Requires the *offers* parameter. | | **33** | `PRIME_EXCL` | time, value | Price history of the lowest Prime exclusive New offer. Requires the *offers* parameter. | | **34** | `COUNT_NEW_FBA` | time, value | New FBA offer count history (includes Amazon offer). Added March 2026. | | **35** | `COUNT_NEW_FBM` | time, value | New FBM offer count history. Added March 2026. | ### Important csv information - We only append a new entry to the history array if the price/value changed, not every time we update the product. - Shipping and handling costs are not included unless specified. - For NEW, USED, COLLECTIBLE, and REFURBISHED time series, the pricing definition is as follows: entries dated before Feb 23, 2026, reflect the lowest *listing price*. Entries dated on or after Feb 23, 2026, reflect the lowest *landing price* (listing price + shipping). - Amazon is considered to be part of the marketplace. If Amazon has the overall lowest new price, the marketplace new price in the corresponding time interval is identical to the Amazon price. - The following types are only set if the *offers* parameter was used in the [Product Request](https://env.7xmtools.com/api-docs/product.html): NEW\_FBM\_SHIPPING, WAREHOUSE, NEW\_FBA, RATING, COUNT\_REVIEWS, BUY\_BOX\_SHIPPING, USED\_\*\_SHIPPING, COLLECTIBLE\_\*\_SHIPPING, REFURBISHED\_SHIPPING, BUY\_BOX\_USED\_SHIPPING, and PRIME\_EXCL. > **Note – Lightning Deals:** If a deal is currently active, the last entry of the history array will contain the end date (a future date) with a price of -1. When accessing the current deal price, handle this special case. Alternatively, use the *current* price array of the [stats object](https://env.7xmtools.com/api-docs/statistics-object.html) to access the current price. If no deal is currently active but the last entry has the value -1 with a date in the future, it means an upcoming deal is announced (scheduled to start at that date). > **Note – eBay prices:** eBay listings often have incorrect information and/or product codes, causing item mismatches and incorrect pricing information. Use eBay price history information with caution and do not rely on their accuracy. We update eBay prices at different intervals than Amazon prices. > **Important:** We can add new data types to the `csv` field from time to time without announcement. **Do not expect a fixed size of the first array dimension in your implementation.** ## Decoding the Price History The second dimension of the `csv` array contains the price/value history in the format **Keepa time minutes, value, \[…\]** or, if the type includes **\*\_SHIPPING** costs, the format: **Keepa time minutes, price, shipping costs, \[…\]**. If history is unavailable, it is **null**. - The price is an integer of the respective Amazon locale’s smallest currency unit (e.g., euro cents or yen). - If no offer was available in the given interval (e.g., out of stock), the price has the value **-1**. - Timestamps are **Keepa Time minutes** – see the conversion below. A minimal Python decoder: ```python KEEPA_TIME_OFFSET = 21564000 # minutes; Keepa Time -> Unix epoch offset def keepa_time_to_unix_ms(keepa_minutes): return (keepa_minutes + KEEPA_TIME_OFFSET) * 60000 def decode_csv(history, with_shipping=False): """Decode one csv history array into a list of data points. Plain types: [keepaTime, value, keepaTime, value, ...] *_SHIPPING types: [keepaTime, price, shipping, keepaTime, price, shipping, ...] A value/price of -1 means no offer was available in that interval. """ if history is None: return [] # no history available for this type step = 3 if with_shipping else 2 points = [] for i in range(0, len(history), step): point = { "timestamp_ms": keepa_time_to_unix_ms(history[i]), "value": history[i + 1], } if with_shipping: point["shipping"] = history[i + 2] points.append(point) return points # csv index constants (see table above) AMAZON, NEW, USED, SALES, BUY_BOX_SHIPPING = 0, 1, 2, 3, 18 product = response["products"][0] amazon_history = decode_csv(product["csv"][AMAZON]) buy_box_history = decode_csv(product["csv"][BUY_BOX_SHIPPING], with_shipping=True) ``` ## Keepa Time Minutes Keepa Time minutes is the time format used for **all** timestamps of the product object. To convert a Keepa Time minutes value to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ```python from datetime import datetime, timezone def parse_keepa_time(keepa_minutes): """Convert Keepa Time minutes to a timezone-aware datetime (UTC).""" return datetime.fromtimestamp((keepa_minutes + 21564000) * 60, tz=timezone.utc) ``` ## Example Product objects are returned in the `products` array of a [Product Request](https://env.7xmtools.com/api-docs/product.html) response. A basic request: **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, null, "B00M0QVG3W"); api.sendRequest(r) .done(result -> { Product product = result.products[0]; // newest value of the AMAZON price history int price = ProductAnalyzer.getLast( product.csv[Product.CsvType.AMAZON.index], Product.CsvType.AMAZON); System.out.println(product.title + ": " + price); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, null, null, null, 1, true, ['B00M0QVG3W'])); if ($response->status == ResponseStatus::OK) { $product = $response->products[0]; $amazonHistory = $product->csv[0]; // AMAZON price history echo $product->title . ": " . end($amazonHistory); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B00M0QVG3W"} r = requests.get("https://api.keepa.com/product", params=params) product = r.json()["products"][0] print(product["title"]) amazon = product["csv"][0] # AMAZON price history: [keepaTime, price, ...] print("Latest Amazon price (cents):", amazon[-1]) # -1 = out of stock ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B00M0QVG3W"); const data = await res.json(); const product = data.products[0]; console.log(product.title); const amazon = product.csv[0]; // AMAZON price history: [keepaTime, price, ...] console.log("Latest Amazon price (cents):", amazon[amazon.length - 1]); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B00M0QVG3W" ``` ### Example product object ```json { "productType": 0, "asin": "B00M0QVG3W", "domainId": 1, "title": "Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)", "trackingSince": 2711319, "listedSince": 2705011, "lastUpdate": 7664520, "lastRatingUpdate": 7664201, "lastPriceChange": 7664520, "lastEbayUpdate": 7660034, "images": [ { "l": "81bRlmLRyPL.jpg", "lH": 1500, "lW": 1500, "m": "g1dlEmb2mq3.jpg", "mH": 500, "mW": 500, "variant": "MAIN" } ], "rootCategory": 502394, "categories": [281052], "categoryTree": [ { "catId": 502394, "name": "Camera & Photo" }, { "catId": 281052, "name": "Point-and-Shoot Digital Cameras" } ], "parentAsin": null, "frequentlyBoughtTogether": ["B00T85PMWY"], "eanList": ["8714574623290"], "upcList": ["013803243871"], "manufacturer": "Canon", "brand": "Canon", "websiteDisplayGroup": "photo_display_on_website", "websiteDisplayGroupName": "photo", "salesRankDisplayGroup": "photo_display_on_website", "type": "CAMERA_DIGITAL", "partNumber": "9542B001", "binding": "Electronics", "model": "SX400", "color": "Black", "numberOfItems": 1, "releaseDate": 20140929, "features": [ "30x Optical Zoom with 24mm Wide-Angle lens", "16.0 Megapixel CCD sensor with DIGIC 4+ Image Processor" ], "packageHeight": 91, "packageLength": 175, "packageWidth": 137, "packageWeight": 540, "packageQuantity": 1, "itemHeight": 69, "itemLength": 104, "itemWidth": 80, "itemWeight": 313, "availabilityAmazon": 0, "buyBoxEligibleOfferCounts": [3, 5, 1, 2, 0, 0, 0, 0], "competitivePriceThreshold": 18990, "ebayListingIds": [273344490183, 0], "isAdultProduct": false, "isHeatSensitive": false, "launchpad": false, "isSNS": false, "urlSlug": "Canon-PowerShot-SX400-Digital-Optical", "isEligibleForSuperSaverShipping": true, "fbaFees": { "lastUpdate": 7664213, "pickAndPackFee": 384 }, "referralFeePercentage": 8, "coupon": [200, 0], "salesRankReference": 281052, "salesRanks": { "281052": [7650101, 4823, 7660440, 5102, 7664520, 4991] }, "lastSoldUpdate": 7664100, "monthlySold": 100, "monthlySoldHistory": [7620400, 50, 7650300, 100], "csv": [ [7650101, 19900, 7655230, 18999, 7664520, 19499], [7650101, 18990, 7660440, 18500], [7650101, 14999, 7663880, 15250], [7650101, 4823, 7660440, 5102, 7664520, 4991], [7650101, 24999], null, null, [7650101, 18990, 450, 7660440, 18500, 499] ] } ``` *Object shortened for readability; illustrative values only. Real product objects contain many more fields, and the `csv` array covers the history types listed above (`null` where no history exists) – here it is truncated after index 7 (NEW\_FBM\_SHIPPING, which uses the time, price, shipping triplet format). Prices are integers in the locale’s smallest currency unit; timestamps are Keepa Time minutes.* # Statistics Object Source: https://env.7xmtools.com/api-docs/statistics-object.html Aggregated price, sales rank, out-of-stock and Buy Box statistics for a product. Returned as the `stats` field of the Product Object when the Product Request’s `stats` parameter is used. JSON Object · Returned by: Product Request (stats parameter) ## About The statistics object contains aggregated information for a product: last known prices and ranks, weighted averages over several time windows, all-time and per-interval extreme values, out-of-stock percentages, sales rank drop counts, Lightning Deal information and detailed Buy Box data. It is returned by the [Product Request](https://env.7xmtools.com/api-docs/product.html) if the `stats` parameter was used and is part of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) (accessible as its `stats` field). > **Important:** Some fields are only set if the `offers` parameter of the Product Request was utilized *and* the marketplace data was successfully retrieved. Verify this via the `offersSuccessful` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html). ## Format ```json { "current": Integer array, "avg": Integer array, "avg30": Integer array, "avg90": Integer array, "avg180": Integer array, "avg365": Integer array, "atIntervalStart": Integer array, "min": two-dimensional Integer array, "max": two-dimensional Integer array, "minInInterval": two-dimensional Integer array, "maxInInterval": two-dimensional Integer array, "outOfStockPercentageInInterval": Integer array, "outOfStockPercentage30": Integer array, "outOfStockPercentage90": Integer array, "outOfStockPercentage180": Integer array, "outOfStockPercentage365": Integer array, "lastOffersUpdate": Integer, "salesRankDrops30": Integer, "salesRankDrops90": Integer, "salesRankDrops180": Integer, "salesRankDrops365": Integer, "totalOfferCount": Integer, "lightningDealInfo": Integer array, // The following fields are only set if the offers or buybox parameter was used "lastBuyBoxUpdate": Integer, "buyBoxSellerId": String, "buyBoxPrice": Integer, "buyBoxShipping": Integer, "buyBoxSavingBasis": Integer, "buyBoxSavingBasisType": String, "buyBoxSavingPercentage": Integer, "buyBoxIsUnqualified": Boolean, "buyBoxIsShippable": Boolean, "buyBoxIsPreorder": Boolean, "buyBoxIsBackorder": Boolean, "buyBoxIsFBA": Boolean, "buyBoxIsAmazon": Boolean, "buyBoxIsMAP": Boolean, "buyBoxPriceIncludesImportFees": Boolean, "buyBoxAvailabilityMessage": String, "buyBoxShippingTime": Integer array, "buyBoxShippingCountry": String, "buyBoxIsPrimeExclusive": Boolean, "buyBoxIsPrimeEligible": Boolean, "buyBoxStats": Object, "buyBoxUsedStats": Object, "buyBoxUsedPrice": Integer, "buyBoxUsedShipping": Integer, "buyBoxUsedSellerId": String, "buyBoxUsedIsFBA": Boolean, "buyBoxUsedCondition": Integer, // The following fields are only set if the offers parameter was used "retrievedOfferCount": Integer, "sellerIdsLowestFBA": String array, "sellerIdsLowestFBM": String array, "offerCountFBA": Integer, "offerCountFBM": Integer, // The following fields are only set if the stock parameter was used "stockAmazon": Integer, "stockBuyBox": Integer } ``` ## Price Type Indexing All per-type arrays of the statistics object (`current`, `avg`, `avg30`…`avg365`, `atIntervalStart`, `min`/`max`, `minInInterval`/`maxInInterval` and the `outOfStockPercentage…` arrays) use the **Price Type indexing** of the `csv` history array — refer to the `csv` field documentation in the [Product Object](https://env.7xmtools.com/api-docs/product-object.html). The value at index `i` of a statistics array refers to the same data type as `csv[i]`. Excerpt of the price type indices (see the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) for the complete list): | Index | Name | Meaning of the value at this index | | --- | --- | --- | | **0** | `AMAZON` | Amazon price | | **1** | `NEW` | Marketplace New price | | **2** | `USED` | Marketplace Used price | | **3** | `SALES` | Sales Rank (a rank, not a price) | | **4** | `LISTPRICE` | List Price (MSRP) | | **11** | `COUNT_NEW` | New offer count (a count, not a price) | | **12** | `COUNT_USED` | Used offer count (a count, not a price) | | **18** | `BUY_BOX_SHIPPING` | Buy Box price including shipping | - Prices are integers in the smallest currency unit of the respective Amazon locale (e.g. euro cents or yen). - Depending on the price type, an entry can also be a sales rank, an offer count or another non-price value — the unit is determined by the price type at that index. - A value of `-1` means no data / no offer was available (see the per-field descriptions below for the exact semantics). - Do not assume a fixed array length — always access the arrays by price type index. ## Fields ### Core statistics fields These fields are set whenever the `stats` parameter was used. Fields referring to “the interval” relate to the interval specified in the Product Request’s `stats` parameter (see [The stats Parameter](https://env.7xmtools.com/api-docs/statistics-object.html#stats-parameter) below). | Field | Type | Description | | --- | --- | --- | | `current` | Integer array | Contains the last updated product prices/ranks using the Price Type indexing (refer to the `csv` field in the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). Prices are integers representing the smallest currency unit for the respective Amazon locale (e.g. euro cents or yen). A value of `-1` indicates no offer was available in the given interval (e.g. out of stock). | | `avg` | Integer array | Contains the historical weighted mean for the interval specified in the Product Request’s `stats` parameter, using the Price Type indexing. A value of `-1` indicates no offer was available in the interval or insufficient data. | | `avg30` | Integer array | Same as `avg`, but for the last 30 days. | | `avg90` | Integer array | Same as `avg`, but for the last 90 days. | | `avg180` | Integer array | Same as `avg`, but for the last 180 days. | | `avg365` | Integer array | Same as `avg`, but for the last 365 days. | | `atIntervalStart` | Integer array | Contains the prices registered at the start of the interval specified in the Product Request’s `stats` parameter, using the Price Type indexing. A value of `-1` indicates no offer was available in the interval or insufficient data. | | `min` | Two-dimensional Integer array | Contains the lowest prices ever registered for this product. The first dimension uses the Price Type indexing. The second dimension is either `null` (no data available for the price type) or an array of size 2: the first value is the time of the extreme point (in Keepa Time minutes), the second value is the respective extreme value. | | `max` | Two-dimensional Integer array | Contains the highest prices ever registered for this product. Same structure as `min`. | | `minInInterval` | Two-dimensional Integer array | Same as `min`, but restricted to the interval specified in the Product Request’s `stats` parameter. | | `maxInInterval` | Two-dimensional Integer array | Same as `max`, but restricted to the interval specified in the Product Request’s `stats` parameter. | | `outOfStockPercentageInInterval` | Integer array | Contains the out-of-stock percentage in the interval specified in the Product Request’s `stats` parameter, using the Price Type indexing. A value of `-1` indicates insufficient data or that the price type is not a price. Examples: `0` = never out of stock; `100` = out of stock 100% of the time; `25` = out of stock 25% of the time. | | `outOfStockPercentage30` | Integer array | Contains the 30-day out-of-stock percentage, using the Price Type indexing. A value of `-1` indicates insufficient data or that the price type is not a price. | | `outOfStockPercentage90` | Integer array | Same as `outOfStockPercentage30`, but for the last 90 days. | | `outOfStockPercentage180` | Integer array | Same as `outOfStockPercentage30`, but for the last 180 days. | | `outOfStockPercentage365` | Integer array | Same as `outOfStockPercentage30`, but for the last 365 days. | | `lastOffersUpdate` | Integer | The last time the offers information was updated, in Keepa Time minutes. It advances only with a successful retrieval, so a failed one leaves it unchanged. `-1` if the offers information was never retrieved for this product. | | `salesRankDrops30` | Integer | The count of sales rank drops (from a high to a low value) within the last 30 days — considered to indicate sales. | | `salesRankDrops90` | Integer | Same as `salesRankDrops30`, but for the last 90 days. | | `salesRankDrops180` | Integer | Same as `salesRankDrops30`, but for the last 180 days. | | `salesRankDrops365` | Integer | Same as `salesRankDrops30`, but for the last 365 days. | | `totalOfferCount` | Integer | The total count of offers for this product (all conditions combined). The offer count per condition can be found in the `current` field (count price types, e.g. index 11 `COUNT_NEW`, index 12 `COUNT_USED`). `-2` if the count is not known. | | `lightningDealInfo` | Integer array | Used to identify a past, upcoming or current Lightning Deal offer. The format is `[startDate, endDate]` (always an array of length 2 if not `null`). It is `null` if the product never had a Lightning Deal. Both timestamps are in UTC and Keepa Time minutes.
• Upcoming Lightning Deal: only `startDate` is set (`endDate` has the value `-1`).
• Current Lightning Deal: both are set, with `startDate` older than the current time and `endDate` in the future.
• Only a past deal: both `startDate` and `endDate` are in the past. | ### Fields only set if the `offers` or `buybox` parameter was used | Field | Type | Description | | --- | --- | --- | | `lastBuyBoxUpdate` | Integer | Timestamp of the last Buy Box update, in Keepa Time minutes. | | `buyBoxSellerId` | String | The seller ID of the Buy Box offer, if it exists. Otherwise `"-1"`, `"-2"` or `null`. | | `buyBoxPrice` | Integer | The Buy Box **new** price, if it exists. Otherwise `-1` or `-2`. | | `buyBoxShipping` | Integer | The Buy Box **new** shipping cost, if it exists. Otherwise `-1` or `-2`. | | `buyBoxSavingBasis` | Integer | The Buy Box **new** strikethrough price, if it exists. Undefined (field absent) if unavailable. | | `buyBoxSavingBasisType` | String | The reference type of the Buy Box **new** strikethrough price, if it exists: either `LIST_PRICE` or `WAS_PRICE`. Undefined (field absent) if unavailable. | | `buyBoxSavingPercentage` | Integer | The stated percentage discount of the Buy Box **new** price, if it exists. Undefined (field absent) if unavailable. | | `buyBoxIsUnqualified` | Boolean | Indicates whether a seller won the Buy Box. If only sellers with poor offers are available, none qualifies for the Buy Box. | | `buyBoxIsShippable` | Boolean | Indicates whether the Buy Box is listed as being shippable. | | `buyBoxIsPreorder` | Boolean | Indicates if the Buy Box is a pre-order. | | `buyBoxIsBackorder` | Boolean | Indicates if the Buy Box is back-ordered. | | `buyBoxIsFBA` | Boolean | Indicates whether the Buy Box is fulfilled by Amazon. | | `buyBoxIsAmazon` | Boolean | Indicates if Amazon is the seller in the Buy Box. | | `buyBoxIsMAP` | Boolean | Indicates if the Buy Box **new** price is hidden on Amazon due to MAP (Minimum Advertised Price) restrictions. | | `buyBoxPriceIncludesImportFees` | Boolean | Indicates whether the price **Amazon displays** for the Buy Box offer includes the import fees deposit. When `true`, the `buyBoxPrice` reported here does **not** include those fees. `null` if not established for this product, which is not the same as `false`. | | `buyBoxAvailabilityMessage` | String | The availability of the Buy Box offer, as one of three values:
• `IN_STOCK` — available to ship now
• `BACKORDER_NO_ETA` — available to order, but no delivery estimate is known
• `BACKORDER_WITH_ETA` — available to order, with a known delivery estimate
`null` if not available. | | `buyBoxShippingTime` | Integer array | The estimated handling time range (minimum and maximum hours) before the Buy Box offer ships. `null` if unavailable. Example: `[24, 48]` (= available to ship in 1–2 days). Added in a later official update. | | `buyBoxShippingCountry` | String | The default shipping country of the Buy Box seller. `null` if not available or if the seller is Amazon. Example: `"US"` | | `buyBoxIsPrimeExclusive` | Boolean | Indicates if the Buy Box is Prime exclusive. `null` if not available. | | `buyBoxIsPrimeEligible` | Boolean | Indicates if the Buy Box is Prime eligible. `null` if not available. | | `buyBoxStats` | Object | Contains Buy Box statistics for the specified interval. Each key is the `sellerId` of a Buy Box seller, and each value is an object with statistics (see below). | | `buyBoxUsedStats` | Object | Contains **used** Buy Box statistics for the specified interval. The format is the same as `buyBoxStats`. | | `buyBoxUsedPrice` | Integer | The Buy Box **used** price, if available. Otherwise `-1` or `null`. | | `buyBoxUsedShipping` | Integer | The Buy Box **used** shipping cost, if available. Otherwise `-1` or `null`. | | `buyBoxUsedSellerId` | String | The seller ID of the **used** Buy Box offer, if available. Otherwise `null`. | | `buyBoxUsedIsFBA` | Boolean | Indicates whether the **used** Buy Box is fulfilled by Amazon. | | `buyBoxUsedCondition` | Integer | The offer sub-condition of the **used** Buy Box (see the sub-condition table below). | #### Per-seller entries in `buyBoxStats` / `buyBoxUsedStats` | Field | Type | Description | | --- | --- | --- | | `avgNewOfferCount` | Integer | Average “New” offer count during the time the seller held the Buy Box. | | `avgPrice` | Integer | Average price of the Buy Box offer from this seller. | | `isFBA` | Boolean | Whether this offer is fulfilled by Amazon. | | `lastSeen` | Integer | Last time the seller won the Buy Box, in Keepa Time minutes. | | `percentageWon` | Float | Percentage of the time the seller won the Buy Box, for non-Prime shoppers. | Example: ```javascript "buyBoxStats": { "ATVPDKIKX0DER": { "avgNewOfferCount": 1, // Average "New" offer count during the time the seller held the Buy Box "avgPrice": 1466, // Average price of the Buy Box offer from this seller "isFBA": false, // Whether this offer is fulfilled by Amazon "lastSeen": 5911806, // Last time the seller won the buy box (Keepa Time minutes) "percentageWon": 100.0 // Percentage of time the seller won the buy box for non-prime shoppers } } ``` #### Used Buy Box sub-conditions (`buyBoxUsedCondition`) | Value | Condition | | --- | --- | | `2` | Used – Like New | | `3` | Used – Very Good | | `4` | Used – Good | | `5` | Used – Acceptable | ### Fields only set if the `offers` parameter was used | Field | Type | Description | | --- | --- | --- | | `retrievedOfferCount` | Integer | The count of offers retrieved for this request. `-2` if no offers were retrieved for this request: either the retrieval failed (`offersSuccessful` is `false`), or none took place because our offer data was already recent enough (see the `update` parameter of the [Product Request](https://env.7xmtools.com/api-docs/product.html)). `-2` is not an error code and does not state a reason. A successful retrieval for a product without offers returns `0`. | | `sellerIdsLowestFBA` | String array | Contains the seller IDs (if any) of the lowest-priced live **new FBA** offers. Multiple entries exist if multiple offers share the same price. | | `sellerIdsLowestFBM` | String array | Contains the seller IDs (if any) of the lowest-priced live **new FBM** offers. Multiple entries exist if multiple offers share the same price. | | `offerCountFBA` | Integer | The count of retrieved live new **FBA** offers, if available. Otherwise `-2`. | | `offerCountFBM` | Integer | The count of retrieved live new **FBM** offers, if available. Otherwise `-2`. | ### Fields only set if the `stock` parameter was used | Field | Type | Description | | --- | --- | --- | | `stockAmazon` | Integer | The stock of the Amazon offer, if available. Otherwise undefined (field absent). | | `stockBuyBox` | Integer | The stock of the Buy Box offer, if available. Otherwise undefined (field absent). | ## The stats Parameter The statistics object is only included in a product if the `stats` parameter was added to the [Product Request](https://env.7xmtools.com/api-docs/product.html). Its value defines the interval the interval-based statistics are calculated for — either as the number of most-recent days, or as an explicit date range: ``` stats=90 last 90 days stats=180 last 180 days stats=2015-10-20,2015-12-24 interval from Oct 20 to Dec 24, 2015 (ISO 8601 dates) stats=1445299200000,1450915200000 the same interval as Unix epoch time in milliseconds ``` The chosen interval affects the fields `avg`, `atIntervalStart`, `minInInterval`, `maxInInterval`, `outOfStockPercentageInInterval` as well as `buyBoxStats` and `buyBoxUsedStats` (“for the specified interval”). The fixed-window fields (`avg30`/`avg90`/`avg180`/`avg365`, `outOfStockPercentage30`…`365`, `salesRankDrops30`…`365`) are independent of the chosen interval. Which field groups are present additionally depends on other Product Request parameters: | Request parameters | Field groups included | | --- | --- | | `stats` | Core statistics fields | | `stats` + `offers` or `buybox` | Additionally the Buy Box fields (`lastBuyBoxUpdate` … `buyBoxUsedCondition`) | | `stats` + `offers` | Additionally the offer fields (`retrievedOfferCount`, `sellerIdsLowestFBA`/`FBM`, `offerCountFBA`/`FBM`) | | `stats` + `stock` | Additionally `stockAmazon` and `stockBuyBox` | > **Tip:** When relying on the `offers`-dependent fields, always check the `offersSuccessful` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) to verify that the marketplace offer data was successfully retrieved. ## Keepa Time Minutes Time format used for all timestamps in this object. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ```javascript unixMs = (keepaTime + 21564000) * 60000; unixSec = (keepaTime + 21564000) * 60; ``` ## Example Request a product with a 90-day statistics interval and marketplace offers (which also enables the Buy Box and offer statistics fields): ``` GET https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&stats=90&offers=20 ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, 90, 20, "B0F3GWXLTS") // stats=90, offers=20; api.sendRequest(r) .done(result -> { Product product = result.products[0]; System.out.println(product.stats.current[0]); // current AMAZON price }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, 20, null, null, 1, true, ['B0F3GWXLTS'], ["stats" => "90"])); if ($response->status == ResponseStatus::OK) { $product = $response->products[0]; print_r($product->stats->current); } ``` **Python** ```python import requests params = { "key": "YOUR_API_KEY", "domain": 1, # amazon.com "asin": "B0F3GWXLTS", "stats": 90, # statistics interval: last 90 days "offers": 20, # enables the Buy Box and offer statistics fields } r = requests.get("https://api.keepa.com/product", params=params) product = r.json()["products"][0] stats = product["stats"] AMAZON, NEW = 0, 1 # csv price type indices print("Current NEW price (cents):", stats["current"][NEW]) print("90-day avg NEW price (cents):", stats["avg"][NEW]) print("Amazon out-of-stock % (interval):", stats["outOfStockPercentageInInterval"][AMAZON]) if stats["min"][NEW] is not None: when, price = stats["min"][NEW] unix_ms = (when + 21564000) * 60000 print("Lowest NEW price ever:", price, "cents at", unix_ms) ``` **Node.js** ```javascript const url = "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&stats=90&offers=20"; const res = await fetch(url); const data = await res.json(); const stats = data.products[0].stats; const NEW = 1; // csv price type index console.log("Current NEW price (cents):", stats.current[NEW]); console.log("90-day avg NEW price (cents):", stats.avg[NEW]); console.log("Buy Box:", stats.buyBoxPrice, "cents, seller", stats.buyBoxSellerId); ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&stats=90&offers=20" ``` ### Example stats object The statistics object is located inside each product of the response (`products[0].stats`): ```json { "current": [3499, 3289, 2646, 5321, 4999, -1, -1, 3428, -1, 2795, 3289, 14, 5], "avg": [3544, 3310, 2701, 4876, 4999, -1, -1, 3465, -1, 2811, 3315, 13, 4], "avg30": [3521, 3298, 2688, 5104, 4999, -1, -1, 3440, -1, 2801, 3301, 14, 5], "avg90": [3544, 3310, 2701, 4876, 4999, -1, -1, 3465, -1, 2811, 3315, 13, 4], "avg180": [3587, 3345, 2730, 4655, 4999, -1, -1, 3492, -1, 2843, 3350, 13, 4], "avg365": [3610, 3378, 2779, 4392, 4999, -1, -1, 3521, -1, 2870, 3384, 12, 4], "atIntervalStart": [3599, 3349, 2724, 4311, 4999, -1, -1, 3499, -1, 2850, 3349, 12, 4], "min": [[7211460, 2999], [7204320, 2846], [7250100, 2200], [7654890, 398], [6988200, 4999], null, null, [7204320, 3046], null, [7422780, 2312], [7204500, 2899], [7100220, 4], [7233060, 1]], "max": [[6870300, 4599], [6865200, 4499], [6912000, 3599], [7031400, 18744], [6988200, 4999], null, null, [6865200, 4699], null, [7521300, 3105], [6865440, 4520], [7590600, 21], [7412160, 8]], "minInInterval": [[7622340, 3299], [7601100, 3149], [7588020, 2515], [7654890, 398], [7533420, 4999], null, null, [7601100, 3349], null, [7612560, 2698], [7601160, 3160], [7548000, 9], [7539840, 2]], "maxInInterval": [[7539900, 3699], [7546200, 3455], [7639080, 2799], [7561200, 9866], [7533420, 4999], null, null, [7546200, 3655], null, [7650300, 2930], [7546260, 3470], [7660980, 16], [7655400, 6]], "outOfStockPercentageInInterval": [18, 0, 4, -1, -1, -1, -1, 0, -1, 37, 0, -1, -1], "outOfStockPercentage30": [12, 0, 5, -1, -1, -1, -1, 0, -1, 29, 0, -1, -1], "outOfStockPercentage90": [18, 0, 4, -1, -1, -1, -1, 0, -1, 37, 0, -1, -1], "outOfStockPercentage180": [22, 1, 6, -1, -1, -1, -1, 1, -1, 41, 1, -1, -1], "outOfStockPercentage365": [25, 1, 8, -1, -1, -1, -1, 1, -1, 45, 1, -1, -1], "lastOffersUpdate": 7663255, "salesRankDrops30": 41, "salesRankDrops90": 118, "salesRankDrops180": 224, "salesRankDrops365": 431, "totalOfferCount": 19, "lightningDealInfo": null, "lastBuyBoxUpdate": 7663255, "buyBoxSellerId": "ATVPDKIKX0DER", "buyBoxPrice": 3499, "buyBoxShipping": 0, "buyBoxSavingBasis": 4999, "buyBoxSavingBasisType": "LIST_PRICE", "buyBoxSavingPercentage": 30, "buyBoxIsUnqualified": false, "buyBoxIsShippable": true, "buyBoxIsPreorder": false, "buyBoxIsBackorder": false, "buyBoxIsFBA": true, "buyBoxIsAmazon": true, "buyBoxIsMAP": false, "buyBoxPriceIncludesImportFees": false, "buyBoxAvailabilityMessage": "IN_STOCK", "buyBoxShippingTime": [24, 48], "buyBoxShippingCountry": null, "buyBoxIsPrimeExclusive": false, "buyBoxIsPrimeEligible": true, "buyBoxStats": { "ATVPDKIKX0DER": { "avgNewOfferCount": 18, "avgPrice": 3512, "isFBA": true, "lastSeen": 7663255, "percentageWon": 74.5 }, "A2L77EE7U53NWQ": { "avgNewOfferCount": 17, "avgPrice": 3448, "isFBA": true, "lastSeen": 7659110, "percentageWon": 25.5 } }, "buyBoxUsedStats": { "A2L77EE7U53NWQ": { "avgNewOfferCount": 5, "avgPrice": 2687, "isFBA": true, "lastSeen": 7663255, "percentageWon": 100.0 } }, "buyBoxUsedPrice": 2646, "buyBoxUsedShipping": 0, "buyBoxUsedSellerId": "A2L77EE7U53NWQ", "buyBoxUsedIsFBA": true, "buyBoxUsedCondition": 3, "retrievedOfferCount": 19, "sellerIdsLowestFBA": ["A2L77EE7U53NWQ"], "sellerIdsLowestFBM": ["A3F2K9QLX8B7MN"], "offerCountFBA": 11, "offerCountFBM": 8 } ``` Illustrative values, abridged for readability: the per-type arrays are truncated to the first 13 price types (indices 0–12: 0 `AMAZON`, 1 `NEW`, 2 `USED`, 3 `SALES`, 4 `LISTPRICE`, 5 `COLLECTIBLE`, 6 `REFURBISHED`, 7 `NEW_FBM_SHIPPING`, 8 `LIGHTNING_DEAL`, 9 `WAREHOUSE`, 10 `NEW_FBA`, 11 `COUNT_NEW`, 12 `COUNT_USED`); real responses contain further types (see the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). Prices are in US cents (`domain=1`, e.g. `3499` = $34.99), index 3 holds the sales rank and indices 11/12 hold offer counts. In `min`/`max`, `null` means no data exists for that price type; the `stockAmazon`/`stockBuyBox` fields are absent because the `stock` parameter was not used. All timestamps are Keepa Time minutes. # Marketplace Offer Object Source: https://env.7xmtools.com/api-docs/offer-object.html The offer object represents a single marketplace offer for a product — its seller, condition, Prime/FBA flags, coupons and the full price, shipping, stock and Prime exclusive price histories. JSON Object · Returned by: Product Request (offers parameter) The offer object is returned by the [Product Request](https://env.7xmtools.com/api-docs/product.html) when the optional `offers` parameter is used, and it is part of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) (in its `offers` array). ## Important to Know Updating billions of marketplace offers regularly is not feasible. The product request’s `offers` parameter determines how many offers Keepa retrieves/updates. Keepa always fetches the best offers, as sorted by Amazon, in all conditions. If a product has more offers than requested, those will not be retrieved. > **Important:** The order of offers constantly changes, and a different amount of offers can be retrieved with each data retrieval. Because of this — and because Keepa maintains a history of offers — you will almost certainly encounter outdated offers. The following is therefore crucial: > > 1. **Evaluate the `lastSeen` field — only process fresh and active offers if you are not interested in past offers.** Alternatively, you can use the `liveOffersOrder` field of the [product object](https://env.7xmtools.com/api-docs/product-object.html). > 2. The history of an offer (its past prices and shipping costs) is often not without gaps. Evaluate the `EXTRA_INFO_UPDATES` *csv*-type of the [product object](https://env.7xmtools.com/api-docs/product-object.html) to find out when the offers were updated. If you need complete coverage of (all) offers for a product, you must request it regularly. If there are almost identical offers — same seller, same condition, and same shipping type — only the one with the cheapest price is provided in the offers list. While duplicates are not listed, their price & condition comment are provided via the `offerDuplicates` field. ## Format ```json { "offerId": Integer, "lastSeen": Integer, "sellerId": String, "isPrime": Boolean, "isFBA": Boolean, "isMAP": Boolean, "isShippable": Boolean, "isPreorder": Boolean, "isWarehouseDeal": Boolean, "isAmazon": Boolean, "isPrimeExcl": Boolean, "coupon": Integer, "couponHistory": Integer array, "condition": Integer, "conditionComment": String, "minOrderQty": Integer, "savingBasis": Integer, "savingBasisType": Integer, "lastStockUpdate": Integer, "offerCSV": Integer array, "stockCSV": Integer array, "primeExclCSV": Integer array, "offerDuplicates": Object array } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `offerId` | Integer | Unique ID of this offer (in the scope of the product). Not related to the offerIds used by Amazon, as those are user-specific and valid only for a short time. The `offerId` can be used to identify the same offers throughout requests.
Example: `4` | | `lastSeen` | Integer | Indicates the last time this offer was seen (and updated), in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/offer-object.html#keepa-time-minutes). If you are only interested in live offers, use this field to verify that the offer is current.
Example: `2700145` | | `sellerId` | String | The seller ID of the merchant.
Example: [`A2L77EE7U53NWQ`](https://www.amazon.com/sp?marketplaceID=ATVPDKIKX0DER&seller=A2L77EE7U53NWQ) (Amazon.com Warehouse Deals) | | `isPrime` | Boolean | Whether or not this offer is available via Prime shipping. Keepa is unable to reliably identify SFP — Seller Fulfilled Prime.
Example: `true` | | `isFBA` | Boolean | Whether or not this offer is fulfilled by Amazon.
Example: `true` | | `isMAP` | Boolean | If the price of this offer is hidden on Amazon due to a MAP (“minimum advertised price”) restriction. Even if so, the offer object will contain the price and shipping costs.
Example: `false` | | `isShippable` | Boolean | Boolean value indicating whether or not the offer is currently shippable. If not, this could mean, for example, that it is temporarily out of stock or a pre-order.
Example: `true` | | `isPreorder` | Boolean | Indicating whether or not the offer is a pre-order.
Example: `false` | | `isWarehouseDeal` | Boolean | Indicating whether or not the offer is a Warehouse Deal.
Example: `false` | | `isAmazon` | Boolean | True if the seller is Amazon (e.g. “Amazon.com”). Note: Amazon’s Warehouse Deals seller account or other accounts Amazon is maintaining under a different name are *not* considered to be Amazon.
Example: `false` | | `isPrimeExcl` | Boolean | This offer has a discounted Prime exclusive price.
Example: `false` | | `coupon` | Integer | Contains one-time coupon details of this offer. Undefined if none is available. Positive integer for an absolute discount or negative for a percentage discount.
Examples: `500` — coupon with a $5 discount; `-15` — coupon with a 15% discount. | | `couponHistory` | Integer array | Contains the coupon history of this offer, if available. It has the format **Keepa Time minutes, coupon, \[…\]**. | | `condition` | Integer | The condition of the offered product, as an integer value — see the [condition values table](https://env.7xmtools.com/api-docs/offer-object.html#condition-values) below.
Note: *Open Box* conditions are coded as *Used* conditions. | | `conditionComment` | String | The describing text of the condition. **undefined** if unavailable.
Example: *“The item may come repackaged. Small cosmetic imperfection on top, \[…\]”* | | `minOrderQty` | Integer | Minimum order quantity. This field will only appear in the response if there is a value.
Example: `2` | | `savingBasis` | Integer | The offer’s strikethrough reference price, if Amazon shows one. Use `savingBasisType` to tell what the number is — it is not always a list price. This field will only appear in the response if there is a value.
Example: `2185` — a reference price of $21.85 | | `savingBasisType` | Integer | What `savingBasis` refers to. This field will only appear in the response if there is a value.
`1` — *typical price*: the median price customers paid over the last 90 days.
`2` — *recent lowest price*: the lowest price of the last 30 days, shown in the EU.
`3` — *list price*: the manufacturer’s suggested price (also RRP, UVP, M.R.P.).
`4` — *new price*: the price of a new item, shown alongside a used offer. | | `lastStockUpdate` | Integer | The most recent update of the stock data for this offer, in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/offer-object.html#keepa-time-minutes).
Example: `2711319` | | `offerCSV` | Integer array | Contains the current price and shipping costs of the offer as well as, if available, the offer’s history. See [offerCSV format](https://env.7xmtools.com/api-docs/offer-object.html#offercsv) below. | | `stockCSV` | Integer array | The stock history for this offer, provided the `stock` [product request](https://env.7xmtools.com/api-docs/product.html) parameter was utilized. This data represents Keepa’s best attempt to determine the available stock quantity for this offer, though it may not always be accurate, such as in instances where per-customer limits apply. Stock data availability is not guaranteed. **undefined** if unavailable.
It has the format **Keepa Time minutes, stock, \[…\]**. | | `primeExclCSV` | Integer array | Contains the Prime exclusive price history of this offer, if available. A Prime exclusive offer can only be ordered if the buyer has an active Prime subscription. See [primeExclCSV format](https://env.7xmtools.com/api-docs/offer-object.html#primeexclcsv) below. | | `offerDuplicates` | Object array | An array that lists identical offers detected for the same seller, condition, and shipping type that were excluded from the main *offers* list because they were not the cheapest. **undefined** if unavailable. See [offerDuplicates format](https://env.7xmtools.com/api-docs/offer-object.html#offerduplicates) below. | ### Condition values | Value | Condition | | --- | --- | | `0` | Unknown: unable to determine the condition | | `1` | New | | `2` | Used - Like New | | `3` | Used - Very Good | | `4` | Used - Good | | `5` | Used - Acceptable | | `6` | Refurbished | | `7` | Collectible - Like New | | `8` | Collectible - Very Good | | `9` | Collectible - Good | | `10` | Collectible - Acceptable | | `11` | Rental | > **Note:** *Open Box* conditions are coded as *Used* conditions. ### offerCSV format The `offerCSV` array has the format **Keepa Time minutes, price, shipping cost, \[…\]**: - The price and shipping cost are integers of the respective Amazon locale’s smallest currency unit (e.g. euro cents or yen). - If the price or shipping cost could not be determined, they have the value `-2`. - Free shipping has the shipping cost of `0`. - If an offer is not shippable or has unspecified shipping costs, the shipping cost will be `-1`. - To get the newest price and shipping cost, access the last two entries of the array: ```javascript // Most recent price: offerCSV[offerCSV.length - 2] // Most recent shipping cost: offerCSV[offerCSV.length - 1] ``` ### primeExclCSV format The `primeExclCSV` array has the format **Keepa Time minutes, price, \[…\]**: - The price is an integer of the respective Amazon locale’s smallest currency unit (e.g. euro cents or yen). - If no Prime exclusive price exists, the price will be `-1` or the field will be `null`. - To get the most recent Prime exclusive price: ```javascript primeExclCSV[primeExclCSV.length - 1] ``` ### offerDuplicates format Each entry provides the price, shipping cost and condition comment of a duplicate offer (same seller, condition and shipping type) that was excluded from the main offers list because it was not the cheapest: ```json "offerDuplicates": [{ "price": 1900, "shipping": 400, "conditionComment": "Open Box, Works great!" }] ``` ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ```javascript const unixMs = (keepaTime + 21564000) * 60000; const unixSeconds = (keepaTime + 21564000) * 60; const date = new Date(unixMs); ``` ## Example Offer objects are retrieved via the [Product Request](https://env.7xmtools.com/api-docs/product.html) with the optional `offers` parameter (how many offers to retrieve, see the endpoint page for parameter details and token cost). Add the `stock` parameter to also receive `stockCSV` data. ``` GET https://api.keepa.com/product?key=&domain=&asin=&offers= ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getProductRequest(AmazonLocale.US, null, 20, "B0F3GWXLTS"); api.sendRequest(r) .done(result -> { Product product = result.products[0]; for (Offer offer : product.offers) { System.out.println(offer.sellerId + " " + offer.condition); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getProductRequest(AmazonLocale::US, 20, null, null, 1, true, ['B0F3GWXLTS'])); if ($response->status == ResponseStatus::OK) { $product = $response->products[0]; print_r($product->offers); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "asin": "B0F3GWXLTS", "offers": 20} r = requests.get("https://api.keepa.com/product", params=params) data = r.json() for offer in data["products"][0]["offers"]: price = offer["offerCSV"][-2] shipping = offer["offerCSV"][-1] print(offer["sellerId"], offer["condition"], price, shipping, offer["lastSeen"]) ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&offers=20"); const data = await res.json(); for (const offer of data.products[0].offers) { const price = offer.offerCSV[offer.offerCSV.length - 2]; const shipping = offer.offerCSV[offer.offerCSV.length - 1]; console.log(offer.sellerId, offer.condition, price, shipping, offer.lastSeen); } ``` **cURL** ```bash curl -s "https://api.keepa.com/product?key=YOUR_API_KEY&domain=1&asin=B0F3GWXLTS&offers=20" ``` ### Example response The offer objects are contained in the `offers` array of each [product object](https://env.7xmtools.com/api-docs/product-object.html). The first offer below is a Warehouse Deal in “Used - Very Good” condition with a detected duplicate; the second is a new-condition FBA offer with a 15% coupon and a Prime exclusive price. ```json { "timestamp": 1753747260000, "tokensLeft": 280, "refillIn": 42000, "refillRate": 5, "tokensConsumed": 6, "processingTimeInMs": 312, "products": [ { "asin": "B0F3GWXLTS", "domainId": 1, "title": "Example Bluetooth Speaker (Black)", "liveOffersOrder": [1, 0], "offers": [ { "offerId": 4, "lastSeen": 7665120, "sellerId": "A2L77EE7U53NWQ", "isPrime": true, "isFBA": true, "isMAP": false, "isShippable": true, "isPreorder": false, "isWarehouseDeal": true, "isAmazon": false, "isPrimeExcl": false, "condition": 3, "conditionComment": "The item may come repackaged. Small cosmetic imperfection on top.", "lastStockUpdate": 7665120, "offerCSV": [7621040, 2299, 0, 7648900, 2149, 0, 7665120, 2079, 0], "offerDuplicates": [ { "price": 2199, "shipping": 0, "conditionComment": "Open Box, works great!" } ] }, { "offerId": 11, "lastSeen": 7665080, "sellerId": "A1B2C3D4E5F6G7", "isPrime": true, "isFBA": true, "isMAP": false, "isShippable": true, "isPreorder": false, "isWarehouseDeal": false, "isAmazon": false, "isPrimeExcl": true, "coupon": -15, "couponHistory": [7648900, 500, 7665080, -15], "condition": 1, "minOrderQty": 2, "lastStockUpdate": 7665080, "offerCSV": [7590200, 2999, 449, 7648900, 2899, 0, 7665080, 2849, 0], "primeExclCSV": [7648900, 2699, 7665080, 2649] } ] } ] } ``` *Response shortened for readability; illustrative values.* Prices are integers in the locale’s smallest currency unit (here: US cents, e.g. `2079` = $20.79); timestamps are Keepa Time minutes (e.g. `7665120` → Unix ms `(7665120 + 21564000) * 60000 = 1753747200000`). # Category Object Source: https://env.7xmtools.com/api-docs/category-object.html An Amazon Category Object provides information about a category — its name, subcategories and parent category for navigating the category tree — plus aggregated statistics about the products listed in it. JSON Object · Returned by: Category Lookup & Category Search An Amazon **Category Object** provides information about a category, including its name and details about subcategories and parent categories, enabling navigation through the category tree. > **Tip:** Category objects change infrequently and can be cached for extended periods. The Category object is returned by the following requests: - [Category Searches](https://env.7xmtools.com/api-docs/category-search.html) - [Category Lookups](https://env.7xmtools.com/api-docs/category-lookup.html) ## Format ```json { "domainId": Integer, "catId": Long, "name": String, "websiteDisplayGroup": String, "children": Long[], "parent": Long, "isBrowseNode": Boolean, "highestRank": Integer, "lowestRank": Integer, "productCount": Integer, "avgBuyBox": Integer, "avgBuyBox90": Integer, "avgBuyBox365": Integer, "avgBuyBoxDeviation": Integer, "avgReviewCount": Integer, "avgRating": Integer, "isFBAPercent": Float, "soldByAmazonPercent": Float, "hasCouponPercent": Float, "avgOfferCountNew": Float, "avgOfferCountUsed": Float, "sellerCount": Integer, "brandCount": Integer, "avgDeltaPercent30BuyBox": Float, "avgDeltaPercent90BuyBox": Float, "avgDeltaPercent30Amazon": Float, "avgDeltaPercent90Amazon": Float, "relatedCategories": Long[], "topBrands": String[] } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `domainId` | Integer | The Amazon locale this category belongs to. See the [Domain IDs](https://env.7xmtools.com/api-docs/category-object.html#domain-ids) table below for all possible values. | | `catId` | Long | The category node ID used by Amazon, representing the identifier of the category. It is also part of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)'s `categories` and `rootCategory` fields. Always a positive Long value.
**Note:** The ID `9223372036854775807` (maximum signed long value) denotes a blank category with the name `"?"`. This is used in cases where a product is listed in no or non-existent categories.
*Example:* `281052` — [https://www.amazon.com/b/?node=281052](https://www.amazon.com/b/?node=281052) | | `name` | String | The name of the category.
*Example:* `"Digital Cameras"` | | `websiteDisplayGroup` | String | The `websiteDisplayGroup`, available for most root categories.
*Example:* `"fashion_display_on_website"` | | `children` | Long\[\] | List of all subcategories. `null` or `[]` (empty array) if the category has no subcategories.
*Example:* `[3109924011, 7242008011, 3017941, 2476680011, 330405011, 2476681011, 3109925011]` | | `parent` | Long | The parent category's ID. Always a positive Long value. If it is `0`, the category is a root category and has no parent category.
*Example:* `502394` | | `isBrowseNode` | Boolean | Determines if this category functions as a standard browse node rather than serving promotional purposes. Every child within a category, along with their respective children, shares the same value.
*Examples:* `true` (e.g. for `"Home & Kitchen"`), `false` (e.g. for `"Prime Day 10% Off"` or `"Specialty Stores"`).
For more examples, check the [Category Tree](https://env.7xmtools.com/categorytree) and enable the *Show meta categories* option. | | `highestRank` | Integer | The highest (root category) sales rank observed for a product listed in this category. Note: this is an estimate from the Keepa product database and not retrieved directly from Amazon.
*Example:* `2452122` | | `lowestRank` | Integer | The lowest (root category) sales rank observed for a product listed in this category. Note: this is an estimate from the Keepa product database and not retrieved directly from Amazon.
*Example:* `1` | | `productCount` | Integer | The estimated number of products listed in this category. Note: this value is from the Keepa product database and not retrieved directly from Amazon.
*Example:* `2452122` | | `avgBuyBox` | Integer | The average current buy box price of products listed in this category.
*Example:* `1999` (price in the smallest currency unit, e.g. cents) | | `avgBuyBox90`, `avgBuyBox365` | Integer | The average 90- and 365-day buy box price of products listed in this category.
*Example:* `2099` (price in the smallest currency unit, e.g. cents) | | `avgBuyBoxDeviation` | Integer | The average 30-day buy box deviation of products listed in this category, showing how much prices fluctuate.
*Example:* `450` (price in the smallest currency unit, e.g. cents) | | `avgReviewCount` | Integer | The average number of reviews of products listed in this category.
*Example:* `235` | | `avgRating` | Integer | The average rating (on a scale from 10 to 50) of products listed in this category.
*Example:* `45` (4.5 stars) | | `isFBAPercent` | Float | Represents the distribution of products fulfilled by Amazon (FBA) as a percentage.
*Example:* `65.5` (indicating 65.5% of products are fulfilled by Amazon) | | `soldByAmazonPercent` | Float | Represents the distribution of products sold by Amazon versus third-party sellers as a percentage.
*Example:* `45.3` (indicating 45.3% of products are sold by Amazon) | | `hasCouponPercent` | Float | The percentage of products in the category that have an active coupon.
*Example:* `10.2` (indicating 10.2% of products have a one time coupon) | | `avgOfferCountNew` | Float | The average number of *new* offers per product in this category, excluding out-of-stock listings.
*Example:* `3.5` — on average, each product has 3.5 active new offers. | | `avgOfferCountUsed` | Float | The average number of *used* offers per product in this category, excluding out-of-stock listings.
*Example:* `1.2` — on average, each product has 1.2 active used offers. | | `sellerCount` | Integer | The total number of distinct sellers with at least one active offer in this category.
*Example:* `452` — 452 unique sellers have active listings in this category. | | `brandCount` | Integer | The total number of distinct brands represented among products in this category.
*Example:* `120` — 120 different brands are present. | | `avgDeltaPercent30BuyBox`, `avgDeltaPercent90BuyBox` | Float | The average *percentage change* in Buy Box price per product over the last 30 and 90 days. A **positive** value means that, on average, products have become **cheaper**; a **negative** value means products have become **more expensive**. Each product contributes equally regardless of price.
*Example:* `2.1` — Buy Box prices have decreased by an average of 2.1%. | | `avgDeltaPercent30Amazon`, `avgDeltaPercent90Amazon` | Float | The average *percentage change* in Amazon's own offer prices (where available) per product over the last 30 and 90 days.
*Example:* `0.8` — Amazon dropped its offer price by an average of 0.8% in this timeframe. | | `relatedCategories` | Long\[\] | A list of category IDs representing other categories where products from this category are commonly co-listed. Sorted by frequency of co-listing (most common first). This field allows recommendation systems and cross-category navigation by identifying semantically or behaviorally adjacent categories.
*Example:* `[672123011, 281407, 11057241]` | | `topBrands` | String\[\] | Up to the **top 3 most frequent brands** represented in this category, in descending order of occurrence. If fewer than 3 distinct brands exist, the array will contain fewer elements.
*Example:* `["Sony", "Canon", "Panasonic"]` | ### Domain IDs Possible values for the `domainId` field: | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Example Category Objects are obtained through a [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html) (by category ID) or a [Category Search](https://env.7xmtools.com/api-docs/category-search.html) (by search term). The following request fetches the category `281052` ("Digital Cameras") on amazon.com: ``` GET https://api.keepa.com/category?key=&domain=&category= ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); Request r = Request.getCategoryLookupRequest(AmazonLocale.US, false, 281052); api.sendRequest(r) .done(result -> { System.out.println(result.categories.get(281052L).name); }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php sendRequestWithRetry(Request::getCategoryLookupRequest(AmazonLocale::US, false, "281052")); if ($response->status == ResponseStatus::OK) { print_r($response->categories); } ``` **Python** ```python import requests params = {"key": "YOUR_API_KEY", "domain": 1, "category": 281052} r = requests.get("https://api.keepa.com/category", params=params) data = r.json() category = data["categories"]["281052"] print(category["name"], "-", category["productCount"], "products") ``` **Node.js** ```javascript const res = await fetch("https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052"); const data = await res.json(); const category = data.categories["281052"]; console.log(`${category.name} - ${category.productCount} products`); ``` **cURL** ```bash curl -s "https://api.keepa.com/category?key=YOUR_API_KEY&domain=1&category=281052" ``` ### Example Category Object ```json { "domainId": 1, "catId": 281052, "name": "Digital Cameras", "websiteDisplayGroup": "ce_display_on_website", "children": [3109924011, 7242008011, 3017941, 2476680011, 330405011, 2476681011, 3109925011], "parent": 502394, "isBrowseNode": true, "highestRank": 2452122, "lowestRank": 1, "productCount": 148733, "avgBuyBox": 25499, "avgBuyBox90": 26120, "avgBuyBox365": 26890, "avgBuyBoxDeviation": 1450, "avgReviewCount": 235, "avgRating": 42, "isFBAPercent": 65.5, "soldByAmazonPercent": 21.4, "hasCouponPercent": 10.2, "avgOfferCountNew": 3.5, "avgOfferCountUsed": 1.2, "sellerCount": 4520, "brandCount": 120, "avgDeltaPercent30BuyBox": 2.1, "avgDeltaPercent90BuyBox": 3.4, "avgDeltaPercent30Amazon": 0.8, "avgDeltaPercent90Amazon": 1.5, "relatedCategories": [672123011, 281407, 11057241], "topBrands": ["Sony", "Canon", "Panasonic"] } ``` Illustrative values. Prices are integers in the smallest currency unit (e.g. cents: `25499` = $254.99); `avgRating` `42` corresponds to 4.2 stars. In the actual lookup response, Category Objects are contained in the `categories` result field — see [Category Lookup](https://env.7xmtools.com/api-docs/category-lookup.html). # Deal Object Source: https://env.7xmtools.com/api-docs/deal-object.html A Deal object represents a product that has recently undergone changes, typically in price or sales rank. It contains a summary of the product and information about the changes. JSON Object · Returned by: Browsing Deals The Deal object is returned by the [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) request (in the `dr` array of its `deals` response object). Each entry combines basic product information with the current, previous and average prices/ranks across several date ranges, so you can see at a glance what changed and by how much. ## Format ```json { // product information "asin": String, "parentAsin": String, "title": String, "rootCat": Long, "categories": Long array, "image": Integer array, // price/rank information "current": Integer array, "currentSince": Integer array, "deltaLast": Integer array, "delta": two dimensional Integer array, "deltaPercent": two dimensional Integer array, "avg": two dimensional Integer array, // deal information "lastUpdate": Integer, "creationDate": Integer, "lightningEnd": Integer, "warehouseCondition": Integer, "warehouseConditionComment": String } ``` ## Fields ### Product information | Field | Type | Description | | --- | --- | --- | | `asin` | String | The ASIN of the product.
Example: `B00M0QVG3W` | | `parentAsin` | String | The parent ASIN of the product.
Example: `B01D0MKH5V` | | `title` | String | Title of the product. **Caution:** may contain unescaped HTML markup in rare cases.
Example: `Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)` | | `rootCat` | Long | Category node id of the product’s root category. `0` or `9223372036854775807` if no root category is known.
Example: `562066` | | `categories` | Long array | Array of Amazon category node ids this product is listed in. Can be empty.
Example: `[569604]` | | `image` | Integer array | The name of the main product image of the product. Make sure you own the rights to use the image.
Each entry represents the integer of a US-ASCII (ISO646-US) coded character. The easiest way to convert it to a String in JavaScript is:
`var imageName = String.fromCharCode.apply("", dealObject.image);`
Example: `[54,49,107,51,76,97,121,55,74,85,76,46,106,112,103]`, which equals `"61k3Lay7JUL.jpg"`.
Full Amazon image path: `https://images-na.ssl-images-amazon.com/images/I/` | ### Price and rank information > **Note:** The following indexes apply to all price/rank information fields: > > - **Price Type** — see the *csv* field of the [product object](https://env.7xmtools.com/api-docs/product-object.html). > - **Date Range** (should be declared as an enum/constants): > > | Index | Range | Description | > | --- | --- | --- | > | `0` | day | the last 24 hours | > | `1` | week | the last 24 × 7 hours | > | `2` | month | the last 24 × 31 hours | > | `3` | 90 days | the last 24 × 90 hours | | Field | Type | Description | | --- | --- | --- | | `current` | Integer array | Contains the prices/ranks of the product at the time of the last update. Uses the Price Type indexing.
The price is an integer of the respective Amazon locale’s smallest currency unit (e.g. euro cents or yen). If no offer was available in the given interval (e.g. out of stock), the price has the value `-1`.
Shipping and handling costs are not included. Amazon is considered to be part of the marketplace, so if Amazon has the overall lowest new price, the marketplace new price in the corresponding time interval will be identical to the Amazon price (except if there is only one marketplace offer). | | `currentSince` | Integer array | The timestamp indicating the starting point from which the `current` value has been in effect, in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/deal-object.html#keepa-time-minutes). Uses the Price Type indexing. | | `deltaLast` | Integer array | Contains the difference between the previous and current price/rank. The value `0` means it did not change or could not be calculated. Uses the Price Type indexing. | | `delta` | Integer array (two-dimensional) | Contains the difference between the average value and the current value of the respective date range interval. The value `0` means it did not change or could not be calculated. The first dimension uses the Date Range indexing, the second the Price Type indexing. | | `deltaPercent` | Integer array (two-dimensional) | Same as `delta`, but in percent. | | `avg` | Integer array (two-dimensional) | Contains the weighted averages in the respective date range and price type. The first dimension uses the Date Range indexing, the second the Price Type indexing.
**Note:** The day interval (index `0`) is actually the average of the last **48 hours**, not 24 hours. This is due to the way Keepa’s deals work. | ### Deal information | Field | Type | Description | | --- | --- | --- | | `lastUpdate` | Integer | States the last time Keepa has updated the information for this deal, in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/deal-object.html#keepa-time-minutes). | | `creationDate` | Integer | Contains the timestamp of the last price / value change for the requested *priceTypes*, in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/deal-object.html#keepa-time-minutes). The value `-1` means the value was never collected. | | `lightningEnd` | Integer | States the time this lightning deal is scheduled to end, in [**Keepa Time minutes**](https://env.7xmtools.com/api-docs/deal-object.html#keepa-time-minutes). Only applicable to lightning deals; `0` otherwise. | | `warehouseCondition` | Integer | The offer condition of the cheapest warehouse deal of this product. Possible values:
`0` — no warehouse deal found in our data or condition unknown
`2` — “Used - Like New”
`3` — “Used - Very Good”
`4` — “Used - Good”
`5` — “Used - Acceptable” | | `warehouseConditionComment` | String | The offer comment of the cheapest warehouse deal of this product. `null` if no warehouse deal was found in our data. | ## Lightning, Prime Exclusive and Warehouse Deals > **Note:** The `deltaLast`, `delta` and `deltaPercent` entries for those two price types are calculated with the **Amazon or New price as the reference price** (instead of the same price type’s previous price). ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ```javascript const unixMs = (keepaTime + 21564000) * 60000; const unixSeconds = (keepaTime + 21564000) * 60; const date = new Date(unixMs); ``` ## Example Deal objects are retrieved via the [Browsing Deals](https://env.7xmtools.com/api-docs/deals.html) request. The query JSON can be sent as the POST payload or, URL-encoded, in the `selection` GET parameter — see the [endpoint page](https://env.7xmtools.com/api-docs/deals.html) for all query options and the token cost. ``` POST https://api.keepa.com/deal?key= ``` **Java** ```java KeepaAPI api = new KeepaAPI("YOUR_API_KEY"); DealRequest dealQuery = new DealRequest(); dealQuery.page = 0; dealQuery.domainId = 1; // amazon.com dealQuery.priceTypes = new int[]{0}; // AMAZON price type dealQuery.dateRange = 1; // interval: last week dealQuery.isRangeEnabled = true; dealQuery.currentRange = new int[]{500, 40000}; dealQuery.deltaPercentRange = new int[]{20, 100}; dealQuery.sortType = 4; api.sendRequest(Request.getDealsRequest(dealQuery)) .done(result -> { for (Deal deal : result.deals.dr) { System.out.println(deal.asin + " " + deal.title); } }) .fail(failure -> System.out.println(failure)); ``` **PHP** ```php page = 0; $dealQuery->domainId = 1; // amazon.com $dealQuery->priceTypes = [0]; // AMAZON price type $dealQuery->dateRange = 1; // interval: last week $dealQuery->isRangeEnabled = true; $dealQuery->currentRange = [500, 40000]; $dealQuery->deltaPercentRange = [20, 100]; $dealQuery->sortType = 4; $response = $api->sendRequestWithRetry(Request::getDealsRequest($dealQuery)); if ($response->status == ResponseStatus::OK) { foreach ($response->deals->dr as $deal) { echo $deal->asin . " " . $deal->title . PHP_EOL; } } ``` **Python** ```python import requests query = {"page": 0, "domainId": 1, "priceTypes": [0], "dateRange": 1} r = requests.post("https://api.keepa.com/deal", params={"key": "YOUR_API_KEY"}, json=query) data = r.json() for deal in data["deals"]["dr"]: image_name = "".join(chr(c) for c in deal["image"]) print(deal["asin"], deal["title"], deal["current"][0], image_name) ``` **Node.js** ```javascript const query = { page: 0, domainId: 1, priceTypes: [0], dateRange: 1 }; const res = await fetch("https://api.keepa.com/deal?key=YOUR_API_KEY", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(query) }); const data = await res.json(); for (const deal of data.deals.dr) { const imageName = String.fromCharCode.apply("", deal.image); console.log(deal.asin, deal.title, deal.current[0], imageName); } ``` **cURL** ```bash curl -s -X POST "https://api.keepa.com/deal?key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"page":0,"domainId":1,"priceTypes":[0],"dateRange":1}' ``` ### Example Deal object ```json { "asin": "B00M0QVG3W", "parentAsin": "B01D0MKH5V", "title": "Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)", "rootCat": 562066, "categories": [569604], "image": [54, 49, 107, 51, 76, 97, 121, 55, 74, 85, 76, 46, 106, 112, 103], "current": [12999, 12999, 9850, 1859], "currentSince": [7661010, 7661010, 7658200, 7661900], "deltaLast": [-3000, -3000, 0, 245], "delta": [ [3000, 3000, 0, -217], [1800, 1651, -51, -139], [1600, 1524, -130, -44], [1313, 1201, -200, -69] ], "deltaPercent": [ [19, 19, 0, -13], [12, 11, -1, -8], [11, 10, -1, -2], [9, 8, -2, -4] ], "avg": [ [15999, 15999, 9850, 1642], [14799, 14650, 9799, 1720], [14599, 14523, 9720, 1815], [14312, 14200, 9650, 1790] ], "lastUpdate": 7661998, "creationDate": 7661010, "lightningEnd": 0, "warehouseCondition": 3, "warehouseConditionComment": "Item will come repackaged. Small cosmetic scratch on the bottom of the casing." } ``` *Example shortened for readability; illustrative values.* The one-dimensional arrays (`current`, `currentSince`, `deltaLast`) are indexed by price type; only the first four entries are shown here (see the *csv* field of the [product object](https://env.7xmtools.com/api-docs/product-object.html) for the full price type indexing — in a real response the arrays cover all price types). The two-dimensional arrays contain one row per date range (day, week, month, 90 days). Prices are integers in the locale’s smallest currency unit (here: US cents, e.g. `12999` = $129.99); timestamps are Keepa Time minutes (e.g. `7661010` → Unix ms `(7661010 + 21564000) * 60000 = 1753500600000`). The `image` array decodes to `61k3Lay7JUL.jpg`, and `warehouseCondition` `3` means “Used - Very Good”. # Best Sellers Object Source: https://env.7xmtools.com/api-docs/best-sellers-object.html A list of best-selling ASINs for a specific category, ordered from the best-selling product (lowest sales rank) downwards. JSON Object · Returned by: Best Sellers The Best Sellers Object is returned by the [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) request. It contains the Amazon locale, the requested category and a ranked list of ASINs. ## Format ```json { "domainId": Integer, "lastUpdate": Integer, "categoryId": Long, "asinList": String[] } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `domainId` | Integer | The Amazon locale this list belongs to. See the [valid domain IDs](https://env.7xmtools.com/api-docs/best-sellers-object.html#domain-ids) below. | | `lastUpdate` | Integer | The last time the list was updated, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/best-sellers-object.html#keepa-time-minutes). Example: `2711319` | | `categoryId` | Long | The category node ID used in the request, representing the category identifier. Example: `281052` ([Amazon category link](http://www.amazon.com/b/?node=281052)) | | `asinList` | String\[\] | A list of ASINs, starting with the best-selling product (lowest sales rank). | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ```python # Convert Keepa Time minutes to a Python datetime from datetime import datetime, timezone def keepa_minutes_to_datetime(keepa_time): return datetime.fromtimestamp((keepa_time + 21564000) * 60, tz=timezone.utc) print(keepa_minutes_to_datetime(7663000)) # illustrative value (mid 2026) ``` ## Example A Best Sellers Object as returned inside the `bestSellersList` field of a [Best Sellers](https://env.7xmtools.com/api-docs/best-sellers.html) response: ```json { "domainId": 1, "lastUpdate": 7662840, "categoryId": 281052, "asinList": [ "B0BDHWDR12", "B09XS7JWHH", "B08N5WRWNW", "B07YN82X3B", "B01M0AGIKS" ] } ``` *Response shortened for readability; illustrative values.* A real list can contain far more ASINs. # Seller Object Source: https://env.7xmtools.com/api-docs/seller-object.html Information about an Amazon marketplace seller, including their name, rating history and rating count history. JSON Object · Returned by: Seller Information The Seller Object provides information about an Amazon marketplace seller, including their name, rating history, and rating count history. It is returned by the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request. > **Note:** The API does not provide information for sellers who only sell in the handmade category. ## Format ```json { "domainId": Integer, "trackingSince": Integer, "lastUpdate": Integer, "sellerId": String, "sellerName": String, "businessName": String, "address": String array, "tradeNumber": String, "vatID": String, "phoneNumber": String, "businessType": String, "shareCapital": String, "representative": String, "email": String, "customerServicesAddress": String array, "lastRatingUpdate": Integer, "ratingCount": Integer array, "positiveRating": Integer array, "negativeRating": Integer array, "neutralRating": Integer array, "recentFeedback": Feedback Object array, "hasFBA": Boolean, "totalStorefrontAsins": Integer array, "csv": Two-dimensional Integer array, "asinList": String array, "asinListLastSeen": Integer array, "sellerCategoryStatistics": Object array, "sellerBrandStatistics": Object array, "competitors": Object array, "avgBuyBoxCompetitors": Float, "buyBoxNewOwnershipRate": Integer, "buyBoxUsedOwnershipRate": Integer } ``` ## Fields ### Identification & basic data | Field | Type | Description | | --- | --- | --- | | `domainId` | Integer | The Amazon locale this seller belongs to. See the [valid domain IDs](https://env.7xmtools.com/api-docs/seller-object.html#domain-ids) below. | | `trackingSince` | Integer | The time when Keepa started tracking this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-object.html#keepa-time-minutes). Example: `2700145` | | `lastUpdate` | Integer | The time of the last basic data update of this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-object.html#keepa-time-minutes). This does not include ratings or storefront data. Example: `2711319` | | `sellerId` | String | The seller ID of the merchant. Example: `A2L77EE7U53NWQ` (Amazon.com Warehouse Deals) | | `sellerName` | String | The name of the seller. Example: `Amazon Warehouse Deals` | ### Business information Except for `businessName`, the following fields only appear in the response if there is a value. | Field | Type | Description | | --- | --- | --- | | `businessName` | String | The name of the business. Example: `Keepa GmbH` | | `address` | String\[\] | The business address. Each entry of the array contains one address line. The last entry contains the 2-letter country code. Example: `["123 Main Street", "New York, NY", "10001", "US"]` | | `tradeNumber` | String | The Trade Register Number. Example: `HRB 123 456` | | `vatID` | String | The VAT number. Example: `DE123456789` | | `phoneNumber` | String | The phone number. Example: `800 1234 567` | | `businessType` | String | The business type. Example: `Unternehmen in Privatbesitz` | | `shareCapital` | String | The share capital. Example: `25000` | | `representative` | String | The name of the business representative. Example: `Max Mustermann` | | `email` | String | The email address of the business. Example: `info@keepa.com` | | `customerServicesAddress` | String\[\] | The customer services address. Each entry of the array contains one address line. The last entry contains the 2-letter country code. Example: `["123 Main Street", "New York, NY", "10001", "US"]` | ### Ratings & feedback | Field | Type | Description | | --- | --- | --- | | `lastRatingUpdate` | Integer | The time of the last rating data update of this seller, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-object.html#keepa-time-minutes). Example: `2711319` | | `ratingCount` | Integer\[\] | Contains the rating counts for the last 30 days, 90 days, 365 days, and lifetime, in that order. Example: `[3, 10, 98, 321]` | | `positiveRating` | Integer\[\] | Contains the positive percentage ratings for the last 30 days, 90 days, 365 days, and lifetime, in that order. A positive rating is a 4 or 5-star rating. Example: `[96, 98, 98, 95]` | | `negativeRating` | Integer\[\] | Contains the negative percentage ratings for the last 30 days, 90 days, 365 days, and lifetime, in that order. A negative rating is a 1 or 2-star rating. Example: `[3, 1, 1, 3]` | | `neutralRating` | Integer\[\] | Contains the neutral percentage ratings for the last 30 days, 90 days, 365 days, and lifetime, in that order. A neutral rating is a 3-star rating. Example: `[1, 1, 1, 2]` | | `recentFeedback` | Feedback\[\] | Contains up to 5 of the most recent customer feedbacks. Only appears in the response if there is a value. Each feedback object contains:
• `date` Integer — timestamp of the feedback, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-object.html#keepa-time-minutes)
• `rating` Integer — the feedback star rating, value ranges from 10 (1 star) to 50 (5 stars)
• `isStriked` Boolean — indicates whether the feedback is striked | | `csv` | Integer\[\]\[\] | A two-dimensional history array containing historical data for this seller. First dimension index:
• **0** — `RATING`: the merchant's rating in percent, integer from 0 to 100
• **1** — `RATING_COUNT`: the merchant's total rating count, integer
The second dimension contains the history in the format `[Keepa Time minutes, value, ...]`. It is `null` if no data is available. Newly created merchant accounts may not yet have any ratings. | > **Tip:** To get the newest value, access the last entry of the array (after checking it is not `null`): most recent rating: `csv[0][csv[0].length - 1]`, most recent rating count: `csv[1][csv[1].length - 1]`. ### Storefront & statistics | Field | Type | Description | | --- | --- | --- | | `hasFBA` | Boolean | Indicates whether the seller currently has FBA (Fulfillment by Amazon) listings. This value is usually correct, but could be set to `false` even if the seller has FBA listings, since Keepa is not always aware of all seller listings. This can especially be the case with sellers with only a few listings consisting of slow-selling products. Example: `true` | | `totalStorefrontAsins` | Integer\[\] | Contains the number of storefront ASINs, based on Keepa's internal database aggregation (as of February 2026), if available, and the last update of that metric. `null` if not available (no storefront was ever retrieved). This field is available in the default [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request (the `storefront` parameter is not required). Format: `[last update in Keepa Time minutes, count of storefront ASINs]`. Example: `[2711319, 1200]` | | `asinList` | String\[\] | An array containing up to 100,000 storefront ASINs, sorted by freshest first. The corresponding timestamps can be found in the `asinListLastSeen` field. Only available if the `storefront` parameter was used — see the [Seller Information](https://env.7xmtools.com/api-docs/seller.html) request. Example: `["B00M0QVG3W", "B00M4KCH2A"]` | | `asinListLastSeen` | Integer\[\] | Contains the last time (in [Keepa Time minutes](https://env.7xmtools.com/api-docs/seller-object.html#keepa-time-minutes)) Keepa was able to verify each ASIN in the `asinList` field. `asinList` and `asinListLastSeen` share the same indexation, so the corresponding timestamp for `asinList[10]` would be `asinListLastSeen[10]`. Example: `[2711319, 2711311]` | | `sellerCategoryStatistics` | Object\[\] | Statistics about the primary categories of this seller. Based on Keepa's often incomplete and outdated product offers data. Each object contains:
• `catId` Long — the category ID
• `productCount` Integer — the number of products this merchant sells in this category
• `avg30SalesRank` Integer — the 30-day average sales rank of these products
• `productCountWithAmazonOffer` Integer — how many of these products have an Amazon offer | | `sellerBrandStatistics` | Object\[\] | Statistics about the primary brands of this seller. Based on Keepa's often incomplete and outdated product offers data. Each object contains:
• `brand` String — the brand (in all lowercase)
• `productCount` Integer — the number of products this merchant sells with this brand
• `avg30SalesRank` Integer — the 30-day average sales rank of these products
• `productCountWithAmazonOffer` Integer — how many of these products have an Amazon offer | ### Competition & Buy Box | Field | Type | Description | | --- | --- | --- | | `competitors` | Object\[\] | The top five sellers most commonly offering the same products as this seller. Each object contains:
• `sellerId` String — the sellerId of the competitor
• `percent` Integer — the percentage of listings this competitor shares with the seller | | `avgBuyBoxCompetitors` | Float | Average number of sellers competing for the Buy Box of this seller's products (this seller included). | | `buyBoxNewOwnershipRate` | Integer | Average New Buy Box ownership percentage. | | `buyBoxUsedOwnershipRate` | Integer | Average Used Buy Box ownership percentage. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Example A Seller Object as returned inside the `sellers` map of a [Seller Information](https://env.7xmtools.com/api-docs/seller.html) response: ```json { "domainId": 1, "trackingSince": 2700145, "lastUpdate": 7662810, "sellerId": "A2L77EE7U53NWQ", "sellerName": "Amazon Warehouse Deals", "businessName": "Example Trading GmbH", "address": ["123 Main Street", "New York, NY", "10001", "US"], "vatID": "DE123456789", "lastRatingUpdate": 7662780, "ratingCount": [3, 10, 98, 321], "positiveRating": [96, 98, 98, 95], "negativeRating": [3, 1, 1, 3], "neutralRating": [1, 1, 1, 2], "recentFeedback": [ { "date": 7662500, "rating": 50, "isStriked": false }, { "date": 7661900, "rating": 10, "isStriked": true } ], "hasFBA": true, "totalStorefrontAsins": [7662810, 1200], "csv": [ [2711319, 95, 7000000, 96, 7662780, 96], [2711319, 280, 7000000, 305, 7662780, 321] ], "sellerCategoryStatistics": [ { "catId": 281052, "productCount": 214, "avg30SalesRank": 15230, "productCountWithAmazonOffer": 87 } ], "sellerBrandStatistics": [ { "brand": "sony", "productCount": 45, "avg30SalesRank": 9800, "productCountWithAmazonOffer": 21 } ], "competitors": [ { "sellerId": "A3EXAMPLE0SELLER", "percent": 34 } ], "avgBuyBoxCompetitors": 4.2, "buyBoxNewOwnershipRate": 62, "buyBoxUsedOwnershipRate": 18 } ``` *Response shortened for readability; illustrative values.* The `asinList` and `asinListLastSeen` fields (storefront requests only) are omitted here. # Lightning Deal Object Source: https://env.7xmtools.com/api-docs/lightning-deal-object.html Information about an Amazon Lightning Deal: deal price, state, claim progress, timing and variation attributes. JSON Object · Returned by: Lightning Deals The Lightning Deal Object provides information about an Amazon Lightning Deal. It is returned by the [Lightning Deals](https://env.7xmtools.com/api-docs/lightning-deals.html) request. ## Format ```json { "domainId": Integer, "lastUpdate": Integer, "asin": String, "title": String, "sellerId": String, "sellerName": String, "dealId": String, "dealPrice": Integer, "currentPrice": Integer, "image": String, "isPrimeEligible": Boolean, "isFulfilledByAmazon": Boolean, "rating": Integer, "totalReviews": Integer, "dealState": String, "startTime": Integer, "endTime": Integer, "percentClaimed": Integer, "percentOff": Integer, "variation": Object[] } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `domainId` | Integer | The Amazon locale of this deal. See the [valid domain IDs](https://env.7xmtools.com/api-docs/lightning-deal-object.html#domain-ids) below. | | `lastUpdate` | Integer | The time of the last data collection for this Lightning Deal, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/lightning-deal-object.html#keepa-time-minutes). Example: `2711319` | | `asin` | String | The ASIN of the product. Example: `"B00M0QVG3W"` | | `title` | String | The title of the product. **Caution:** may contain unescaped HTML markup in rare cases. Example: `"Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)"` | | `sellerId` | String | The seller ID of the merchant offering this deal. Example: `"A2L77EE7U53NWQ"` (Amazon.com Warehouse Deals) | | `sellerName` | String | The name of the seller offering this deal. Example: `"Amazon Warehouse Deals"` | | `dealId` | String | A unique ID for this Lightning Deal. If the deal is for a product with variations, the ID will be shared among all child ASINs that are part of the deal. Example: `"76fbc441"` | | `dealPrice` | Integer | The discounted price of this deal, available once the deal has started. **-1** if the deal's state is upcoming. The price is in the smallest currency unit of the respective Amazon locale (e.g., euro cents or yen). Example: `999` | | `currentPrice` | Integer | The current buy box price of the product. The price is in the smallest currency unit of the respective Amazon locale. Example: `1299` | | `image` | String | The filename of the product's primary image. `null` if not available. Example: `"51InzcaVqrL.jpg"`. Full Amazon image URL: `https://images-na.ssl-images-amazon.com/images/I/` | | `isPrimeEligible` | Boolean | Indicates whether the deal is Prime eligible. | | `isFulfilledByAmazon` | Boolean | Indicates whether the deal is fulfilled by Amazon. | | `rating` | Integer | The product's rating. An integer from 0 to 50 (e.g., `45` represents 4.5 stars). | | `totalReviews` | Integer | The total number of reviews for the product. | | `dealState` | String | The state of the deal. Possible values: `AVAILABLE`, `WAITLIST`, `SOLDOUT`, `WAITLISTFULL`, `EXPIRED`, `SUPPRESSED` | | `startTime` | Integer | The start time of the Lightning Deal, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/lightning-deal-object.html#keepa-time-minutes). Note that due to data collection delays, the deal price might not be available immediately when the deal starts on Amazon. Example: `2711319` | | `endTime` | Integer | The end time of the Lightning Deal, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/lightning-deal-object.html#keepa-time-minutes). Example: `2711389` | | `percentClaimed` | Integer | The percentage of the deal that has been claimed. Since Lightning Deals have limited stock, this number may change quickly on Amazon; due to data collection delays, the provided value may be outdated. Example: `23` (meaning 23% claimed) | | `percentOff` | Integer | The discount percentage provided for this deal, as indicated by Amazon. The discount may reference the list price rather than the current price. Example: `50` (meaning 50% discount) | | `variation` | Object\[\] | The dimension attributes associated with this deal. Each object contains a `dimension` (e.g. `"Size"`) and a `value` (e.g. `"Large"`) — see the example below. | Example of the `variation` field: ```json "variation": [ { "dimension": "Size", "value": "Large" }, { "dimension": "Color", "value": "Red" } ] ``` ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Example A Lightning Deal Object as returned by the [Lightning Deals](https://env.7xmtools.com/api-docs/lightning-deals.html) request: ```json { "domainId": 3, "lastUpdate": 7662890, "asin": "B00M0QVG3W", "title": "Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)", "sellerId": "A2L77EE7U53NWQ", "sellerName": "Amazon Warehouse Deals", "dealId": "76fbc441", "dealPrice": 999, "currentPrice": 1299, "image": "51InzcaVqrL.jpg", "isPrimeEligible": true, "isFulfilledByAmazon": true, "rating": 45, "totalReviews": 1287, "dealState": "AVAILABLE", "startTime": 7662840, "endTime": 7663200, "percentClaimed": 23, "percentOff": 50, "variation": [ { "dimension": "Color", "value": "Black" } ] } ``` *Illustrative values.* # Search Insights Object Source: https://env.7xmtools.com/api-docs/search-insights-object.html Aggregated metrics calculated over *all* products that match a Product Finder query — ready-to-use KPIs such as average Buy Box prices, seller and brand distribution, fulfilment mix and review statistics. JSON Object · Returned by: Product Finder (stats=1) The Search Insights Object contains aggregated metrics calculated over *all* products that match a [Product Finder query](https://env.7xmtools.com/api-docs/product-finder.html) when the parameter `&stats=1` is supplied. It turns millions of individual products into immediate, ready-to-use key performance indicators (KPIs) such as average Buy Box prices, seller and brand distribution, fulfilment mix and review statistics. > **Returned by:** the [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html) request, as the field `searchInsights`, when called with `&stats=1`. ## Format ```json { "avgDeltaPercent30BuyBox": Float, "avgDeltaPercent90BuyBox": Float, "avgDeltaPercent30Amazon": Float, "avgDeltaPercent90Amazon": Float, "avgBuyBox": Integer, "avgBuyBox90": Integer, "avgBuyBox365": Integer, "avgBuyBoxDeviation": Integer, "avgReviewCount": Integer, "avgRating": Integer, "isFBAPercent": Float, "soldByAmazonPercent": Float, "hasCouponPercent": Float, "avgOfferCountNew": Float, "avgOfferCountNewFBA": Float, "avgOfferCountNewFBM": Float, "avgOfferCountUsed": Float, "sellerCount": Integer, "brandCount": Integer, "highestRank": Integer, "lowestRank": Integer, "relatedCategories": Long[], "topBrandsWithCounts": { String: Integer, ... }, "topSellersWithCounts": { String: Integer, ... } } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `avgDeltaPercent30BuyBox`
`avgDeltaPercent90BuyBox`
`avgDeltaPercent30Amazon`
`avgDeltaPercent90Amazon` | Float | Average percentage change in the Buy Box or Amazon price over the last 30 and 90 days, computed per product. Each product contributes equally, regardless of price. A positive value means the typical product became cheaper; negative means more expensive. Example: `-0.12` (= -0.12 %) | | `avgBuyBox`
`avgBuyBox90`
`avgBuyBox365` | Integer | Average current, 90-day and 365-day Buy Box price across all selling products. Higher-priced products have more influence on this value. Example: `6711` (= € 67.11) | | `avgBuyBoxDeviation` | Integer | Average deviation of the Buy Box price over the last 30 days for all selling products. Indicates short-term price volatility. In smallest currency unit. | | `avgReviewCount` | Integer | Average number of reviews of all products in this category. | | `avgRating` | Integer | Average rating of all products in this category. Example: `45` → 4.5 stars | | `isFBAPercent` | Float | Share of products whose current Buy Box offer is Fulfilled by Amazon (FBA). Returned as a percentage value from `0.0` to `100.0`. Example: `78.3` (= 78.3 %) | | `soldByAmazonPercent` | Float | Share of products currently *sold* by Amazon. | | `hasCouponPercent` | Float | Share of products that have an active coupon. | | `avgOfferCountNew` | Float | Average number of *new* offers per product (excludes out-of-stock). | | `avgOfferCountNewFBA` | Float | Average number of *new* offers fulfilled by Amazon (FBA) per product, over the same products as `avgOfferCountNew`. A product without FBA offers counts as 0, so `avgOfferCountNewFBA` + `avgOfferCountNewFBM` comes close to `avgOfferCountNew`; the difference is products whose split is not known. | | `avgOfferCountNewFBM` | Float | Average number of *new* offers fulfilled by the merchant (FBM) per product, counted the same way as `avgOfferCountNewFBA`. | | `avgOfferCountUsed` | Float | Average number of *used* offers per product (excludes out-of-stock). | | `sellerCount` | Integer | Total number of **distinct** sellers with at least one live offer in the result set. | | `brandCount` | Integer | Total number of distinct brands represented. | | `highestRank` | Integer | The *worst* (numerically highest) Sales Rank among all matched products. | | `lowestRank` | Integer | The *best* (numerically lowest) Sales Rank among all matched products. | | `relatedCategories` | Long\[\] | Up to five [category node ids](https://env.7xmtools.com/api-docs/category-object.html) of other categories in which the matched products are commonly co-listed, ordered by occurrence descending. Useful for cross-category navigation and recommendations. | | `topBrandsWithCounts` | Map\ | Up to five most common brands and their product counts in the result set, ordered descending. Keys are brand names. | | `topSellersWithCounts` | Map\ | Up to five seller IDs that hold the Buy Box most often within the result set, plus their occurrence counts, ordered descending. Keys are seller IDs. | ## Example A Search Insights Object as returned in the `searchInsights` field of a [Product Finder](https://env.7xmtools.com/api-docs/product-finder.html) response with `&stats=1`: ```json { "avgDeltaPercent30BuyBox": -0.12, "avgDeltaPercent90BuyBox": 1.85, "avgDeltaPercent30Amazon": -0.05, "avgDeltaPercent90Amazon": 0.92, "avgBuyBox": 6711, "avgBuyBox90": 6820, "avgBuyBox365": 7015, "avgBuyBoxDeviation": 312, "avgReviewCount": 1245, "avgRating": 45, "isFBAPercent": 78.3, "soldByAmazonPercent": 21.6, "hasCouponPercent": 9.4, "avgOfferCountNew": 5.2, "avgOfferCountNewFBA": 2.3, "avgOfferCountNewFBM": 2.8, "avgOfferCountUsed": 1.4, "sellerCount": 1830, "brandCount": 412, "highestRank": 1845020, "lowestRank": 3, "relatedCategories": [281052, 502394, 172282], "topBrandsWithCounts": { "sony": 210, "canon": 185, "panasonic": 120, "nikon": 95, "fujifilm": 74 }, "topSellersWithCounts": { "ATVPDKIKX0DER": 4210, "A2L77EE7U53NWQ": 830, "A3EXAMPLE0SELLER": 415, "A1EXAMPLE1SELLER": 260, "A9EXAMPLE2SELLER": 190 } } ``` *Illustrative values.* # Tracking Object Source: https://env.7xmtools.com/api-docs/tracking-object.html Represents a price watch. There can only be one tracking object per ASIN, regardless of the locale; a single tracking object can contain desired prices for all locales. JSON Object · Returned by: Tracking API A Tracking Object represents a price watch. There can only be one tracking object per ASIN, regardless of the locale. A single tracking object can contain desired prices for all locales. The tracking object has two child objects: [`TrackingThresholdValue`](https://env.7xmtools.com/api-docs/tracking-object.html#trackingthresholdvalue) and [`TrackingNotifyIf`](https://env.7xmtools.com/api-docs/tracking-object.html#trackingnotifyif). > **Returned by:** the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html) requests. To *create* a tracking, use the [Tracking Creation Object](https://env.7xmtools.com/api-docs/tracking-creation-object.html) instead. ## Format ```json { "asin": String, "createDate": Integer, "isActive": Boolean, "ttl": Integer, "expireNotify": Boolean, "mainDomainId": Integer, "updateInterval": Integer, "metaData": String, "trackingListName": String, "thresholdValues": TrackingThresholdValue[], "notifyIf": TrackingNotifyIf[], "notificationType": Boolean[], "notificationCSV": Integer[], "individualNotificationInterval": Integer } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `asin` | String | The tracked product ASIN. Example: `"B00M0QVG3W"` | | `createDate` | Integer | Creation date of the tracking, in [Keepa Time minutes](https://env.7xmtools.com/api-docs/tracking-object.html#keepa-time-minutes). | | `isActive` | Boolean | Indicates whether the tracking is active. A tracking is automatically deactivated if the corresponding API account is no longer sufficiently funded. | | `ttl` | Integer | The time-to-live in hours until the tracking expires and is deleted. When retrieving the tracking object, it is relative to the `createDate`. Possible values:
• Any positive integer: time-to-live in hours
• `0`: never expires | | `expireNotify` | Boolean | Triggers a notification if the tracking expires or is removed by the system (e.g., product deprecated). | | `mainDomainId` | Integer | The main Amazon locale of this tracking, determining the currency used for all desired prices. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-object.html#domain-ids) below. | | `updateInterval` | Integer | The update interval in hours, determining how often the system will trigger a product update. A setting of 1 hour won't trigger an update exactly every 60 minutes but as close to that as efficiently possible. Throughout a day, it will be updated 24 times, but updates are not perfectly distributed. Possible values: any integer **between** 0 and 25. | | `metaData` | String | The metadata of this tracking (maximum length is 500 characters). Used to assign text to this tracking, like a user reference or memo. | | `trackingListName` | String | The name of the tracking list to which this tracking object belongs (maximum length is 64 characters). | | `thresholdValues` | TrackingThresholdValue\[\] | Contains settings for price or value-related tracking criteria for all locales. See [TrackingThresholdValue](https://env.7xmtools.com/api-docs/tracking-object.html#trackingthresholdvalue) below. | | `notifyIf` | TrackingNotifyIf\[\] | Contains specific meta tracking criteria like out-of-stock status for all locales. See [TrackingNotifyIf](https://env.7xmtools.com/api-docs/tracking-object.html#trackingnotifyif) below. | | `notificationType` | Boolean\[\] | Determines through which channels notifications will be sent. Uses [NotificationType](https://env.7xmtools.com/api-docs/tracking-object.html#notificationtype) indexing. `true` means the channel will be used.
**Important:** the Tracking API only supports notifications through push webhooks or API pull requests. | | `notificationCSV` | Integer\[\] | A history of past notifications for this tracking. Each past notification consists of 5 entries, in the format:
`[AmazonLocale, Product.csvType, NotificationType, TrackingNotificationCause, KeepaTime]` | | `individualNotificationInterval` | Integer | A tracking-specific rearm timer. Possible values:
• `-1`: use the default notification timer of the user account (changeable via website settings)
• `0`: never notify a desired price more than once
• Any positive integer: rearm the desired price after *x* minutes | ## TrackingThresholdValue Contains settings for price or value-related tracking criteria. ```json { "thresholdValueCSV": Integer[], "domain": Integer, "csvType": Integer, "isDrop": Boolean } ``` | Field | Type | Description | | --- | --- | --- | | `thresholdValueCSV` | Integer\[\] | The history of threshold values (or desired prices). Format: `[KeepaTime, value]` | | `domain` | Integer | The Amazon locale to which this threshold value belongs. Regardless of the locale, the threshold value is always in the currency of the `mainDomainId`. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-object.html#domain-ids) below. | | `csvType` | Integer | The price type for this threshold value (refer to the `csv` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). | | `isDrop` | Boolean | Indicates whether this tracking threshold value tracks value drops (`true`) or value increases (`false`). | ## TrackingNotifyIf Contains specific meta tracking criteria, such as out-of-stock status. ```json { "domain": Integer, "csvType": Integer, "notifyIfType": Integer } ``` | Field | Type | Description | | --- | --- | --- | | `domain` | Integer | The Amazon locale to which this `notifyIf` belongs. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-object.html#domain-ids) below. | | `csvType` | Integer | The price type for this `notifyIf` (refer to the `csv` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). | | `notifyIfType` | Integer | Available notification meta trigger types. Possible values:
• **0**: `OUT_OF_STOCK`
• **1**: `BACK_IN_STOCK` | ## NotificationType The available notification channels. > **Note:** Only `API` is available as of now for API tracking. | Value | Type | | --- | --- | | **5** | `API` — push to webhook or pull through API request | ### Valid domain IDs Used by `mainDomainId` and the `domain` fields of the child objects: | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Example A Tracking Object as returned by the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html): watch the Amazon price on amazon.de for a drop to € 49.99, notify via API, and alert when the product goes out of stock: ```json { "asin": "B00M0QVG3W", "createDate": 7650000, "isActive": true, "ttl": 0, "expireNotify": false, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "trackingListName": "My price watches", "thresholdValues": [ { "thresholdValueCSV": [7650000, 4999], "domain": 3, "csvType": 0, "isDrop": true } ], "notifyIf": [ { "domain": 3, "csvType": 0, "notifyIfType": 0 } ], "notificationType": [false, false, false, false, false, true, false], "notificationCSV": [3, 0, 5, 1, 7661500], "individualNotificationInterval": -1 } ``` *Illustrative values.* The `notificationCSV` entry above reads: locale `3` (de), price type `0` (Amazon), channel `5` (API), cause `1` (desired price met), at Keepa Time `7661500`. # Tracking Creation Object Source: https://env.7xmtools.com/api-docs/tracking-creation-object.html Used to create a price watch via the Tracking API. There can be only one tracking per ASIN, regardless of the locale; a single Tracking Creation Object can contain desired prices for all locales. JSON Object · Sent with: Add Tracking A Tracking Creation Object is used to create a price watch. There can be only one tracking per ASIN, regardless of the locale. A single Tracking Creation Object can contain desired prices for all locales. > **Required by:** the *Add Tracking* request of the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html). The API returns the created watch as a [Tracking Object](https://env.7xmtools.com/api-docs/tracking-object.html). ## Format ```json { "asin": String, "ttl": Integer, "expireNotify": Boolean, "desiredPricesInMainCurrency": Boolean, "mainDomainId": Integer, "updateInterval": Integer, "metaData": String, "thresholdValues": TrackingThresholdValue[], "notifyIf": TrackingNotifyIf[], "notificationType": Boolean[], "individualNotificationInterval": Integer } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `asin` | String | The product ASIN to be tracked. Example: `"B00M0QVG3W"` | | `ttl` | Integer | The time-to-live (in hours) until the tracking expires and gets deleted. When setting this value via the *Add Tracking* request, it is relative to the time of the request. When retrieving the tracking object, it is relative to the `createDate`. Possible values:
• Any positive integer: time-to-live in hours
• `0`: never expires
• Any negative integer:
  • If tracking already exists: maintain the original `ttl`
  • If tracking is new: use the absolute value as `ttl` | | `expireNotify` | Boolean | Triggers a notification if the tracking expires or is removed by the system (e.g., product deprecated). | | `desiredPricesInMainCurrency` | Boolean | Indicates whether all desired prices are in the currency of the `mainDomainId`. If `false`, they will be converted. | | `mainDomainId` | Integer | The main Amazon locale of this tracking, determining the currency used for all desired prices. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-creation-object.html#domain-ids) below. | | `updateInterval` | Integer | The update interval in hours, determining how often the system will trigger a product update. A setting of 1 hour won't trigger an update exactly every 60 minutes but as close to that as efficiently possible. Throughout a day, it will be updated 24 times, but updates are not perfectly distributed. Possible values: any integer from **1** to **24** (inclusive). | | `metaData` | String | *Optional.* The metadata of this tracking (maximum length is 500 characters). Used to assign text to this tracking, such as a user reference or memo. | | `thresholdValues` | TrackingThresholdValue\[\] | *Optional.* Contains settings for price or value-related tracking criteria for all locales. See [TrackingThresholdValue](https://env.7xmtools.com/api-docs/tracking-creation-object.html#trackingthresholdvalue) below. | | `notifyIf` | TrackingNotifyIf\[\] | *Optional.* Contains specific meta tracking criteria like out-of-stock status for all locales. See [TrackingNotifyIf](https://env.7xmtools.com/api-docs/tracking-creation-object.html#trackingnotifyif) below. | | `notificationType` | Boolean\[\] | *Optional; defaults to webhook notifications.* Must be a Boolean array with the length of the [NotificationType](https://env.7xmtools.com/api-docs/tracking-creation-object.html#notificationtype) enum (which is 7; see below). Determines the channels through which notifications will be sent. Uses NotificationType indexing. `true` means the channel will be used.
**Important:** the Tracking API currently only supports notifications through push webhooks or API pull requests.
Example — only notify via API: `[false, false, false, false, false, true, false]` | | `individualNotificationInterval` | Integer | A tracking-specific rearm timer. Possible values:
• `-1`: use the default notification timer of the user account (changeable via website settings)
• `0`: never notify a desired price more than once
• Any positive integer: rearm the desired price after *x* minutes | ## TrackingThresholdValue Contains settings for price or value-related tracking criteria. ```json { "thresholdValue": Integer, "domain": Integer, "csvType": Integer, "isDrop": Boolean } ``` | Field | Type | Description | | --- | --- | --- | | `thresholdValue` | Integer | The threshold value (or desired price), represented as an integer of the smallest currency unit for the respective Amazon locale (e.g., euro cents or yen). | | `domain` | Integer | The Amazon locale to which this threshold value belongs. Regardless of the locale, the threshold value is always in the currency of the `mainDomainId`. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-creation-object.html#domain-ids) below. | | `csvType` | Integer | The price type for this threshold value (refer to the `csv` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). | | `isDrop` | Boolean | Indicates whether this tracking threshold value tracks value drops (`true`) or value increases (`false`). | ## TrackingNotifyIf Contains specific meta tracking criteria, such as out-of-stock status. ```json { "domain": Integer, "csvType": Integer, "notifyIfType": Integer } ``` | Field | Type | Description | | --- | --- | --- | | `domain` | Integer | The Amazon locale to which this `notifyIf` belongs. See the [valid domain IDs](https://env.7xmtools.com/api-docs/tracking-creation-object.html#domain-ids) below. | | `csvType` | Integer | The price type for this `notifyIf` (refer to the `csv` field of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). | | `notifyIfType` | Integer | Available notification meta trigger types. Possible values:
• **0**: `OUT_OF_STOCK`
• **1**: `BACK_IN_STOCK` | ## NotificationType The available notification channels. > **Note:** Only `API` is currently available for API tracking. | Value | Type | | --- | --- | | **5** | `API` — push to webhook or pull through API request | ### Valid domain IDs Used by `mainDomainId` and the `domain` fields of the child objects: | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Example A Tracking Creation Object that creates a never-expiring watch for the amazon.de Amazon price at a desired price of € 49.99, hourly updates, API notifications, plus an out-of-stock alert: ```json { "asin": "B00M0QVG3W", "ttl": 0, "expireNotify": false, "desiredPricesInMainCurrency": true, "mainDomainId": 3, "updateInterval": 1, "metaData": "customer-42", "thresholdValues": [ { "thresholdValue": 4999, "domain": 3, "csvType": 0, "isDrop": true } ], "notifyIf": [ { "domain": 3, "csvType": 0, "notifyIfType": 0 } ], "notificationType": [false, false, false, false, false, true, false], "individualNotificationInterval": -1 } ``` *Illustrative values.* See the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html) for how to submit this object with the *Add Tracking* request. # Notification Object Source: https://env.7xmtools.com/api-docs/notification-object.html Represents a price alert triggered by a tracking. Notifications are deleted after 24 hours. JSON Object · Returned by: Get Notifications & webhooks A Notification Object represents a price alert. Notifications are deleted after 24 hours. > **Returned by:** the notification request of the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html). **Provided by:** the *Get Notifications* call of the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html), or an HTTP POST webhook call to the URL set on the [API page](https://env.7xmtools.com/api) or through the *Set Webhook* call of the [Tracking API](https://env.7xmtools.com/api-docs/tracking.html). ## Format ```json { "notificationId": String, "asin": String, "title": String, "image": String, "ttl": Integer, "createDate": Integer, "domainId": Integer, "notificationDomainId": Integer, "csvType": Integer, "trackingNotificationCause": Integer, "currentPrices": Integer array, "sentNotificationVia": Boolean array, "metaData": String, "trackingListName": String } ``` ## Fields | Field | Type | Description | | --- | --- | --- | | `notificationId` | String | Unique identifier of this notification. Example: `"a3f1c04e9b27d5836ea1f0c94d2b78ef15a6c390"` | | `asin` | String | The ASIN (Amazon Standard Identification Number) of the notified product. Example: `"B00M0QVG3W"` | | `title` | String | The title of the product. **Note:** may contain HTML markup in rare cases. | | `image` | String | The main image name of the product. Full Amazon image URL: `https://images-na.ssl-images-amazon.com/images/I/` | | `ttl` | Integer | Time to live of the notification in minutes. | | `createDate` | Integer | The creation date of the notification in [Keepa Time minutes](https://env.7xmtools.com/api-docs/notification-object.html#keepa-time-minutes). | | `domainId` | Integer | The main Amazon locale of the tracking. See the [valid domain IDs](https://env.7xmtools.com/api-docs/notification-object.html#domain-ids) below. | | `notificationDomainId` | Integer | The Amazon locale that triggered the notification and determines the currency of the current prices provided. See the [valid domain IDs](https://env.7xmtools.com/api-docs/notification-object.html#domain-ids) below. | | `csvType` | Integer | The price type that triggered the notification. See the `csv` field indexing in the [Product Object](https://env.7xmtools.com/api-docs/product-object.html). | | `trackingNotificationCause` | Integer | The cause of the notification. See [TrackingNotificationCause](https://env.7xmtools.com/api-docs/notification-object.html#trackingnotificationcause) below. | | `currentPrices` | Integer\[\] | The prices or values of the product at the time the notification was created. Uses price type indexing (see the `csv` field in the [Product Object](https://env.7xmtools.com/api-docs/product-object.html)). The price is an integer representing the smallest currency unit of the respective Amazon locale (e.g., euro cents or yen). If no offer was available (e.g., out of stock), the price is `-1`. This field is `null` for tracking expiration notifications. | | `sentNotificationVia` | Boolean\[\] | Indicates through which notification channels this notification was delivered. Uses [NotificationType](https://env.7xmtools.com/api-docs/notification-object.html#notificationtype) indexing. `true` means the channel was used. | | `metaData` | String | The metadata of the tracking object that triggered the notification. | | `trackingListName` | String | The name of the tracking list containing the tracking that triggered this notification (maximum length of 64 characters). | ## TrackingNotificationCause The cause of a notification. Possible values: | Value | Cause | | --- | --- | | **0** | `EXPIRED`: Tracking expired. | | **1** | `DESIRED_PRICE`: Desired price met for the first time. | | **3** | `PRICE_CHANGE_AFTER_DESIRED_PRICE`: Price changed after previously meeting the desired price, and the tracking was rearmed but hasn't passed the desired threshold since. | | **4** | `OUT_STOCK`: Product is now out of stock for the specified price type (`csvType`). | | **5** | `IN_STOCK`: Product is back in stock for the specified price type (`csvType`). | | **6** | `DESIRED_PRICE_AGAIN`: Desired price met again after exceeding the threshold and the tracking was rearmed. | ## NotificationType The available notification channels. > **Note:** Only `API` is available for API tracking. | Value | Type | | --- | --- | | **5** | `API`: Push to webhook or pull through API request. | ### Valid domain IDs | Domain ID | Locale | | --- | --- | | **1** | com | | **2** | co.uk | | **3** | de | | **4** | fr | | **5** | co.jp | | **6** | ca | | **8** | it | | **9** | es | | **10** | in | | **11** | com.mx | | **12** | com.br | ## Keepa Time Minutes Time format used for all timestamps. To convert to an uncompressed Unix epoch time: - **For milliseconds:** `(keepaTime + 21564000) * 60000` - **For seconds:** `(keepaTime + 21564000) * 60` ## Example A Notification Object as delivered by webhook or the *Get Notifications* call — here the amazon.de Amazon price (`csvType` 0) dropped to the desired price: ```json { "notificationId": "a3f1c04e9b27d5836ea1f0c94d2b78ef15a6c390", "asin": "B00M0QVG3W", "title": "Canon PowerShot SX400 Digital Camera with 30x Optical Zoom (Black)", "image": "51InzcaVqrL.jpg", "ttl": 1440, "createDate": 7661500, "domainId": 3, "notificationDomainId": 3, "csvType": 0, "trackingNotificationCause": 1, "currentPrices": [4899, 5299, 4650, 12490], "sentNotificationVia": [false, false, false, false, false, true, false], "metaData": "customer-42", "trackingListName": "My price watches" } ``` *Illustrative values.* The `currentPrices` array is abridged — it uses the full price type indexing of the [Product Object](https://env.7xmtools.com/api-docs/product-object.html) `csv` field.