Keepa API Docs

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 if the stats parameter was used and is part of the Product Object (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.

Format#

{
    "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. 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 for the complete list):

IndexNameMeaning of the value at this index
0AMAZONAmazon price
1NEWMarketplace New price
2USEDMarketplace Used price
3SALESSales Rank (a rank, not a price)
4LISTPRICEList Price (MSRP)
11COUNT_NEWNew offer count (a count, not a price)
12COUNT_USEDUsed offer count (a count, not a price)
18BUY_BOX_SHIPPINGBuy 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 below).

FieldTypeDescription
currentInteger arrayContains the last updated product prices/ranks using the Price Type indexing (refer to the csv field in the Product Object). 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).
avgInteger arrayContains 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.
avg30Integer arraySame as avg, but for the last 30 days.
avg90Integer arraySame as avg, but for the last 90 days.
avg180Integer arraySame as avg, but for the last 180 days.
avg365Integer arraySame as avg, but for the last 365 days.
atIntervalStartInteger arrayContains 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.
minTwo-dimensional Integer arrayContains 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.
maxTwo-dimensional Integer arrayContains the highest prices ever registered for this product. Same structure as min.
minInIntervalTwo-dimensional Integer arraySame as min, but restricted to the interval specified in the Product Request’s stats parameter.
maxInIntervalTwo-dimensional Integer arraySame as max, but restricted to the interval specified in the Product Request’s stats parameter.
outOfStockPercentageInIntervalInteger arrayContains 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.
outOfStockPercentage30Integer arrayContains 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.
outOfStockPercentage90Integer arraySame as outOfStockPercentage30, but for the last 90 days.
outOfStockPercentage180Integer arraySame as outOfStockPercentage30, but for the last 180 days.
outOfStockPercentage365Integer arraySame as outOfStockPercentage30, but for the last 365 days.
lastOffersUpdateIntegerThe 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.
salesRankDrops30IntegerThe count of sales rank drops (from a high to a low value) within the last 30 days — considered to indicate sales.
salesRankDrops90IntegerSame as salesRankDrops30, but for the last 90 days.
salesRankDrops180IntegerSame as salesRankDrops30, but for the last 180 days.
salesRankDrops365IntegerSame as salesRankDrops30, but for the last 365 days.
totalOfferCountIntegerThe 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.
lightningDealInfoInteger arrayUsed 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#

FieldTypeDescription
lastBuyBoxUpdateIntegerTimestamp of the last Buy Box update, in Keepa Time minutes.
buyBoxSellerIdStringThe seller ID of the Buy Box offer, if it exists. Otherwise "-1", "-2" or null.
buyBoxPriceIntegerThe Buy Box new price, if it exists. Otherwise -1 or -2.
buyBoxShippingIntegerThe Buy Box new shipping cost, if it exists. Otherwise -1 or -2.
buyBoxSavingBasisIntegerThe Buy Box new strikethrough price, if it exists. Undefined (field absent) if unavailable.
buyBoxSavingBasisTypeStringThe reference type of the Buy Box new strikethrough price, if it exists: either LIST_PRICE or WAS_PRICE. Undefined (field absent) if unavailable.
buyBoxSavingPercentageIntegerThe stated percentage discount of the Buy Box new price, if it exists. Undefined (field absent) if unavailable.
buyBoxIsUnqualifiedBooleanIndicates whether a seller won the Buy Box. If only sellers with poor offers are available, none qualifies for the Buy Box.
buyBoxIsShippableBooleanIndicates whether the Buy Box is listed as being shippable.
buyBoxIsPreorderBooleanIndicates if the Buy Box is a pre-order.
buyBoxIsBackorderBooleanIndicates if the Buy Box is back-ordered.
buyBoxIsFBABooleanIndicates whether the Buy Box is fulfilled by Amazon.
buyBoxIsAmazonBooleanIndicates if Amazon is the seller in the Buy Box.
buyBoxIsMAPBooleanIndicates if the Buy Box new price is hidden on Amazon due to MAP (Minimum Advertised Price) restrictions.
buyBoxPriceIncludesImportFeesBooleanIndicates 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.
buyBoxAvailabilityMessageStringThe 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.
buyBoxShippingTimeInteger arrayThe 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.
buyBoxShippingCountryStringThe default shipping country of the Buy Box seller. null if not available or if the seller is Amazon. Example: "US"
buyBoxIsPrimeExclusiveBooleanIndicates if the Buy Box is Prime exclusive. null if not available.
buyBoxIsPrimeEligibleBooleanIndicates if the Buy Box is Prime eligible. null if not available.
buyBoxStatsObjectContains 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).
buyBoxUsedStatsObjectContains used Buy Box statistics for the specified interval. The format is the same as buyBoxStats.
buyBoxUsedPriceIntegerThe Buy Box used price, if available. Otherwise -1 or null.
buyBoxUsedShippingIntegerThe Buy Box used shipping cost, if available. Otherwise -1 or null.
buyBoxUsedSellerIdStringThe seller ID of the used Buy Box offer, if available. Otherwise null.
buyBoxUsedIsFBABooleanIndicates whether the used Buy Box is fulfilled by Amazon.
buyBoxUsedConditionIntegerThe offer sub-condition of the used Buy Box (see the sub-condition table below).

Per-seller entries in buyBoxStats / buyBoxUsedStats

FieldTypeDescription
avgNewOfferCountIntegerAverage “New” offer count during the time the seller held the Buy Box.
avgPriceIntegerAverage price of the Buy Box offer from this seller.
isFBABooleanWhether this offer is fulfilled by Amazon.
lastSeenIntegerLast time the seller won the Buy Box, in Keepa Time minutes.
percentageWonFloatPercentage of the time the seller won the Buy Box, for non-Prime shoppers.

Example:

"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)

ValueCondition
2Used – Like New
3Used – Very Good
4Used – Good
5Used – Acceptable

Fields only set if the offers parameter was used#

FieldTypeDescription
retrievedOfferCountIntegerThe 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). -2 is not an error code and does not state a reason. A successful retrieval for a product without offers returns 0.
sellerIdsLowestFBAString arrayContains the seller IDs (if any) of the lowest-priced live new FBA offers. Multiple entries exist if multiple offers share the same price.
sellerIdsLowestFBMString arrayContains the seller IDs (if any) of the lowest-priced live new FBM offers. Multiple entries exist if multiple offers share the same price.
offerCountFBAIntegerThe count of retrieved live new FBA offers, if available. Otherwise -2.
offerCountFBMIntegerThe count of retrieved live new FBM offers, if available. Otherwise -2.

Fields only set if the stock parameter was used#

FieldTypeDescription
stockAmazonIntegerThe stock of the Amazon offer, if available. Otherwise undefined (field absent).
stockBuyBoxIntegerThe 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. 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 parametersField groups included
statsCore statistics fields
stats + offers or buyboxAdditionally the Buy Box fields (lastBuyBoxUpdate … buyBoxUsedCondition)
stats + offersAdditionally the offer fields (retrievedOfferCount, sellerIdsLowestFBA/FBM, offerCountFBA/FBM)
stats + stockAdditionally stockAmazon and stockBuyBox

Tip: When relying on the offers-dependent fields, always check the offersSuccessful field of the Product Object 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
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
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
use Keepa\KeepaAPI;
use Keepa\API\Request;
use Keepa\API\ResponseStatus;
use Keepa\objects\AmazonLocale;

$api = new KeepaAPI("YOUR_API_KEY");
$response = $api->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);
}
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)
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 -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):

{
  "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). 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.