# ShopSavvy Data API - Changelog

> Version history, feature updates, and breaking changes

*Source: https://shopsavvy.com/data/changelog*

Subscribe: https://shopsavvy.com/data/changelog.xml (RSS). Versioning and deprecation policy: https://shopsavvy.com/data/documentation/versioning

---

## 2026-10-12

### Added
- **MCP price answers name their source** — The MCP tools `product_lookup`, `product_offers`, `product_offers_retailer` and `product_price_history` end with a source line naming ShopSavvy, linking the product page on shopsavvy.com and giving the time the latest price was checked. Each current offer also shows when it was last checked.

### Changed
- **MCP tool descriptions say when to use each tool and what it costs** — Every MCP tool description now states what it returns, when to use it instead of its siblings, which identifiers match best, its credit cost with a key (free without one), and to report "no data" rather than guess. `product_lookup_batch` results now include the ShopSavvy ID.
- **MCP scheduling tools need an API key** — `product_schedule`, `product_unschedule` and `scheduled_products_list` now return `ERR_AUTH_MISSING` without an API key, because a schedule belongs to an account. Lookups, offers, price history and the content tools still work without a key.

---

## 2026-09-30

### Added
- **Every product says how it matched** — Products returned by any endpoint that takes identifiers now carry a `match` object: the `identifier` you sent, the field it matched `by` (`barcode`, `shopsavvy_id`, `asin`, `url`, `model`, `mpn` or `name`), and how many `candidates` shared that identifier. Line results up with your request and tell an exact match from a name-search best guess.
- **Marketplace and condition on every offer** — Offers now include `is_marketplace` (`true` for a third-party marketplace seller, `false` when the retailer sells it, `null` when unknown) and `condition_grade` (for example `open-box` or `refurbished-excellent`), in JSON and as CSV columns.

### Changed
- **Identifier matching gives the same answer every time** — A full-length barcode with a valid check digit is looked up only as a barcode, so a UPC can no longer come back as an unrelated product whose model number happens to be the same digits. ShopSavvy product IDs are matched right after barcodes. When several products share a barcode or model number, the one with the most evidence behind it is returned, consistently.
- **"Product not found" tells you what to try next** — `ERR_PRODUCT_NOT_FOUND` now says whether the barcode check digit failed (usually a missing or extra digit), whether the barcode simply is not in the catalog yet, or which other identifiers to try.
- **Hourly request limit reported the same way everywhere** — Every authenticated response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and `meta.rate_limit_remaining` shows the same number on every endpoint, including errors and `GET /v1/usage`. More than 1,000 requests in a rolling hour returns `429 ERR_RATE_LIMIT` with a `Retry-After` header; rejected requests do not count against the limit.
- **Scheduled monitoring refreshes on the cadence you chose** — Products scheduled with `PUT /v1/products/scheduled` are re-checked hourly, daily or weekly at the retailers we can re-check through an official retailer API (Amazon and Best Buy). Offers at other retailers keep updating as ShopSavvy sees them, each with its own timestamp. Refreshes are not charged; scheduling still costs 1 credit per product.
- **Rescheduling updates instead of duplicating** — A newly scheduled product shows up in `GET /v1/products/scheduled` right away, and scheduling it again updates the existing schedule instead of adding a second one.
- **No credit for a review that does not exist** — `GET /v1/products/reviews`, and `POST /v1/products/batch` with `include: ["reviews"]`, no longer charge a credit when the product has no TLDR review.
- **Playground shows exactly what your code receives** — Live Mode in the API Playground shows the real response, including error bodies with their `action` hint, the HTTP status and the request id. Every response is labelled Demo, Live Sandbox or Live, and the copied curl command matches the request that ran.

### Fixed
- **Unknown availability is always omitted** — Offers with unknown availability now always omit `availability`, as documented, instead of sometimes returning `null`.

---

## 2026-09-28

### Fixed
- **Playground Live Mode calls the API as your key** — Live Mode was returning the sample demo response (`isDemo: true`, 0 credits). It now sends real requests with the API key you select, so results, credit usage and errors match what your own code sees, on every playground endpoint including deals, reviews and batch lookup.
- **New subscriptions always get dashboard access and a key** — A subscription started before your ShopSavvy account had finished setting up could leave you without dashboard access or an API key. The account is now completed when the subscription starts, so your plan, credits and first key are ready right away.

---

## 2026-09-27

### Added
- **Standard MCP transports with anonymous access** — The MCP server at `https://api.shopsavvy.com/mcp` now speaks the standard Streamable HTTP transport (plus legacy HTTP+SSE at `/mcp/sse`), so Claude Code, Cursor, VS Code, Codex and other clients connect by URL: `claude mcp add --transport http shopsavvy https://api.shopsavvy.com/mcp`. It works without a key at a lower rate limit; add your API key as a Bearer token to raise it.

### Fixed
- **Schedule and unschedule accept the SDK request body** — The JSON body the published SDKs send to schedule and unschedule products is now accepted, alongside query parameters.
- **Bare retailer domains work on price history and scheduling** — Passing a retailer as a bare domain (`retailer=bestbuy.com`, the documented format) no longer returns a 500 on `GET /v1/products/offers/history` and scheduling.
- **`GET /v1/products/scheduled` with a removed product** — Listing scheduled products no longer returns a 500 when one of them has since been removed from the catalog.

---

## 2026-08-25

### Changed
- **`product_price_history` accepts `start` and `end`** — The MCP tool now also accepts `start` and `end`, the names the REST endpoint uses. `start_date` and `end_date` keep working.

---

## 2026-08-14

### Fixed
- **`GET /v1/usage` works again** — The usage endpoint returned a 500 on every call. It now returns your credits used, credits remaining and request counts for the current billing period.

---

## 2026-08-10

### Added
- **Webhook event ids and attempt numbers for safe retries** — Every delivery carries a stable event id (`id` in the body, `X-ShopSavvy-Event-Id` header) that is the same on the first attempt and every retry, and an `attempt` number (`X-ShopSavvy-Delivery-Attempt`, `1` to `5`). Record the ids you have processed and ignore repeats; `timestamp` and the signature change on every attempt.

### Changed
- **Price history matches the ShopSavvy price chart** — `GET /v1/products/offers/history` and the `product_price_history` tool now apply the same filters as the chart on shopsavvy.com: a point must come from a verified retailer or a listing confirmed to be this exact product, must carry a real price in the listing's own currency, and must pass the same per-retailer outlier check. Expect fewer, cleaner points on noisy products.
- **Price history points carry price, date and currency** — Each history point now returns `price`, `timestamp`, `currency` and `availability` (only `availability` was coming through), and the CSV `currency` column reflects the archived value. All 10 SDKs describe the real shape, `offer.history[].timestamp`.
- **Offers exclude listings our validation judged wrong** — Every offer endpoint and MCP offer tool now drops listings flagged as a wrong-product or wrong-price match, listings from an unresolved retailer, and archive rows with no real price. `POST /v1/products/batch` with `include: ["offers"]` returns the same filtered set as `GET /v1/products/offers`.
- **Charged only for offers we found** — Batch lookups no longer add 3 credits for a product whose offer list is empty, and the per-day part of price-history pricing is not charged when the request finds no offers.
- **Up to 100 identifiers per request** — Every endpoint that takes a comma-separated `ids` list accepts at most 100 identifiers, matching `POST /v1/products/batch`. Larger requests are rejected with `ERR_INVALID_PARAMS` before any credits are charged. An empty `ids` value now returns `ERR_IDENTIFIER_REQUIRED`.
- **Price history windows of up to 366 days** — Price history is charged per day of the requested window, so one request now spans at most 366 days. Request longer histories in successive windows.
- **Price history no longer includes eBay** — A fresh eBay listing can still appear in `offers`, but its `history` array is always empty, matching the ShopSavvy price chart.
- **Webhooks deduplicated per retailer** — Two retailers changing price on the same product in the same pass now produce one delivery each, instead of collapsing into one delivery for the hour.
- **Documentation: USD offers and per-request history pricing** — The docs and OpenAPI spec now state that offer endpoints return USD-denominated offers only, and that the per-day part of price-history pricing is charged once per request, not per product. Nothing about responses or charges changed.

### Fixed
- **Reversed credits come back to your balance immediately** — When a failed request is reversed, your remaining monthly allowance and any referral bonus it drew on are restored at once, so `credits_used: 0` on an error matches your balance.
- **A failed request counts once against the hourly limit** — A request that errored after being recorded could count twice toward the rate limit. Requests are now counted, not log rows.
- **MCP tool errors report credits and reverse charges** — A failed MCP tool call now includes `credits_used`, `credits_remaining` and `rate_limit_remaining` in the JSON-RPC error `data`, and any credits recorded for it are reversed, as the REST endpoints already did.
- **Referral bonus credits fully usable** — Bonus credits are spent after your plan allowance is used up, and the whole bonus balance is available in a single month.

---

## 2026-08-04

### Fixed
- **Start a trial right after creating an account** — Going straight from a new account to "Start Free Trial" could fail with "User not found". Checkout now works from the moment your account exists.

---

## 2026-07-19

### Added
- **Per-aspect review scores** — Product `score` objects and TLDR review `scores` now include an `aspects` map of per-aspect scores (e.g. `value`, `features`, `reliability`, `quality`) aggregated from the product's professional reviews. Aspect names are free-form and vary per product.

### Fixed
- **Documentation correction: scores are 0-1 scale** — All quality scores (`overall`, `customer`, `professional`, and aspect scores) are on a 0-1 scale, and always have been. The docs previously described a 0-100 scale and three fixed aspect fields (`value`, `features`, `reliability`) that were never actually returned. The API's numeric output is unchanged; multiply by 10 or 100 if you want a /10 or /100 display score.

---

## 2026-07-09

### Changed
- **Faster price-history lookups** — `GET /v1/products/offers/history` returns quickly even for products with long, deep histories, and no longer times out on wide date ranges.

---

## 2026-07-01

### Added
- **Payment-failure emails and a grace window** — If a subscription charge fails you get an email right away with a link to update your card and retry, and API access keeps working for a week after the first failed attempt.

### Changed
- **Custom-plan dashboards** — Customers on a custom plan no longer see the public plan upgrade prompts in the dashboard, keys, webhooks, playground or billing pages.

---

## 2026-06-19

### Added
- **Live Sandbox in the playground** — The API Playground has a Live Sandbox mode that sends real calls for a set of sample products, with no account and no credits.
- **Referral program** — Share your referral link (`shopsavvy.com/data?ref=YOUR_CODE`) and earn bonus API credits when a developer you refer becomes a paying subscriber. Your link and referrals are on the Referrals page of the dashboard.

---

## 2026-06-12

### Changed
- **More identifiers resolve** — Catalog data from additional retail-network partners fills in barcodes, brands and model numbers, so more products resolve on identifier lookups.

---

## 2026-05-23

### Added
- **Update webhooks in place** — `PUT /v1/webhooks/:id` changes a webhook's URL, events or `is_active` flag without deleting it and losing its signing secret. Omitted fields are left alone, and re-enabling a webhook resets its failure counter. Available in all 10 SDKs as `updateWebhook`.

---

## 2026-05-20

### Added
- **Webhooks fire for real events** — Registered webhooks for `price_drop`, `availability_change` and `schedule_completion` now receive signed POSTs when a scheduled product changes, not only from the dashboard test button. Deliveries are deduplicated per webhook, event and product for 60 minutes, retried with backoff (1m, 5m, 30m, 2h, 12h), and a webhook is disabled after 50 consecutive failures.

---

## 2026-05-14

### Added
- **Webhooks dashboard** — Register, test, enable or disable, and delete webhooks from `/data/webhooks`.
- **API Playground page** — The playground is now a dedicated page at `/data/playground`.
- **Automatic first API key** — Starting a subscription creates a default API key, so you can make calls right away.

### Changed
- **Instant subscription activation** — Your subscription, dashboard and API key are ready the moment you return from checkout.
- **Per-key usage breakdown** — The Usage page shows live credit and request counts for each of your API keys.
- **Smarter auth redirects** — Signing in from any Data API page takes you straight to your dashboard.

---

## 2026-04-07

### Added
- **Webhook system** — Register URLs to receive notifications on price drops, availability changes and schedule completions, with HMAC-SHA256 signature verification, exponential backoff retry, and auto-disable after repeated failures.
- **OpenAPI 3.0 spec** — The API specification is available at `https://api.shopsavvy.com/v1/openapi.json` for Postman import, SDK generation and tooling.
- **Credit usage alerts** — `X-Credits-Warning` response header when usage passes 75%, and a dashboard banner at 75%, 90% and 100%.
- **Persistent sidebar navigation** — Every dashboard page has a sidebar with all sections and a credit usage indicator.
- **Usage charts** — Daily usage line chart and endpoint breakdown on the dashboard.
- **Code snippets in 11 languages** — Examples cover cURL, TypeScript, Python, Go, Ruby, Java, PHP, C#, Rust, Swift and Kotlin.
- **Collapsible JSON tree viewer** — The playground response viewer expands and collapses, color-codes values, and has a Raw JSON toggle.
- **Table view for arrays** — Offers, deals and search results can be viewed as sortable tables in the playground.
- **Response metrics** — Response time (ms) and payload size (KB) shown after each playground request.

### Changed
- **Expanded product fields** — Product responses include `title_short`, `slug`, `description`, `categories`, `attributes`, `rating`, `score`, `keywords` and `identifiers`.
- **Improved error responses** — All errors include `error_detail` with `code`, `message`, `action` and `docs_url`, and every response includes `request_id` in `meta`.
- **Retry-After header** — 429 rate limit responses include the standard `Retry-After` HTTP header.

---

## 2026-04-06

### Added
- **Deals endpoint** — `GET /v1/deals` returns a deals feed with expert grades (A+ through F), community votes, hot/new/top sorting, filtering by category, retailer, price and grade, and CSV export.
- **TLDR Reviews endpoint** — `GET /v1/products/reviews` returns expert review summaries with pros, cons, a bottom-line verdict and quality scores.
- **Batch product lookup** — `POST /v1/products/batch` looks up many products at once: synchronous for 20 identifiers or fewer, asynchronous with polling above that. It can include offers and reviews.
- **CSV format support** — `?format=csv` works on all endpoints, including search and price history.
- **Standardized error codes** — Error codes from `ERR_AUTH_MISSING` to `ERR_INTERNAL`, each with an actionable message and a documentation link.

---

## 2026-03-15

### Added
- **Product Search endpoint** — `GET /v1/products/search` for keyword product discovery with pagination.
- **Scheduled Monitoring** — `PUT /v1/products/scheduled` sets hourly, daily or weekly refresh cadences for tracked products.
- **API Playground demo mode** — Try every endpoint with sample data, no credits consumed.
- **Live mode playground** — Test with your own API key and see real product data and credit use.

### Changed
- **Improved product matching** — Better handling of model numbers and URLs as identifiers, and faster ASIN lookups.

---

## 2026-02-28

### Added
- **CSV export** — `?format=csv` on `/products` and `/products/offers` for spreadsheets.
- **Single retailer filtering** — `?retailer=amazon.com` on the offers endpoint returns prices from one retailer only.
- **Usage endpoint** — `GET /v1/usage` returns credits used, credits remaining and request count for the current billing period.

### Fixed
- **Price history date validation** — Clearer error messages when a date is in the wrong format.
- **Offer deduplication** — Duplicate offers from the same retailer are removed from responses.

---

## 2026-02-15

### Added
- **Developer Dashboard** — Usage analytics, API key management, subscription billing and an onboarding checklist.
- **Subscriptions** — Starter ($49/mo), Professional ($199/mo) and Enterprise ($499/mo) plans, with a 14-day trial on Starter.
- **API key management** — Create up to 5 API keys per account, revoke keys, and see when each was last used.
- **Grandfathered legacy allowance** — Accounts that used the API before plans existed keep 50 credits a month.

---

## 2026-01-30

### Added
- **Initial API launch** — Product lookup, all-retailer prices and price history endpoints.
- **API key authentication** — Bearer token auth with `ss_live_` prefixed keys, stored as SHA-256 hashes.
- **Credit-based billing** — 1 credit per product lookup, 3 per all-retailer offers, 2 per single-retailer offers, 1 per day of history.
- **Rate limiting** — 100 requests a minute for authenticated users and 10 a minute for anonymous MCP access.
- **10 official SDKs** — TypeScript, Python, Go, Ruby, Java, PHP, C#, Rust, Swift and Kotlin.
- **MCP server** — A Model Context Protocol server for AI assistants (Claude, Cursor and others), with anonymous rate-limited access.
