Keepa API Docs

By accessing our 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 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=<yourAccessKey>&selection=<queryJSON>
ParameterRequiredDescription
keyrequiredYour private API key.
selectionrequiredThe 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=<yourAccessKey>
ParameterRequiredDescription
keyrequiredYour private API key.
POST payloadrequiredMust contain the queryJSON (no URL encoding needed).

Tip: To quickly get a valid queryJSON, there is a link on the deals page 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:

{
  "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#

ParameterRequiredDescription
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 IDLocale
1com
2co.uk
3de
4fr
5co.jp
6ca
8it
9es
10in
11com.mx
12com.br

Valid priceTypes values

ValuePrice Type
0AMAZON: Amazon price
1NEW: Marketplace New price
2USED: Marketplace Used price
3SALES: Sales Rank
5COLLECTIBLE: Collectible price
6REFURBISHED: Refurbished price
7NEW_FBM_SHIPPING: New FBM with shipping
8LIGHTNING_DEAL: Lightning Deal price
9WAREHOUSE: Amazon Warehouse price
10NEW_FBA: New FBA price
18BUY_BOX_SHIPPING: New Buy Box with shipping
19USED_NEW_SHIPPING: Used - Like New with shipping
20USED_VERY_GOOD_SHIPPING: Used - Very Good with shipping
21USED_GOOD_SHIPPING: Used - Good with shipping
22USED_ACCEPTABLE_SHIPPING: Used - Acceptable with shipping
27REFURBISHED_SHIPPING: Refurbished with shipping
32BUY_BOX_USED_SHIPPING: Used Buy Box with shipping
33PRIME_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

ValueInterval
0Day (last 24 hours)
1Week (last 7 days)
2Month (last 31 days)
33 Months (last 90 days)

Filter options#

ParameterRequiredDescription
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.
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.

ParameterRequiredDescription
materialoptionalInclude only products made of the specified material (e.g. “cotton”).
Example: "material": ["cotton"]
typeoptionalInclude only products matching the specified type (e.g. “shirt”, “dress”).
manufactureroptionalInclude only products from the specified manufacturer.
brandoptionalInclude only products from the specified brand.
modeloptionalInclude only products matching the specified model identifier.
coloroptionalInclude only products matching the specified color attribute.
sizeoptionalInclude only products matching the specified size (e.g. “small”, “one size”).
unitTypeoptionalInclude only products with the specified unit type (e.g. “count”, “ounce”).
scentoptionalInclude only products with the specified scent (e.g. “lavender”, “citrus”).
itemFormoptionalInclude only products matching the specified item form (e.g. “liquid”, “sheet”).
patternoptionalInclude only products matching the specified pattern (e.g. “striped”, “solid”).
styleoptionalInclude only products matching the specified style attribute (e.g. “modern”, “vintage”).
itemTypeKeywordoptionalInclude only products matching the specified item type keyword (custom search term, e.g. “books”, “prints”).
targetAudienceKeywordoptionalInclude only products targeting the specified audience (e.g. “kids”, “professional”).
editionoptionalInclude only products matching the specified edition (e.g. “first edition”, “standard edition”).
formatoptionalInclude only products in the specified format (e.g. “kindle ebook”, “import”, “dvd”).
authoroptionalInclude only products by the specified author (applicable to books, music, etc.).
bindingoptionalInclude only products with the specified binding type (e.g. “paperback”).
languagesoptionalInclude only products available in the specified languages. Use an array of language names.
brandStoreNameoptionalInclude only products sold under the specified brand store name on Amazon.
brandStoreUrlNameoptionalInclude only products sold under the specified URL-friendly brand store identifier.
websiteDisplayGroupoptionalInclude only products in the specified website display group.
websiteDisplayGroupNameoptionalInclude only products in the specified website display group name (a more user-friendly label).
salesRankDisplayGroupoptionalInclude 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].

ParameterRequiredDescription
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#

ParameterRequiredDescription
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

ValueSort ByOrder
1Deal ageNewest deals first (not invertible)
2Absolute deltaHighest delta to lowest
3Sales RankLowest rank to highest
4Percentage deltaHighest 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:

{
  "dr": [deal objects],
  "categoryIds": [Long],
  "categoryNames": [String],
  "categoryCount": [Integer]
}
FieldDescription
dr Ordered array of all deal objects 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 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:

{
  "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:

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:

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
use Keepa\KeepaAPI;
use Keepa\API\Request;
use Keepa\API\ResponseStatus;
use Keepa\objects\AmazonLocale;

use Keepa\API\DealRequest;
$api = new KeepaAPI("YOUR_API_KEY");
$dealQuery = new DealRequest();
$dealQuery->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;
    }
}
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"])
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 -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):

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#

{
  "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 page for the full structure of the entries in dr.