{
  "info": {
    "name": "ShopSavvy Data API",
    "description": "Product details, current prices, price history, deals, and expert reviews for 30M+ products across tens of thousands of retailers. Look up by barcode, UPC/EAN, ASIN, model number, MPN, URL, or product name. JSON or CSV responses, with official SDKs in 10 languages.\n\nAuthentication: send your API key as `Authorization: Bearer ss_live_...`. Every response reports `credits_used`, `credits_remaining` and `rate_limit_remaining` in `meta`; each account can make 1,000 requests per rolling hour. Errors never cost credits. Each operation's `x-credit-cost` states what it charges.\n\nDocumentation: https://shopsavvy.com/data/documentation · Errors: https://shopsavvy.com/data/documentation/errors · Changelog: https://shopsavvy.com/data/changelog\n\nGenerated from the OpenAPI 3.0.3 spec (version 1.3.0). Set the apiKey variable to your ss_live_ key.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.shopsavvy.com/v1"
    },
    {
      "key": "apiKey",
      "value": "ss_live_your_key_here"
    }
  ],
  "item": [
    {
      "name": "products",
      "item": [
        {
          "name": "Look up product details",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products?ids=611247373064,B07GV2S1GS",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products"
              ],
              "query": [
                {
                  "key": "ids",
                  "value": "611247373064,B07GV2S1GS",
                  "description": "Up to 100 comma-separated product identifiers of any type: UPC, EAN, ISBN, GTIN, Amazon ASIN, model number, MPN, product URL at any retailer (URL-encoded), product name, or ShopSavvy product ID. Identifiers that match nothing are left out of `data`; use each product's `match.identifier` to line results up with your request."
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns the product record for each identifier you send: title, brand, category, images, identifiers, rating and scores. Identifiers of different types can be mixed in one request. Each product carries a `match` object showing which identifier produced it and how."
          }
        },
        {
          "name": "Search products by keyword",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/search?q=sony headphones",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "search"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "sony headphones",
                  "description": "Search text."
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "offset",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Full-text search over the product catalog, best match first, with pagination. Use it when you have a name or description rather than an identifier, then pass a result's `shopsavvy`, `barcode` or `amazon` value to the offers and history endpoints."
          }
        },
        {
          "name": "Get current prices from all retailers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/offers?ids=611247373064,B07GV2S1GS",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "offers"
              ],
              "query": [
                {
                  "key": "ids",
                  "value": "611247373064,B07GV2S1GS",
                  "description": "Up to 100 comma-separated product identifiers of any type: UPC, EAN, ISBN, GTIN, Amazon ASIN, model number, MPN, product URL at any retailer (URL-encoded), product name, or ShopSavvy product ID. Identifiers that match nothing are left out of `data`; use each product's `match.identifier` to line results up with your request."
                },
                {
                  "key": "retailer",
                  "value": "bestbuy.com",
                  "description": "Only this retailer, as a domain such as `bestbuy.com` or `amazon.com`.",
                  "disabled": true
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns each product with an `offers` array: one entry per retailer listing, with price, availability, condition, marketplace seller and when ShopSavvy last saw it. Pass `retailer` to get one retailer only.\n\nReturns USD-denominated offers only. Offers mined in other currencies (GBP, EUR, CAD, AUD and ~40 more) exist but are not served by this endpoint and there is no parameter to request them, so an empty `offers` array can mean either \"no offers on file\" or \"no USD offers on file\". Offers our product-match validation flagged as invalid, and offers from unknown/untrusted-source retailers, are excluded."
          }
        },
        {
          "name": "Get historical price data",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/offers/history?ids=611247373064,B07GV2S1GS&start=2026-09-01&end=2026-09-30",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "offers",
                "history"
              ],
              "query": [
                {
                  "key": "ids",
                  "value": "611247373064,B07GV2S1GS",
                  "description": "Up to 100 comma-separated product identifiers of any type: UPC, EAN, ISBN, GTIN, Amazon ASIN, model number, MPN, product URL at any retailer (URL-encoded), product name, or ShopSavvy product ID. Identifiers that match nothing are left out of `data`; use each product's `match.identifier` to line results up with your request."
                },
                {
                  "key": "start",
                  "value": "2026-09-01",
                  "description": "YYYY-MM-DD. `start_date` is accepted as an alias."
                },
                {
                  "key": "end",
                  "value": "2026-09-30",
                  "description": "YYYY-MM-DD, at most 366 days after `start`. `end_date` is accepted as an alias."
                },
                {
                  "key": "retailer",
                  "value": "bestbuy.com",
                  "description": "Only this retailer, as a domain such as `bestbuy.com` or `amazon.com`.",
                  "disabled": true
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns each product's offers with a `history` array of dated price and availability points between `start` and `end`. Points are quality-filtered to the same series the ShopSavvy price chart renders, and eBay listings never carry history. The window may span at most 366 days; request longer histories in successive windows.\n\nReturns USD-denominated offers and USD history points only; there is no currency parameter (see /products/offers)."
          }
        },
        {
          "name": "Get TLDR review for a product",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/reviews?id=B09XS7JWHH",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "reviews"
              ],
              "query": [
                {
                  "key": "id",
                  "value": "B09XS7JWHH",
                  "description": "One product identifier (barcode, ASIN, URL, model number or ShopSavvy id)."
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns ShopSavvy's expert review summary for one product: headline, pros, cons, bottom line and 0-1 quality scores. `review` is null when the product has no TLDR review."
          }
        },
        {
          "name": "Batch product lookup",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/products/batch",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "batch"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"identifiers\": [\n    \"611247373064\",\n    \"B07GV2S1GS\"\n  ],\n  \"include\": [\n    \"offers\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Looks up 1-100 identifiers in one request, optionally with offers and reviews. Up to 20 identifiers answer synchronously (200 with `results`); more than 20 create an asynchronous job (202 with `batch`), which you poll at `GET /batch/{batchId}`."
          }
        },
        {
          "name": "List scheduled products",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/scheduled",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "scheduled"
              ]
            },
            "description": "Returns every product you have scheduled for refreshes, with its `schedule` and, when limited to one retailer, its `retailer`. Read their latest prices with `GET /products/offers`."
          }
        },
        {
          "name": "Schedule product monitoring",
          "request": {
            "method": "PUT",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/scheduled?ids=611247373064,B07GV2S1GS&schedule=hourly",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "scheduled"
              ],
              "query": [
                {
                  "key": "ids",
                  "value": "611247373064,B07GV2S1GS",
                  "description": "Up to 100 comma-separated product identifiers of any type: UPC, EAN, ISBN, GTIN, Amazon ASIN, model number, MPN, product URL at any retailer (URL-encoded), product name, or ShopSavvy product ID. Identifiers that match nothing are left out of `data`; use each product's `match.identifier` to line results up with your request."
                },
                {
                  "key": "schedule",
                  "value": "hourly",
                  "description": ""
                },
                {
                  "key": "retailer",
                  "value": "bestbuy.com",
                  "description": "Only this retailer, as a domain such as `bestbuy.com` or `amazon.com`.",
                  "disabled": true
                }
              ]
            },
            "description": "Schedules products to be re-checked hourly, daily or weekly at the retailers ShopSavvy can re-check through an official retailer API (Amazon for products with an ASIN, Best Buy for products with a Best Buy SKU). Offers at other retailers keep updating as ShopSavvy sees them. Scheduling a product again updates its schedule in place. Read the results with `GET /products/offers`."
          }
        },
        {
          "name": "Remove products from the schedule",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/products/scheduled?ids=611247373064,B07GV2S1GS",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "products",
                "scheduled"
              ],
              "query": [
                {
                  "key": "ids",
                  "value": "611247373064,B07GV2S1GS",
                  "description": "Up to 100 comma-separated product identifiers of any type: UPC, EAN, ISBN, GTIN, Amazon ASIN, model number, MPN, product URL at any retailer (URL-encoded), product name, or ShopSavvy product ID. Identifiers that match nothing are left out of `data`; use each product's `match.identifier` to line results up with your request."
                }
              ]
            },
            "description": "Stops scheduled refreshes for the given products. Their existing offers stay available."
          }
        }
      ]
    },
    {
      "name": "batch",
      "item": [
        {
          "name": "Poll batch job status",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/batch/:batchId",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "batch",
                ":batchId"
              ],
              "variable": [
                {
                  "key": "batchId",
                  "value": "",
                  "description": "The `batch.id` from `POST /products/batch`."
                }
              ]
            },
            "description": "Returns the job's progress until `batch.status` is `completed`, then the full `results` and `summary`. A failed job has `batch.status` `failed` and an `error` message."
          }
        }
      ]
    },
    {
      "name": "deals",
      "item": [
        {
          "name": "Browse shopping deals",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/deals",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "deals"
              ],
              "query": [
                {
                  "key": "sort",
                  "value": "hot",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "offset",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "category",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "retailer",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "grade",
                  "value": "A",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "min_price",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "max_price",
                  "value": "",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "format",
                  "value": "json",
                  "description": "`csv` returns a flattened CSV file instead of JSON.",
                  "disabled": true
                }
              ]
            },
            "description": "Returns current deals with expert grades (A+ through F), community votes, retailer and pricing, sorted hot/new/top and filterable by category, retailer, price and grade. Page through the feed with `limit` and `offset`."
          }
        }
      ]
    },
    {
      "name": "webhooks",
      "item": [
        {
          "name": "List webhooks",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/webhooks",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhooks"
              ]
            },
            "description": "Returns your registered webhooks with their events, whether they are active, when they last fired and their failure counts. The signing secret is not included; it is shown once, on creation."
          }
        },
        {
          "name": "Create a webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhooks",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhooks"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://your-app.example.com/webhooks/shopsavvy\",\n  \"events\": [\n    \"price_drop\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Registers an HTTPS URL to receive signed POSTs for price drops, availability changes and completed scheduled refreshes. The response includes the signing `secret`, shown once. Up to 5 webhooks per account."
          }
        },
        {
          "name": "Update a webhook",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/webhooks/:webhookId",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhooks",
                ":webhookId"
              ],
              "variable": [
                {
                  "key": "webhookId",
                  "value": "",
                  "description": "The webhook id returned by `POST /webhooks` or `GET /webhooks`."
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://your-app.example.com/webhooks/shopsavvy\",\n  \"events\": [\n    \"price_drop\"\n  ],\n  \"is_active\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Changes a webhook's URL, event list or `is_active` flag without deleting it, so its signing secret is kept. Omitted fields are left unchanged; re-enabling resets the failure counter."
          }
        },
        {
          "name": "Delete a webhook",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/webhooks/:webhookId",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhooks",
                ":webhookId"
              ],
              "variable": [
                {
                  "key": "webhookId",
                  "value": "",
                  "description": "The webhook id returned by `POST /webhooks` or `GET /webhooks`."
                }
              ]
            },
            "description": "Permanently removes a webhook and its delivery history. To pause deliveries and keep the signing secret, set `is_active` to false with `PUT /webhooks/{webhookId}` instead."
          }
        },
        {
          "name": "Send a test webhook",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/webhooks/:webhookId/test",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "webhooks",
                ":webhookId",
                "test"
              ],
              "variable": [
                {
                  "key": "webhookId",
                  "value": "",
                  "description": "The webhook id returned by `POST /webhooks` or `GET /webhooks`."
                }
              ]
            },
            "description": "Sends a signed test event to the webhook's URL right away and reports whether your server accepted it. Use it to check your endpoint and signature verification before real events arrive."
          }
        }
      ]
    },
    {
      "name": "usage",
      "item": [
        {
          "name": "Get API usage statistics",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/usage",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "usage"
              ]
            },
            "description": "Returns credits used and remaining, requests made and subscription status for the current billing period. The same remaining-credit count is in `meta.credits_remaining` on every response."
          }
        }
      ]
    }
  ]
}
