# 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.<br>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.<br>Example: `2700145` |
| `sellerId` | String | The seller ID of the merchant.<br>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.<br>Example: `true` |
| `isFBA` | Boolean | Whether or not this offer is fulfilled by Amazon.<br>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.<br>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.<br>Example: `true` |
| `isPreorder` | Boolean | Indicating whether or not the offer is a pre-order.<br>Example: `false` |
| `isWarehouseDeal` | Boolean | Indicating whether or not the offer is a Warehouse Deal.<br>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.<br>Example: `false` |
| `isPrimeExcl` | Boolean | This offer has a discounted Prime exclusive price.<br>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.<br>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.<br>Note: *Open Box* conditions are coded as *Used* conditions. |
| `conditionComment` | String | The describing text of the condition. **undefined** if unavailable.<br>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.<br>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.<br>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.<br> `1` — *typical price*: the median price customers paid over the last 90 days.<br> `2` — *recent lowest price*: the lowest price of the last 30 days, shown in the EU.<br> `3` — *list price*: the manufacturer’s suggested price (also RRP, UVP, M.R.P.).<br> `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).<br>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.<br>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=<yourAccessKey>&domain=<domainId>&asin=<ASIN>&offers=<count>
```

**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
<?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']));
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`).
