
# Use shelf data from your own code or agent

Shelf data is the Amazon page as a shopper at a given location sees it: the search results page for a keyword, the Buy Box for an ASIN, the whole offer list, the product page, a seller's storefront. The MixShift plugin's Amazon Shelf skill is one way in; this article is the other two: the REST endpoints for your own code and automations, and the `shelf_*` tools for AI clients over MCP. Beta, on for every organization. Full reference: [mcp.mixshift.io/developers#shelf](https://mcp.mixshift.io/developers#shelf).

## Where the data comes from, and what it is not

Public shelf observations from a licensed third-party shelf-data provider, through MixShift's service on MixShift's own key. No call uses your Amazon authorization, and nothing of yours is sent: an ASIN, a keyword or a seller id is the only input. It is not your account's data (that is the retail surface), not sales estimates ("bought in past month" is the label Amazon puts on its own page), and nothing here writes anywhere.

## Access

- **Scope:** `shelf:read`. Interactive sign-ins hold it, and so does a sign-in from a ChatGPT custom app or a Claude, Cursor or Codex connector. A service credential minted at `/admin` gets it by default; a tenant admin can deny it per person.
- **Organization:** your account must belong to a MixShift organization (every customer does). If a call answers `shelf_not_enrolled`, ask MixShift.
- **Allowance:** every data answer counts one against your organization's monthly shelf allowance (a larger discovery allowance in the first month, a monthly one after; no rollover). `GET /api/shelf/usage` and the zip list are free. See "When you run out" below.

## The calls

| REST | MCP tool | Body | What comes back in `data` |
|---|---|---|---|
| `POST /api/shelf/search` | `shelf_search` | `{ "query", "surface": "desktop" or "mobile", "page": 1 to 5, "zip", "country", "fresh" }` | every position with `rank`, `absolute_rank`, `is_sponsored`, price, rating, reviews, `monthly_sales`, badges, coupon, stock text, delivery promise; `banners` (sponsored brands with brand and headline); `related_keywords`, `total_results`, `has_more`. Desktop is 60 positions a page, mobile 15. One page is one answer. |
| `POST /api/shelf/buybox` | `shelf_get_buybox` | `{ "asin", "zip", "country", "fresh" }` | price, seller and `seller_id`, ships-from, Prime, stock, `free_delivery` and `fastest_delivery` as text and as `promise_days_*` |
| `POST /api/shelf/offers` | `shelf_get_offers` | `{ "asin", "zip", "country", "fresh" }` | the featured offer plus `offers[]`: price and `price_num`, `fba`, condition, `seller_id`, promise days |
| `POST /api/shelf/product` | `shelf_get_product` | `{ "asin", "zip", "country", "fresh" }` | title, bullets, details, media, best-seller ranks, rating, badge, the Buy Box block, "customers say"; the answer carries `beta: true` (a field can be missing) |
| `POST /api/shelf/seller` | `shelf_get_seller` | `{ "seller_id", "country", "fresh" }` | storefront name, rating, description, business details |
| `GET /api/shelf/zips?country=us` | `shelf_list_zips` | | the shopper locations per country (`us` default; `ca uk de fr it es in`). Free. |
| `GET /api/shelf/usage` | `shelf_get_usage` | | `period`, `allowance`, `used`, `remaining`, `resets_at`. Free. |

Only `query`, `asin` or `seller_id` is required. `zip` is a location from the zip list (omit for the default location; a zip off the list is refused for free). `country` defaults to `us`. `fresh: true` asks for the shelf as of now instead of a recent observation, at the same cost.

A keyword rank call from your own code:

```
POST https://mcp.mixshift.io/api/shelf/search
Authorization: Bearer <token>
Content-Type: application/json

{ "query": "backpacking meals", "surface": "mobile", "zip": "10001" }
```

Every data answer has one shape:

```
{ "ok": true, "kind": "search_mobile", "retailer": "amazon", "country": "us", "zip": "10001",
  "subject": "backpacking meals", "observed_at": "2026-10-20T14:41:13.187Z", "source": "shelf",
  "data": { "surface": "mobile", "page": 1, "page_size": 15, "products": [ ... ], ... } }
```

`observed_at` is when the shelf looked like this. MixShift may answer from a recent observation (hours for rank, the Buy Box and offers; a day for the product page; a week for a seller); nothing in the answer says how it was produced. Rank on page `n` is `absolute_rank = (n - 1) * page_size + rank`.

## From ChatGPT, Claude, Cursor or Codex

Connect the MixShift MCP server as described in [Connect AI tools over MCP](/knowledge-base/builder-platform/how-to/connect-ai-tools-over-mcp); the sign-in grants `shelf:read` with the rest. The seven tools then appear next to the warehouse and Amazon tools, and a question such as "where do we rank for backpacking meals in New York on mobile?" maps to `shelf_search`. The tool descriptions say what each call costs; the allowance is per organization, so a connector and the plugin draw on the same monthly number.

## Tracking rank over time

Every observation MixShift takes is kept and dated, so calling the same keyword at the same zip on a schedule (your own cron, n8n, or a MixShift scheduled task) builds a dated series. A MixShift-run tracked keyword list, with the history on a page and feeding the daily health check and the monthly report, is the next thing being built on this data; to be first on it, send MixShift your keywords, locations and cadence (from the plugin, "track these keywords for me"; or email MixShift). Daily observations count against the allowance like any other answer until history is priced.

## When you run out

The call answers `402 shelf_allowance_exhausted` with `period`, `allowance`, `used`, `resets_at` and `request_more`, which says how to ask for more: from the plugin, "request more shelf requests" sends the request with your organization and period; or reply to any MixShift message. MixShift raises the allowance from your organization's settings, with effect this month.

## Errors

The usual envelope, `{ "ok": false, "kind", "friendly", "source", "retryable", ... }`; branch on `kind`:

| kind | status | meaning |
|---|---|---|
| `shelf_not_enabled` | 403 | shelf data is switched off for your organization; ask MixShift |
| `shelf_not_enrolled` | 403 | your account has no organization yet; ask MixShift |
| `shelf_allowance_exhausted` | 402 | the month's allowance is used; see above |
| `zip_unavailable` | 400 | not a location on the list (`available_count` says how many are) |
| `bad_request` | 400 | refused as sent, for example no such ASIN or seller; do not resend unchanged |
| `invalid_request` | 400 | the body did not pass; nothing was sent |
| `throttled` | 429 | retry after `retryAfterMs` |
| `upstream_unavailable` | 502 | shelf data is temporarily unavailable; retry in a minute |

For the general failure contract (who acts, whether to retry), see [When a call fails](/knowledge-base/builder-platform/reference/when-a-call-fails).