# ShopSavvy Data API - Documentation

> Complete developer guide for the ShopSavvy Data API

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

---

## Table of Contents

- [Getting Started](#getting-started)
  - [Overview & Authentication](#overview--authentication)
  - [Quick Start Guide](#quick-start-guide)
  - [Pricing & Credits](#pricing--credits)
- [SDKs & Libraries](#sdks--libraries)
  - [TypeScript/JavaScript](#typescriptjavascript-sdk)
  - [Python](#python-sdk)
  - [Ruby](#ruby-sdk)
  - [Go](#go-sdk)
  - [Java](#java-sdk)
  - [PHP](#php-sdk)
  - [C#](#c-sdk)
  - [Rust](#rust-sdk)
  - [Swift](#swift-sdk)
  - [Kotlin](#kotlin-sdk)
  - [SDK Comparison](#sdk-comparison)
- [AI Integration](#ai-integration)
  - [Model Context Protocol Server](#model-context-protocol-server)
  - [Claude Desktop Setup](#claude-desktop-setup)
  - [Usage Examples](#usage-examples)
- [Products API](#products-api)
  - [Retrieving Product Details](#retrieving-product-details)
  - [Product Details in CSV Format](#retrieving-product-details-in-csv-format)
  - [Searching Products by Keyword](#searching-products-by-keyword)
- [Batch API](#batch-api)
  - [Batch Product Lookup](#batch-product-lookup)
- [Pricing API](#pricing-api)
  - [Offers at All Retailers](#retrieving-offers-for-products-at-all-retailers)
  - [Offers at a Single Retailer](#retrieving-offers-for-a-single-retailer)
  - [Offers in CSV Format](#retrieving-offers-in-csv-format)
  - [Price History](#retrieving-offers-with-historical-offer-data)
- [Scheduling API](#scheduling-api)
  - [Schedule Monitoring](#enabling-scheduled-refreshes-for-products)
  - [Update Schedule](#changing-refresh-schedule-for-products)
  - [Remove Monitoring](#disabling-scheduled-refreshes-for-products)
  - [View Scheduled Products](#retrieve-products-currently-enabled-for-scheduled-refreshes)
- [Deals API](#deals-api)
  - [Browse Deals](#browse-deals)
- [Reviews API](#reviews-api)
  - [Get TLDR Review](#get-tldr-review-for-product)
- [Webhooks](#webhooks)
  - [Create Webhook](#create-webhook)
  - [List Webhooks](#list-webhooks)
  - [Test Webhook](#test-webhook)
  - [Delete Webhook](#delete-webhook)
- [Analytics & Tools](#analytics--tools)
  - [Usage Statistics](#get-api-usage-statistics)
  - [CSV Request Builder](#csv-to-api-request-converter)
  - [Rate Limits](#rate-limits)

---

## Getting Started

### Overview & Authentication

- First you'll need to [subscribe to one of our plans](https://shopsavvy.com/data#pricing).
- Once you've subscribed, you'll be redirected to your [Data API Dashboard](https://shopsavvy.com/data/dashboard).
- Go to [API Keys](https://shopsavvy.com/data/api-keys) to create and manage your API keys.
- Use your API keys to authenticate with the API.

**Base URL:** `https://api.shopsavvy.com/v1`

**Authentication:** Include your API key in the `Authorization` header as a Bearer token, or as an `api_key` query parameter.

**Authentication Examples:**

**Header (Recommended):**
```
Authorization: Bearer ss_live_abc123...
```

**Query Parameter:**
```
GET /v1/products?ids=123&api_key=ss_live_abc123...
```

That's it. You're now ready to start requesting data from the API.

### Quick Start Guide

Get up and running with the ShopSavvy Data API in minutes.

#### 1. Get Your API Key

1. Visit [shopsavvy.com/data](https://shopsavvy.com/data)
2. Sign up for an account
3. Choose a subscription plan
4. Get your API key from the dashboard

#### 2. Make Your First Request

Try looking up a product by barcode:

```bash
curl -X GET "https://api.shopsavvy.com/v1/products?ids=012345678901" \
  -H "Authorization: Bearer ss_live_your_api_key_here"
```

#### 3. Use an SDK (Recommended)

For easier integration, use one of our official SDKs:

| Language | Install Command |
|----------|----------------|
| TypeScript/JavaScript | `npm install @shopsavvy/sdk` |
| Python | `pip install shopsavvy-sdk` |
| Ruby | `gem install shopsavvy-sdk` |

### Pricing & Credits

The ShopSavvy Data API uses a credit-based pricing system. Different operations cost different amounts of credits.

#### Credit Costs

| Operation | Cost |
|-----------|------|
| Retrieving Product Details | 1 credit per product |
| Searching Products by Keyword | 1 credit per product returned |
| Current Offers (All Retailers) | 3 credits per product |
| Current Offers (Single Retailer) | 2 credits per product |
| Price History | Offer cost + 1 credit per day |
| Schedule Product Monitoring | 1 credit + 3 credits per refresh |
| Browse Deals | 1 credit per 10 deals returned |
| TLDR Product Review | 1 credit per product |
| Batch Product Lookup | 1 credit per product found (+ 3 if including offers, + 1 if including reviews) |

#### Subscription Plans

Visit the [pricing page](https://shopsavvy.com/data#pricing) to see current subscription plans and credit allocations.

---

## SDKs & Libraries

### TypeScript/JavaScript SDK

Our official TypeScript/JavaScript SDK provides a convenient way to interact with the ShopSavvy Data API from Node.js and browser environments.

- [View on GitHub](https://github.com/shopsavvy/sdk-typescript)
- [View on npm](https://www.npmjs.com/package/@shopsavvy/sdk)

#### Installation

```bash
npm install @shopsavvy/sdk
# or
yarn add @shopsavvy/data-api
# or
bun add @shopsavvy/data-api
```

#### Basic Usage

```typescript
import { createShopSavvyClient } from '@shopsavvy/data-api'

// Initialize the client
const api = createShopSavvyClient({
  apiKey: 'ss_live_your_api_key_here'
})

// Look up a product by barcode
const product = await api.getProductDetails('012345678901')
console.log(product.data.name)

// Get current prices from all retailers
const offers = await api.getCurrentOffers('012345678901')
offers.data.forEach(offer => {
  console.log(`${offer.retailer}: $${offer.price}`)
})

// Get price history
const history = await api.getPriceHistory(
  '012345678901',
  '2024-01-01',
  '2024-01-31'
)
```

#### Features

- Full TypeScript support with comprehensive type definitions
- Modern async/await API
- Automatic error handling and retry logic
- Support for both Node.js and browser environments
- Built-in request/response validation
- Comprehensive documentation and examples

#### Error Handling

```typescript
try {
  const product = await api.getProductDetails('invalid-identifier')
} catch (error) {
  if (error.message.includes('Product not found')) {
    console.log('Product does not exist')
  } else if (error.message.includes('Invalid API key')) {
    console.log('Check your API key')
  } else {
    console.log('Unexpected error:', error.message)
  }
}
```

### Python SDK

Our official Python SDK provides a convenient way to interact with the ShopSavvy Data API from Python applications with full type safety and modern async support.

- [View on GitHub](https://github.com/shopsavvy/sdk-python)
- [View on PyPI](https://pypi.org/project/shopsavvy-sdk/)

#### Installation

```bash
pip install shopsavvy-data-api
```

#### Basic Usage

```python
from shopsavvy import create_client

# Initialize the client
client = create_client("ss_live_your_api_key_here")

# Look up a product by barcode
product = client.get_product_details("012345678901")
print(product.data.name)

# Get current prices from all retailers
offers = client.get_current_offers("012345678901")
for offer in offers.data:
    print(f"{offer.retailer}: {offer.price}")

# Get price history
history = client.get_price_history(
    "012345678901",
    "2024-01-01",
    "2024-01-31"
)
```

#### Features

- Full type safety with Pydantic models
- Modern HTTP client with automatic retries
- Comprehensive error handling
- Rails integration support
- Context manager support for automatic cleanup
- Python 2.7+ compatibility

#### Context Manager Usage

```python
with create_client("ss_live_your_api_key_here") as client:
    product = client.get_product_details("012345678901")
    print(product.data.name)
# Client automatically closed
```

#### Error Handling

```python
from shopsavvy import create_client, NotFoundError, AuthenticationError

try:
    client = create_client("ss_live_your_api_key_here")
    product = client.get_product_details("invalid-identifier")
except NotFoundError:
    print("Product not found")
except AuthenticationError:
    print("Invalid API key")
except Exception as e:
    print(f"Unexpected error: {e}")
```

### Ruby SDK

Our official Ruby SDK provides a convenient way to interact with the ShopSavvy Data API from Ruby applications with idiomatic Ruby patterns and comprehensive documentation.

- [View on GitHub](https://github.com/shopsavvy/sdk-ruby)
- [View on RubyGems](https://rubygems.org/gems/shopsavvy-sdk)

#### Installation

```bash
gem install shopsavvy-sdk

# Or add to your Gemfile:
gem 'shopsavvy-sdk'
```

#### Basic Usage

```ruby
require 'shopsavvy_data_api'

# Initialize the client
client = ShopsavvyDataApi.new(api_key: "ss_live_your_api_key_here")

# Look up a product by barcode
product = client.get_product_details("012345678901")
puts product.data.name

# Get current prices from all retailers
offers = client.get_current_offers("012345678901")
offers.data.each do |offer|
  puts "#{offer.retailer}: $#{offer.price}"
end

# Get price history
history = client.get_price_history(
  "012345678901",
  "2024-01-01",
  "2024-01-31"
)
```

#### Features

- Idiomatic Ruby patterns and conventions
- Comprehensive YARD documentation
- Automatic retry logic with exponential backoff
- Convenient model methods and helpers
- Rails integration examples
- Ruby 2.7+ compatibility

#### Rails Integration

```ruby
# config/initializers/shopsavvy.rb
Rails.application.config.shopsavvy_client = ShopsavvyDataApi.new(
  api_key: Rails.application.credentials.shopsavvy_api_key
)

# In your models/controllers
client = Rails.application.config.shopsavvy_client
product = client.get_product_details(params[:barcode])
```

#### Error Handling

```ruby
begin
  client = ShopsavvyDataApi.new(api_key: "ss_live_your_api_key_here")
  product = client.get_product_details("invalid-identifier")
rescue ShopsavvyDataApi::NotFoundError => e
  puts "Product not found"
rescue ShopsavvyDataApi::AuthenticationError => e
  puts "Invalid API key"
rescue ShopsavvyDataApi::RateLimitError => e
  puts "Rate limit exceeded"
rescue ShopsavvyDataApi::APIError => e
  puts "API error: #{e.message}"
end
```

### Go SDK

Our official Go SDK provides a fast, type-safe way to interact with the ShopSavvy Data API from Go applications.

- [View on GitHub](https://github.com/shopsavvy/go-sdk)
- [View Docs on pkg.go.dev](https://pkg.go.dev/github.com/shopsavvy/go-sdk)

#### Installation

```bash
go get github.com/shopsavvy/go-sdk
```

#### Quick Start

```go
package main

import (
    "fmt"
    "log"

    "github.com/shopsavvy/go-sdk"
)

func main() {
    // Create a new client
    client, err := shopsavvy.NewClient("ss_live_your_api_key_here")
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Look up a product by barcode
    product, err := client.GetProductDetails("012345678901")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Product: %s\n", product.Data.Name)

    // Get current offers
    offers, err := client.GetCurrentOffers("012345678901", "")
    if err != nil {
        log.Fatal(err)
    }

    for _, offer := range offers.Data {
        fmt.Printf("%s: $%.2f\n", offer.Retailer, offer.Price)
    }
}
```

#### Features

- Full type safety with Go generics
- Comprehensive error handling with custom error types
- Context support for request cancellation
- Built-in rate limiting and retry logic
- Support for both JSON and CSV response formats
- Batch operations for multiple products

### Java SDK

Our official Java SDK provides enterprise-grade reliability and performance for Java applications.

- [View on GitHub](https://github.com/shopsavvy/java-sdk)
- [Maven Central](https://search.maven.org/artifact/com.shopsavvy/shopsavvy-sdk-java)

#### Installation

**Maven:**

```xml
<dependency>
  <groupId>com.shopsavvy</groupId>
  <artifactId>shopsavvy-sdk</artifactId>
  <version>1.0.0</version>
</dependency>
```

**Gradle:**

```groovy
implementation 'com.shopsavvy:shopsavvy-sdk:1.0.0'
```

#### Quick Start

```java
import com.shopsavvy.ShopSavvyClient;
import com.shopsavvy.model.Product;
import com.shopsavvy.model.ApiResponse;

public class Example {
    public static void main(String[] args) {
        // Create a new client
        ShopSavvyClient client = new ShopSavvyClient("ss_live_your_api_key_here");

        try {
            // Get product details
            ApiResponse<Product> response = client.getProductDetails("012345678901");
            Product product = response.getData();

            System.out.println("Product: " + product.getName());
            System.out.println("Brand: " + product.getBrand());

            // Get current offers
            var offers = client.getCurrentOffers("012345678901");
            offers.getData().forEach(offer -> {
                System.out.printf("%s: $%.2f%n",
                    offer.getRetailer(), offer.getPrice());
            });

        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}
```

#### Features

- Full Java type safety with generics
- Builder pattern for configuration
- Async support with CompletableFuture
- Spring Boot auto-configuration
- Jackson JSON serialization
- Comprehensive error handling

### PHP SDK

Our official PHP SDK provides easy integration for PHP applications and frameworks like Laravel, Symfony, and CodeIgniter.

- [View on GitHub](https://github.com/shopsavvy/php-sdk)
- [Packagist](https://packagist.org/packages/shopsavvy/sdk)

#### Installation

```bash
composer require shopsavvy/shopsavvy-sdk-php
```

#### Quick Start

```php
<?php
require_once 'vendor/autoload.php';

use ShopSavvy\Client;

// Create a new client
$client = new Client('ss_live_your_api_key_here');

// Get product details
$product = $client->getProductDetails('012345678901');
echo "Product: " . $product['data']['name'] . "\n";

// Get current offers
$offers = $client->getCurrentOffers('012345678901');
foreach ($offers['data'] as $offer) {
    echo $offer['retailer'] . ": $" . $offer['price'] . "\n";
}

// Get price history
$history = $client->getPriceHistory(
    '012345678901',
    '2024-01-01',
    '2024-01-31'
);
```

#### Laravel Integration

```php
// config/services.php
'shopsavvy' => [
    'api_key' => env('SHOPSAVVY_API_KEY'),
],

// In your controller
use ShopSavvy\Client;

class ProductController extends Controller
{
    public function show($barcode)
    {
        $client = new Client(config('services.shopsavvy.api_key'));
        $product = $client->getProductDetails($barcode);

        return view('product.show', compact('product'));
    }
}
```

#### Features

- PSR-4 autoloading
- Laravel service provider
- Guzzle HTTP client
- Comprehensive error handling
- Support for PHP 8.0+
- Full PHPDoc documentation

### C# SDK

Our official C# SDK provides seamless integration for .NET applications, with full async/await support and strong typing.

- [View on GitHub](https://github.com/shopsavvy/csharp-sdk)
- [NuGet](https://www.nuget.org/packages/ShopSavvy.SDK/)

#### Installation

```bash
dotnet add package ShopSavvy.SDK
```

#### Quick Start

```csharp
using ShopSavvy;

// Create a new client
var client = new ShopSavvyClient("ss_live_your_api_key_here");

// Get product details
var product = await client.GetProductDetailsAsync("012345678901");
Console.WriteLine($"Product: {product.Data.Name}");

// Get current offers
var offers = await client.GetCurrentOffersAsync("012345678901");
foreach (var offer in offers.Data)
{
    Console.WriteLine($"{offer.Retailer}: ${offer.Price:F2}");
}

// Get price history
var history = await client.GetPriceHistoryAsync(
    "012345678901",
    new DateTime(2024, 1, 1),
    new DateTime(2024, 1, 31)
);
```

#### Dependency Injection

```csharp
// Program.cs or Startup.cs
services.AddShopSavvy(options =>
{
    options.ApiKey = Configuration["ShopSavvy:ApiKey"];
    options.BaseUrl = "https://api.shopsavvy.com/v1";
});

// In your controller
[ApiController]
public class ProductsController : ControllerBase
{
    private readonly IShopSavvyClient _client;

    public ProductsController(IShopSavvyClient client)
    {
        _client = client;
    }

    [HttpGet("{barcode}")]
    public async Task<IActionResult> GetProduct(string barcode)
    {
        var product = await _client.GetProductDetailsAsync(barcode);
        return Ok(product);
    }
}
```

#### Features

- Full async/await support
- Strong typing with C# models
- Dependency injection support
- ConfigureAwait(false) for library code
- Custom exception types
- Support for .NET 6+

### Rust SDK

Our official Rust SDK provides memory-safe, high-performance access to the ShopSavvy Data API with full type safety.

- [View on GitHub](https://github.com/shopsavvy/rust-sdk)
- [Crates.io](https://crates.io/crates/shopsavvy)

#### Installation

```toml
[dependencies]
shopsavvy = "1.0.0"
tokio = { version = "1.0", features = ["full"] }
```

#### Quick Start

```rust
use shopsavvy::{Client, Result};

#[tokio::main]
async fn main() -> Result<()> {
    // Create a new client
    let client = Client::new("ss_live_your_api_key_here")?;

    // Get product details
    let product = client.get_product_details("012345678901").await?;
    println!("Product: {}", product.data.name);

    // Get current offers
    let offers = client.get_current_offers("012345678901", None).await?;
    for offer in offers.data {
        println!("{}: ${:.2}", offer.retailer, offer.price);
    }

    // Get price history
    let history = client.get_price_history(
        "012345678901",
        "2024-01-01",
        "2024-01-31",
        None
    ).await?;

    Ok(())
}
```

#### Error Handling

```rust
use shopsavvy::{Client, Error};

match client.get_product_details("invalid-id").await {
    Ok(product) => println!("Found: {}", product.data.name),
    Err(Error::NotFound) => println!("Product not found"),
    Err(Error::RateLimit) => println!("Rate limit exceeded"),
    Err(Error::Authentication) => println!("Invalid API key"),
    Err(e) => println!("Other error: {}", e),
}
```

#### Features

- Memory safe with zero-cost abstractions
- Full async/await support with tokio
- Strongly typed with serde serialization
- Comprehensive error handling
- Built-in rate limiting
- Support for Rust 1.70+

### Swift SDK

Our official Swift SDK provides native iOS and macOS integration with modern Swift concurrency and SwiftUI support.

- [View on GitHub](https://github.com/shopsavvy/swift-sdk)

#### Installation

Swift Package Manager:

```swift
.package(url: "https://github.com/shopsavvy/swift-sdk.git", from: "1.0.0")
```

#### Quick Start

```swift
import ShopSavvy

// Create a new client
let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")

// Get product details
do {
    let product = try await client.getProductDetails("012345678901")
    print("Product: \(product.data.name)")

    // Get current offers
    let offers = try await client.getCurrentOffers("012345678901")
    for offer in offers.data {
        print("\(offer.retailer): $\(offer.price, specifier: "%.2f")")
    }

    // Get price history
    let history = try await client.getPriceHistory(
        "012345678901",
        startDate: "2024-01-01",
        endDate: "2024-01-31"
    )

} catch {
    print("Error: \(error)")
}
```

#### SwiftUI Integration

```swift
struct ProductView: View {
    @State private var product: Product?
    @State private var offers: [Offer] = []

    let barcode: String
    let client = ShopSavvyClient(apiKey: "your_api_key")

    var body: some View {
        VStack {
            if let product = product {
                Text(product.name)
                    .font(.title)

                LazyVStack {
                    ForEach(offers, id: \.id) { offer in
                        HStack {
                            Text(offer.retailer)
                            Spacer()
                            Text("$\(offer.price, specifier: "%.2f")")
                        }
                    }
                }
            }
        }
        .task {
            await loadProduct()
        }
    }

    private func loadProduct() async {
        do {
            let productResponse = try await client.getProductDetails(barcode)
            let offersResponse = try await client.getCurrentOffers(barcode)

            await MainActor.run {
                self.product = productResponse.data
                self.offers = offersResponse.data
            }
        } catch {
            print("Error loading product: \(error)")
        }
    }
}
```

#### Features

- Modern Swift concurrency (async/await)
- SwiftUI and UIKit support
- Codable models for type safety
- iOS 15+ and macOS 12+ support
- Built-in error handling
- Network layer with URLSession

### Kotlin SDK

Our official Kotlin SDK provides native Android integration with coroutines support and modern Kotlin idioms.

- [View on GitHub](https://github.com/shopsavvy/kotlin-sdk)
- [Maven Central](https://search.maven.org/artifact/com.shopsavvy/shopsavvy-sdk-kotlin)

#### Installation

```kotlin
// build.gradle.kts
dependencies {
    implementation("com.shopsavvy:shopsavvy-sdk-kotlin:1.0.0")
}
```

#### Quick Start

```kotlin
import com.shopsavvy.sdk.*
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    // Create a new client
    val client = ShopSavvyClient("ss_live_your_api_key_here")

    try {
        // Get product details
        val product = client.getProductDetails("012345678901")
        println("Product: ${product.data.name}")

        // Get current offers
        val offers = client.getCurrentOffers("012345678901")
        offers.data.forEach { offer ->
            println("${offer.retailer}: $${offer.price}")
        }

        // Get price history
        val history = client.getPriceHistory(
            "012345678901",
            "2024-01-01",
            "2024-01-31"
        )

    } catch (e: Exception) {
        println("Error: ${e.message}")
    }
}
```

#### Android Integration

```kotlin
class ProductRepository(private val client: ShopSavvyClient) {

    suspend fun getProduct(barcode: String): Result<Product> =
        try {
            val response = client.getProductDetails(barcode)
            Result.success(response.data)
        } catch (e: Exception) {
            Result.failure(e)
        }
}

// In your ViewModel
class ProductViewModel(
    private val repository: ProductRepository
) : ViewModel() {

    private val _product = MutableLiveData<Product?>()
    val product: LiveData<Product?> = _product

    fun loadProduct(barcode: String) {
        viewModelScope.launch {
            repository.getProduct(barcode)
                .onSuccess { _product.value = it }
                .onFailure { /* handle error */ }
        }
    }
}
```

#### Features

- Full coroutines support
- Null safety with Kotlin types
- Android lifecycle awareness
- OkHttp-based HTTP client
- Serialization with kotlinx.serialization
- Support for Android API 21+

### SDK Comparison

Choose the right SDK for your technology stack. All SDKs provide the same comprehensive API coverage with language-specific optimizations.

| Feature | TypeScript/JavaScript | Python | Ruby |
|---------|----------------------|--------|------|
| Package Manager | npm, yarn, bun | pip | gem, bundler |
| Type Safety | Full TypeScript | Pydantic models | Runtime validation |
| Async Support | Native async/await | Sync + async variants | Sync only |
| Environment | Node.js, Browser | Python 3.8+ | Ruby 2.7+ |
| Error Handling | Comprehensive | Exception hierarchy | Custom error classes |
| Framework Integration | React, Next.js, Express | Django, FastAPI, Flask | Rails, Sinatra |
| Documentation | TSDoc + examples | Google-style + Sphinx | YARD + examples |

#### Quick Installation Comparison

| SDK | Install | Best For |
|-----|---------|----------|
| TypeScript/JavaScript | `npm install @shopsavvy/sdk` | Frontend apps, Node.js services, full-stack applications |
| Python | `pip install shopsavvy-data-api` | Data science, ML pipelines, Django/FastAPI apps |
| Ruby | `gem install shopsavvy_data_api` | Rails applications, Ruby scripts, background jobs |
| Go | `go get github.com/shopsavvy/go-sdk` | High-performance services, microservices |
| Java | `com.shopsavvy:shopsavvy-sdk:1.0.0` (Maven/Gradle) | Enterprise Java apps, Spring Boot |
| PHP | `composer require shopsavvy/shopsavvy-sdk-php` | Laravel, Symfony, PHP web apps |
| C# | `dotnet add package ShopSavvy.SDK` | .NET applications, ASP.NET |
| Rust | `shopsavvy = "1.0.0"` (Cargo) | Systems programming, high-performance |
| Swift | SPM: `https://github.com/shopsavvy/swift-sdk.git` | iOS, macOS native apps |
| Kotlin | `com.shopsavvy:shopsavvy-sdk-kotlin:1.0.0` (Gradle) | Android apps, Kotlin services |

#### When to Use Each SDK

**Choose TypeScript/JavaScript if:**
- Building web applications or Node.js services
- Need browser compatibility
- Want the best type safety and IDE support
- Using modern JavaScript frameworks

**Choose Python if:**
- Building data analysis or ML applications
- Need both sync and async support
- Want comprehensive type validation
- Using Django, FastAPI, or Flask

**Choose Ruby if:**
- Building Rails applications
- Want idiomatic Ruby patterns
- Need excellent Rails integration
- Prefer Ruby's expressive syntax

---

## AI Integration

### Model Context Protocol Server

Connect AI assistants directly to ShopSavvy's product database. The open-source MCP server enables Claude Desktop, Cursor, and other AI assistants to access product lookups, pricing data, and price history through natural conversation.

- [View on GitHub](https://github.com/shopsavvy/shopsavvy-mcp-server)
- [Learn about MCP](https://modelcontextprotocol.io)

### Claude Desktop Setup

#### 1. Install the MCP Server

```bash
npm install -g shopsavvy-data-api-mcp
```

#### 2. Configure Claude Desktop

Add to your Claude Desktop config file:

```json
{
  "mcpServers": {
    "shopsavvy-data-api": {
      "command": "npx",
      "args": ["shopsavvy-data-api-mcp"],
      "env": {
        "SHOPSAVVY_API_KEY": "ss_live_your_key_here"
      }
    }
  }
}
```

#### 3. Get Your API Key

- [Subscribe to a Plan](https://shopsavvy.com/data#pricing)
- [Create API Key](https://shopsavvy.com/data/dashboard)

### Available AI Tools

| Tool | Description |
|------|-------------|
| Product Lookup | Find products by barcode, ASIN, URL, or model number |
| Current Pricing | Get offers from all retailers or specific stores |
| Price History | Historical pricing data with custom date ranges |
| Price Monitoring | Schedule automatic price tracking |
| Usage Analytics | Track API usage and credit consumption |

### Usage Examples

**Product Research:**
- "Look up the product with barcode 012345678901"
- "Find product information for ASIN B08N5WRWNW"
- "Get details for this Amazon URL: https://amazon.com/dp/B08N5WRWNW"

**Price Comparison:**
- "Show me current prices for ASIN B08N5WRWNW from all retailers"
- "Get Amazon prices for product 012345678901"
- "Compare Best Buy and Target prices for this product"

**Price History:**
- "Get price history for B08N5WRWNW from January 1-31, 2024"
- "Show me price trends for the last 3 months"
- "What were Amazon's prices for this product in December?"

**Price Monitoring:**
- "Schedule daily price monitoring for these products"
- "Set up hourly monitoring for ASIN B08N5WRWNW"
- "Show me all my scheduled products"

### Advanced Features

- **Open Source** - MIT licensed and available on GitHub for customization and contributions.
- **Easy Integration** - Works with Claude Desktop, Cursor, and any MCP-compatible AI assistant.
- **Batch Operations** - Look up multiple products, compare prices across retailers, and manage large product catalogs efficiently.
- **Usage Tracking** - Built-in usage analytics help you monitor API consumption and optimize your credit usage.

**Credit Usage:** The MCP server uses the same credit system as the REST API. Each AI tool interaction consumes credits based on the data requested.

---

## Products API

### Retrieving Product Details

**Cost:** 1 credit per product requested.

You can retrieve product details by using the `GET /products?ids={identifiers}` endpoint.

The `identifiers` parameter can be a comma-separated list of **one** or **more** identifiers. You can mix and match any combination of different identifiers, like `GET /products?ids=B07G14HTBZ,611247369449,3ONn300xybP3y66ibqc1`.

An identifier can be any of the following:

- UPC
- EAN
- ISBN
- GTIN
- Amazon ASIN
- Model Number
- Product Name
- URL at any Retailer
- ShopSavvy Product ID

#### Examples

**Example with barcodes:**

```bash
curl -X GET "https://api.shopsavvy.com/v1/products?ids=611247373064,611247369449" \
  -H "Authorization: Bearer ss_live_your_api_key_here"
```

**Example with product name:**

```bash
curl -X GET "https://api.shopsavvy.com/v1/products?ids=iPhone%2015%20Pro" \
  -H "Authorization: Bearer ss_live_your_api_key_here"
```

**Note:** When using a product name, the API uses full-text search to find the best matching product based on relevance and offer availability.

#### Response Format

The response will be a JSON object with success status, data array, and metadata including credits used.

Products will each have the following fields. (Note: not all fields are available on all products).

| Field | Description |
|-------|-------------|
| `title` | The name of the product. |
| `title_short` | A shorter, human-friendly version of the title (when available). |
| `slug` | URL-friendly slug for the product. |
| `category` | A comma separated list of categories for the product. |
| `brand` | The brand of the product. |
| `color` | The color of the product. |
| `model` | The model of the product. |
| `shopsavvy` | The ShopSavvy Product ID of the product. This can optionally be used alongside any other identifier when retrieving products, offers, etc. |
| `barcode` | The barcode of the product. Will always be a number. |
| `amazon` | The Amazon ASIN of the product. |
| `mpn` | The manufacturer's part number of the product. |
| `images` | An array of image URLs pointing to images of the product. |
| `identifiers` | All known identifiers for the product (barcode, amazon, walmart, bestbuy, newegg, etc.). |
| `description` | Product description text (single best available description). |
| `categories` | Array of category path strings. |
| `attributes` | Product specifications as a flat object (e.g., `{"Color": "Black", "Weight": "250g"}`). |
| `rating` | Aggregated customer rating with `value` (out of 5) and `count` (total reviews). |
| `score` | Expert quality scores: `overall`, `customer`, `professional`, `value`, `features`, `reliability` (all on a 0-100 scale, only populated fields included). |
| `keywords` | Array of relevant search keywords for the product. |

All response `meta` objects now include a `request_id` field — a unique identifier for every API request. Include this in any support inquiries.

**Error Responses** include both a human-readable `error` string and a structured `error_detail` object with `code`, `message`, `action` (what to do), and `docs_url` (link to relevant documentation).

#### Example Response

```json
{
  "success": true,
  "data": [
    {
      "title": "Keurig K-Mini Single Serve Coffee Maker, Black",
      "category": "Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",
      "brand": "Keurig",
      "color": "Black",
      "model": "K-MINI",
      "shopsavvy": "products/3ONn300xybP3y66ibqc1",
      "barcode": 611247373064,
      "amazon": "B07G14HTBZ",
      "mpn": "5000200237",
      "images": [
        "https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/411uxu%2Bg17L.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/41jEx1YoTQL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/41CanelWIlL.jpg"
      ]
    },
    {
      "title": "Keurig K-Elite Single Serve K-Cup Pod Maker with Strength and Temperature Control, Iced Coffee Capability, 12oz Brew Size, Brushed Silver",
      "category": "Home & Kitchen > Kitchen & Dining > Coffee, Tea & Espresso > Coffee Makers > Single-Serve Brewers",
      "brand": "Keurig",
      "color": "Silver",
      "model": "K-Elite",
      "shopsavvy": "products/DrKWneG0MpFlZpwZXNYa",
      "barcode": 611247369449,
      "amazon": "B0788F3R8X",
      "mpn": "5000197492",
      "images": [
        "https://images-na.ssl-images-amazon.com/images/I/411fEW99TlL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/51bdqFw6lNL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/51-NbDX9S7L.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/412o2pQ-swL.jpg"
      ]
    }
  ],
  "meta": {
    "credits_used": 2,
    "credits_remaining": 998,
    "rate_limit_remaining": 58
  }
}
```

### Retrieving Product Details in CSV Format

**Cost:** 1 credit per product requested.

By default all responses are in JSON format, but you can also retrieve products in CSV format by adding `?format=csv` to the request:

```
GET /products?ids=611247373064,611247369449&format=csv
```

When you do this, the response will be formatted as a CSV file, with columns for each of the different fields, and each product on its own row:

```csv
shopsavvy,barcode,amazon,title,category,brand,color,mpn,model,image
3ONn300xybP3y66ibqc1,611247373064,B07G14HTBZ,"Keurig K-Mini Single Serve Coffee Maker, Black","Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",Keurig,Black,5000200237,K-MINI,https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg
DrKWneG0MpFlZpwZXNYa,611247369449,B0788F3R8X,"Keurig K-Elite Single Serve K-Cup Pod Maker with with Strength and Temperature Control, Iced Coffee Capability, 12oz Brew Size, Brushed Silver","Home & Kitchen > Kitchen & Dining > Coffee, Tea & Espresso > Coffee Makers > Single-Serve Brewers",Keurig,Silver,5000197492,K-Elite,https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/411fEW99TlL.jpg
```

### Searching Products by Keyword

**Cost:** 1 credit per product returned.

You can search for products by keyword using the `GET /products/search?q={query}` endpoint.

This endpoint uses PostgreSQL full-text search to find products matching your search query. Results are ranked by a composite score that combines:

- **Text Relevance (70%)**: How well the product title, brand, and model match your search query
- **Offer Count (25%)**: Products with more current offers are ranked higher (indicates active products)
- **Recency (5%)**: Recently updated products are slightly preferred

#### Query Parameters

| Parameter | Required | Description |
|-----------|----------|-------------|
| `q` | Yes | Search query or keyword (e.g., "iphone 15 pro", "samsung tv", "nike shoes") |
| `limit` | No | Maximum number of results to return (default: 20, max: 100) |
| `offset` | No | Offset for pagination (default: 0) |

#### Example Request

```bash
curl -X GET "https://api.shopsavvy.com/v1/products/search?q=iphone%2015%20pro&limit=10" \
  -H "Authorization: Bearer ss_live_your_api_key_here"
```

#### Example Response

```json
{
  "success": true,
  "data": [
    {
      "title": "Apple iPhone 15 Pro Max 256GB - Natural Titanium",
      "category": "Cell Phones & Accessories > Cell Phones > Smartphones",
      "brand": "Apple",
      "color": "Natural Titanium",
      "model": "iPhone 15 Pro Max",
      "shopsavvy": "products/abc123xyz",
      "barcode": 195949038674,
      "amazon": "B0CHX3TZ7R",
      "mpn": "MU773LL/A",
      "images": [
        "https://images-na.ssl-images-amazon.com/images/I/41BvSLn90ML.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/51ckLKbsOsL.jpg"
      ]
    },
    {
      "title": "Apple iPhone 15 Pro 128GB - Blue Titanium",
      "category": "Cell Phones & Accessories > Cell Phones > Smartphones",
      "brand": "Apple",
      "color": "Blue Titanium",
      "model": "iPhone 15 Pro",
      "shopsavvy": "products/def456uvw",
      "barcode": 195949037894,
      "amazon": "B0CHX1W1XY",
      "mpn": "MTUX3LL/A",
      "images": [
        "https://images-na.ssl-images-amazon.com/images/I/41m9Pq3ScgL.jpg"
      ]
    }
  ],
  "pagination": {
    "total": 47,
    "limit": 10,
    "offset": 0,
    "returned": 2
  },
  "meta": {
    "credits_used": 2,
    "credits_remaining": 998,
    "rate_limit_remaining": 58
  }
}
```

#### Use Cases

- **Autocomplete / Search Suggestions**: Use with a low limit (e.g., 5-10) to show real-time search results as users type
- **Category Browsing**: Search for broad categories like "gaming laptops" or "bluetooth speakers"
- **Product Discovery**: Find products when you don't have a specific identifier like a barcode or ASIN
- **Fuzzy Matching**: The full-text search handles typos and variations in product names

**Note:** Once you have a product from search results, you can use its `shopsavvy` ID, `barcode`, or `amazon` ASIN with the other endpoints like `GET /products/offers` to retrieve pricing data.

---

## Batch API

### Batch Product Lookup

Look up multiple products at once. For small batches (up to 20 identifiers), results are returned immediately. For larger batches (21-100), processing happens asynchronously — you receive a batch ID and poll for results.

**Endpoint:** `POST /v1/products/batch`

**Credit Cost:** Same as individual lookups (1 credit per product found, + 3 per product if including offers, + 1 per product if including reviews)

**Request Body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `identifiers` | string[] | Yes | Array of product identifiers (1-100). Supports barcodes, ASINs, URLs, model numbers. |
| `include` | string[] | No | Additional data to fetch: `"offers"` and/or `"reviews"` |

**Example Request (Synchronous, <=20 identifiers):**

```bash
curl -X POST 'https://api.shopsavvy.com/v1/products/batch' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "identifiers": ["B09XS7JWHH", "B0CHX3TW6K", "027242923782"],
    "include": ["offers"]
  }'
```

**Synchronous Response (<=20 identifiers):**

```json
{
  "success": true,
  "results": [
    { "identifier": "B09XS7JWHH", "status": "found", "product": { "title": "Sony WH-1000XM5", ... }, "offers": [...] },
    { "identifier": "B0CHX3TW6K", "status": "found", "product": { "title": "iPhone 15 Pro", ... }, "offers": [...] },
    { "identifier": "INVALID123", "status": "not_found", "product": null }
  ],
  "summary": { "total": 3, "found": 2, "not_found": 1 },
  "meta": { "request_id": "abc-123", "credits_used": 8, "credits_remaining": 992 }
}
```

**Async Response (>20 identifiers):**

When submitting more than 20 identifiers, you receive a batch ID immediately:

```json
{
  "success": true,
  "batch": {
    "id": "batch_abc123def456",
    "status": "processing",
    "total": 50,
    "processed": 0,
    "poll_url": "/v1/batch/batch_abc123def456",
    "estimated_seconds": 75
  }
}
```

Poll `GET /v1/batch/{batch_id}` until `status` is `"completed"`, then the response includes the full `results` array.

---

## Pricing API

### Retrieving Offers for Products at All Retailers

**Cost:** 3 credits per product requested.

An **offer** represents a **product** being sold by a specific **retailer** or **seller** for a specific price, condition, etc.

You can retrieve offers for products by using the `GET /products/offers` endpoint. The `ids` parameter supports all identifier types including barcodes, ASINs, model numbers, URLs, and **product names**.

**Example with barcodes:**

```
GET /products/offers?ids=611247373064,611247369449
```

**Example with product name:**

```
GET /products/offers?ids=iPhone%2015%20Pro
```

**Note:** When using a product name, the API uses full-text search to find the best matching product based on relevance and offer availability, then returns offers for that product.

#### Offer Fields

This will return an array of products, each containing a new `offers` property, which will be an array of offer objects, each containing the following properties:

| Field | Description |
|-------|-------------|
| `id` | A unique identifier for this offer. |
| `availability` | The availability of the product in the offer. This will only be present if the value is confirmed and known. It will be missing if availability is unknown. Will be either `"in"` or `"out"`. |
| `condition` | The condition of the product in the offer. Will be `"new"`, `"used"`, or `"refurbished"`. |
| `retailer` | The name of the retailer or marketplace the offer is for. |
| `price` | The price of the product in the offer. Will always be a number. |
| `seller` | The name of the marketplace seller selling this product. If missing, then the offer is from a first-party retailer and there is no marketplace seller. |
| `URL` | The URL for the offer. |
| `timestamp` | An [ISO 8601](https://www.w3.org/TR/NOTE-datetime) formatted date and time representing when the offer was last seen by ShopSavvy. |

#### Example Response

```json
[
    {
      "title": "Keurig K-Mini Single Serve Coffee Maker, Black",
      "category": "Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",
      "brand": "Keurig",
      "color": "Black",
      "model": "K-MINI",
      "shopsavvy": "3ONn300xybP3y66ibqc1",
      "barcode": 611247373064,
      "amazon": "B07G14HTBZ",
      "mpn": "5000200237",
      "images": [
        "https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/411uxu%2Bg17L.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/41jEx1YoTQL.jpg",
        "https://images-na.ssl-images-amazon.com/images/I/41CanelWIlL.jpg"
      ],
      "offers": [
        {
          "id": "0IUouCFtZEhxeOablTPl",
          "availability": "in",
          "condition": "new",
          "retailer": "Amazon",
          "price": 74.96,
          "seller": "Palm Tree Deals",
          "URL": "https://www.amazon.com/dp/B07GV2S1GS?m=A1GKQADQC2VI6E",
          "timestamp": "2022-05-01T22:36:33.236Z"
        },
        {
          "id": "0RmL0ZMUesP2PmSlP97G",
          "availability": "in",
          "condition": "new",
          "retailer": "Amazon",
          "price": 58.86,
          "URL": "https://www.amazon.com/dp/B07GV2S1GS",
          "timestamp": "2022-05-03T22:52:06.802Z"
        },
        {
          "id": "0qp0KKdFnwIi3c09kGyT",
          "availability": "in",
          "condition": "new",
          "retailer": "Walmart",
          "price": 60.34,
          "URL": "https://www.walmart.com/ip/Keurig-K-Mini-Single-Serve-Coffee-Maker-Black/389238886?selectedSellerId=FBB34940E137490C8ABD825B48534874",
          "timestamp": "2022-05-01T20:38:25.218Z"
        },
        {
          "id": "2EHAxfhrvF6hEFs8IarY",
          "availability": "in",
          "condition": "new",
          "retailer": "Walmart",
          "price": 81.5,
          "seller": "Focus Camera",
          "URL": "https://www.walmart.com/ip/Keurig-K-Mini-Single-Serve-K-Cup-Pod-Coffee-Maker-6-to-12-oz-Brew-Sizes-Black/389238886?selectedSellerId=888853D0A1394FA4BB92C88C4FD20210",
          "timestamp": "2022-05-02T20:26:42.657Z"
        },
        {
          "id": "1upFPYp9qj74v8S0E7qp",
          "availability": "in",
          "condition": "refurbished",
          "retailer": "shopcheap.club",
          "price": 59.99,
          "seller": null,
          "URL": "https://shopcheap.club/kitchen-tabletop/keurig-k-mini-coffee-maker-single-serve-k-cup-pod-coffee-brewer-6-to-12-oz-brew-sizes-black/",
          "timestamp": "2022-05-03T13:49:10.053Z"
        }
      ]
    }
]
```

### Retrieving Offers for a Single Retailer

**Cost:** 2 credits per product requested.

You can retrieve offers for products at a single retailer by specifying a value for the `retailer` parameter. The value should be the domain of the retailer you want to retrieve offers for, like `amazon.com` or `bestbuy.com`.

```
GET /products/offers?ids=611247373064,611247369449&retailer=amazon.com
```

The response will be in the same format and schema, but it will only contain offers from your specified retailer.

#### Example Response

```json
[
    {
      "title": "Keurig K-Mini Single Serve Coffee Maker, Black",
      "category": "Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",
      "brand": "Keurig",
      "color": "Black",
      "model": "K-MINI",
      "shopsavvy": "3ONn300xybP3y66ibqc1",
      "barcode": 611247373064,
      "amazon": "B07G14HTBZ",
      "mpn": "5000200237",
      "images": [
        "https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg"
      ],
      "offers": [
        {
          "id": "0IUouCFtZEhxeOablTPl",
          "availability": "in",
          "condition": "new",
          "retailer": "Amazon",
          "price": 74.96,
          "seller": "ACME Deals",
          "URL": "https://www.amazon.com/dp/B07G14HTBZ?m=A1GKQADQC2VI6E",
          "timestamp": "2022-05-01T22:36:33.236Z"
        },
        {
          "id": "0RmL0ZMUesP2PmSlP97G",
          "availability": "in",
          "condition": "new",
          "retailer": "Amazon",
          "price": 58.86,
          "URL": "https://www.amazon.com/dp/B07G14HTBZ",
          "timestamp": "2022-05-03T22:52:06.802Z"
        }
      ]
    }
]
```

### Retrieving Offers in CSV Format

**Cost:** 3 credits per product requested when requesting all retailers, 2 credits per product when requesting a single retailer.

By default all responses are in JSON format, but you can also retrieve data in CSV format by adding `?format=csv` to the request:

```
GET /products/offers?ids=611247373064,611247369449&retailer=bestbuy.com&format=csv
```

When you do this, the response will be formatted as a CSV file, with columns for each of the different fields, and each product on its own row. Each offer field will be a separate column, allowing for easy integration into spreadsheets and other tools or workflows.

#### Example Response

```csv
shopsavvy,barcode,amazon,title,category,brand,color,mpn,model,image,currency-Best Buy,price-Best Buy,availability-Best Buy,condition-Best Buy,URL-Best Buy,timestamp-Best Buy
3ONn300xybP3y66ibqc1,611247373064,B07G14HTBZ,"Keurig K-Mini Single Serve Coffee Maker, Black","Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",Keurig,Matte Black,5000200237,K-MINI,https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg,USD,59.99,in,new,https://www.bestbuy.com/site/keurig-k-mini-single-serve-k-cup-pod-coffee-maker-matte-black/6358476.p?skuId=6358476&ref=NS&loc=101,2022-11-05T11:47:00.226Z
DrKWneG0MpFlZpwZXNYa,611247369449,B0788F3R8X,"Keurig K-Elite Single Serve K-Cup Pod Maker with with Strength and Temperature Control, Iced Coffee Capability, 12oz Brew Size, Brushed Silver","Home & Kitchen > Kitchen & Dining > Coffee, Tea & Espresso > Coffee Makers > Single-Serve Brewers",Keurig,Brushed Silver,5000197492,K-Elite,https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/411fEW99TlL.jpg,USD,129.99,,new,https://www.bestbuy.com/site/keurig-k-elite-single-serve-k-cup-pod-coffee-maker-brushed-silver/6203569.p?skuId=6203569,2022-11-05T11:33:16.004Z
```

### Retrieving Offers With Historical Offer Data

**Cost:** 3 credits per product requested when requesting all retailers, 2 credits per product when requesting a single retailer. Additionally, there is a cost of 1 credit per day of historical data requested.

Historical data can be requested by adding `start` and `end` parameters to the request. These should be formatted as `YYYY-MM-DD`.

```
GET /products/offers/history?ids=611247373064&start=2022-11-20&end=2022-11-27
```

Please note you'll be charged **1 credit** for each day of historical data you request.

The response will be in the same format and schema as requests for offers, but each offer will include a `history` field, which will contain an array of historical changes for that specific offer. Each change will include these fields:

| Field | Description |
|-------|-------------|
| `timestamp` | An [ISO 8601](https://www.w3.org/TR/NOTE-datetime) formatted date and time representing when the change was seen by ShopSavvy. |
| `price` | The price of the offer at the time of the change. This will always be a number. |
| `availability` | The availability of the offer at the time of the change. This will only be present if the value is confirmed and known. It will be missing if availability is unknown. Will be either `"in"` or `"out"`. |

#### Example Response

```json
[
    {
      "title": "Keurig K-Mini Single Serve Coffee Maker, Black",
      "category": "Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",
      "brand": "Keurig",
      "color": "Black",
      "model": "K-MINI",
      "shopsavvy": "3ONn300xybP3y66ibqc1",
      "barcode": 611247373064,
      "amazon": "B07G14HTBZ",
      "mpn": "5000200237",
      "images": [
        "https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg"
      ],
      "offers": [
        {
          "id": "0IUouCFtZEhxeOablTPl",
          "availability": "in",
          "condition": "new",
          "retailer": "Amazon",
          "price": 74.96,
          "seller": "ACME Deals",
          "URL": "https://www.amazon.com/dp/B07G14HTBZ?m=A1GKQADQC2VI6E",
          "timestamp": "2022-05-01T22:36:33.236Z",
          "history": [
            {
              "timestamp": "2022-05-01T22:36:33.236Z",
              "price": 74.96,
              "availability": "in"
            },
            {
              "timestamp": "2022-05-02T22:36:33.236Z",
              "price": 70.99,
              "availability": "in"
            },
            {
              "timestamp": "2022-05-01T22:36:33.236Z",
              "price": 70.99,
              "availability": "out"
            }
          ]
        }
      ]
    }
]
```

---

## Scheduling API

### Enabling Scheduled Refreshes for Products

**Cost:** 1 credit per product scheduled + 3 credits every time each scheduled product is refreshed.

Enabling scheduled refreshes for products will cause ShopSavvy to refresh the pricing and availability data for the specified products on an interval you specify.

You can schedule one or more products using the same `ids` parameter as the `GET /products` and `GET /products/offers` endpoints.

Use the `schedule` parameter to specify how frequently you like the product(s) refreshed. This can be a string with a value of `"hourly"`, `"daily"`, or `"weekly"`.

```
PUT /products/scheduled?ids=611247373064,611247369449&schedule=daily
```

This will begin refreshing the pricing and availability for the product(s), and return products that were just scheduled. Note: You will need to call the `GET /products/offers` endpoint whenever you want to retrieve the latest data.

### Changing Refresh Schedule for Products

**Cost:** 1 credit per product scheduled + 3 credits every time each scheduled product is refreshed.

You can change how frequently previously scheduled product(s) are refreshed by calling the same endpoint but with a `POST`. Everything else works the same as enabling scheduled refreshes for new products.

Use the `schedule` parameter to specify how frequently you like the product(s) refreshed. This can be a string with a value of `"hourly"`, `"daily"`, or `"weekly"`.

```
POST /products/scheduled?ids=611247373064&schedule=hourly&retailer=bestbuy.com
```

This will begin refreshing the pricing and availability for the product(s), and return products that had their refresh schedule changed. Note: You will need to call the `GET /products/offers` endpoint whenever you want to retrieve the latest data.

### Disabling Scheduled Refreshes for Products

**Cost:** 0 credits per product scheduled.

Disabling scheduled refreshes for products will cause ShopSavvy to stop refreshing the pricing and availability data for the specified products.

```
DELETE /products/scheduled?ids=611247369449
```

### Retrieve Products Currently Enabled for Scheduled Refreshes

**Cost:** 0 credits.

```
GET /products/scheduled
```

This returns all the products you currently have enabled for scheduled refreshes, along with each of their configuration and refresh interval.

#### Example Response

```json
[
  {
    "schedule": "hourly",
    "title": "Keurig K-Mini Single Serve Coffee Maker, Black",
    "category": "Grocery & Gourmet Food > Beverages > Coffee, Tea & Cocoa > Coffee > Single-Serve Capsules & Pods",
    "brand": "Keurig",
    "color": "Black",
    "model": "K-MINI",
    "shopsavvy": "3ONn300xybP3y66ibqc1",
    "barcode": 611247373064,
    "amazon": "B07G14HTBZ",
    "mpn": "5000200237",
    "images": [
      "https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/31jy5fSzyRL.jpg"
    ]
  },
  {
    "schedule": "daily",
    "retailer": "bestbuy.com",
    "title": "Keurig K-Elite Single Serve K-Cup Pod Maker with Strength and Temperature Control, Iced Coffee Capability, 12oz Brew Size, Brushed Silver",
    "category": "Home & Kitchen > Kitchen & Dining > Coffee, Tea & Espresso > Coffee Makers > Single-Serve Brewers",
    "brand": "Keurig",
    "color": "Silver",
    "model": "K-Elite",
    "shopsavvy": "DrKWneG0MpFlZpwZXNYa",
    "barcode": 611247369449,
    "amazon": "B0788F3R8X",
    "mpn": "5000197492",
    "images": [
      "https://x.shopsavvy.com/https://images-na.ssl-images-amazon.com/images/I/411fEW99TlL.jpg"
    ]
  }
]
```

---

## Deals API

### Browse Deals

Retrieve a feed of current shopping deals with Reddit-style sorting, filtering, and pagination. Each deal includes an expert grade (A+ through F), pricing, retailer info, community votes, and more.

**Endpoint:** `GET /v1/deals`

**Credit Cost:** 1 credit per 10 deals returned

**Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sort` | string | `hot` | Sort algorithm: `hot`, `new`, `top-hour`, `top-day`, `top-week` |
| `limit` | number | 25 | Results per page (1-100) |
| `offset` | number | 0 | Pagination offset |
| `category` | string | | Filter by product category |
| `retailer` | string | | Filter by retailer domain (e.g., `amazon.com`) |
| `tag` | string | | Filter by deal tag |
| `min_price` | number | | Minimum deal price |
| `max_price` | number | | Maximum deal price |
| `grade` | string | | Minimum grade: `A`, `B`, `C`, `D` |
| `format` | string | `json` | Response format: `json` or `csv` |

**Boolean Filters** (set to `true` to filter): `is_percentage_off`, `is_dollar_off`, `is_bogo`, `is_price_drop`, `is_free_shipping`, `is_fast_shipping`, `is_limited_time`, `is_clearance`, `is_new_product`, `is_bundle`, `is_refurbished`, `is_open_box`, `requires_membership`, `has_coupon_code`, `has_mail_in_rebate`

**Example Request:**

```bash
curl -X GET 'https://api.shopsavvy.com/v1/deals?sort=hot&limit=10&grade=B' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

**Example Response:**

```json
{
  "success": true,
  "deals": [
    {
      "path": "deals/abc123",
      "title": "Sony WH-1000XM5 Wireless Headphones - 25% Off",
      "subtitle": "Lowest price in 3 months",
      "description": "Industry-leading noise cancellation headphones at a rare discount...",
      "emoji": "🎧",
      "grade": { "letter": "A", "suffix": "+", "value": 0.98, "justification": "Excellent price on a top-rated product" },
      "pricing": { "current": 248.00, "original": 349.99, "currency": "USD" },
      "retailer": { "name": "Amazon" },
      "url": "https://...",
      "image": { "url": "https://..." },
      "votes": { "upvotes": 142, "downvotes": 3, "score": 139 },
      "comment_count": 23,
      "tags": [{ "slug": "electronics", "display": "Electronics" }],
      "expires_at": "2026-04-15T00:00:00Z",
      "created_at": "2026-03-28T12:00:00Z"
    }
  ],
  "pagination": { "total": 487, "has_more": true, "limit": 10, "offset": 0 },
  "meta": { "request_id": "abc-123", "credits_used": 1, "credits_remaining": 999 }
}
```

---

## Reviews API

### Get TLDR Review for Product

Retrieve a concise expert review summary for a product, including pros, cons, a bottom line verdict, and quantitative scores. These are curated TLDR reviews — not raw customer reviews.

**Endpoint:** `GET /v1/products/reviews`

**Credit Cost:** 1 credit per product

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | string | Yes | Product identifier (barcode, ASIN, URL, model number) |
| `format` | string | No | Response format: `json` or `csv` |

**Example Request:**

```bash
curl -X GET 'https://api.shopsavvy.com/v1/products/reviews?id=B09XS7JWHH' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

**Example Response:**

```json
{
  "success": true,
  "product": { "path": "products/sony-wh1000xm5", "title": "Sony WH-1000XM5" },
  "review": {
    "slug": "sony-wh-1000xm5-review",
    "headline": "Best-in-class noise cancellation with premium sound",
    "pros": ["Industry-leading ANC", "30-hour battery life", "Comfortable all-day wear"],
    "cons": ["No IP rating", "No aptX support", "Premium pricing"],
    "bottom_line": "The best noise-cancelling headphones for most people.",
    "scores": { "overall": 87, "customer": 85, "professional": 89, "value": 78, "features": 91, "reliability": 83 }
  },
  "meta": { "request_id": "abc-123", "credits_used": 1, "credits_remaining": 998 }
}
```

**Note:** Returns `"review": null` if no TLDR review exists for the product (1 credit is still charged).

---

## Webhooks

Register webhook URLs to get notified when prices drop, product availability changes, or scheduled refreshes complete.

### Create Webhook

**Endpoint:** `POST /v1/webhooks`

**Request Body:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `url` | string | Yes | HTTPS URL to receive webhook POST requests |
| `events` | string[] | Yes | Event types: `price_drop`, `availability_change`, `schedule_completion` |

**Example:**
```bash
curl -X POST 'https://api.shopsavvy.com/v1/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://your-app.com/webhooks/shopsavvy", "events": ["price_drop", "availability_change"]}'
```

The response includes a `secret` field (shown once) — use it to verify webhook signatures.

### Verifying Webhook Signatures

Every webhook delivery includes an `X-ShopSavvy-Signature` header with format: `t=<timestamp>,v1=<signature>`.

To verify: compute `HMAC-SHA256(secret, "<timestamp>.<request_body>")` and compare to `v1`.

### List Webhooks

`GET /v1/webhooks` — Returns all your registered webhooks with status and failure counts.

### Test Webhook

`POST /v1/webhooks/:id/test` — Sends a test event to verify your URL is reachable.

### Delete Webhook

`DELETE /v1/webhooks/:id` — Permanently removes a webhook and all its event history.

**Retry Policy:** Failed deliveries are retried with exponential backoff (1min, 5min, 30min, 2hr, 12hr). After 5 failed attempts per event, the event is marked as permanently failed. After 50 consecutive failures, the webhook is automatically disabled.

**Limits:** Maximum 5 webhooks per account. Maximum 3 event types per webhook.

---

## Analytics & Tools

### Get API Usage Statistics

**Cost:** 0 credits.

You can retrieve your current API usage statistics and limits by using the `GET /usage` endpoint.

```bash
curl -X GET "https://api.shopsavvy.com/v1/usage" \
  -H "Authorization: Bearer ss_live_your_api_key_here"
```

This will return information about your current billing period usage, including credits used, remaining credits, and the percentage of your monthly limit used.

#### Example Response

```json
{
  "success": true,
  "data": {
    "current_period": {
      "start_date": "2025-01-01",
      "end_date": "2025-01-31",
      "credits_used": 1500,
      "credits_limit": 10000,
      "credits_remaining": 8500,
      "requests_made": 245
    },
    "usage_percentage": 15
  },
  "meta": {
    "credits_used": 0,
    "credits_remaining": 8500,
    "rate_limit_remaining": 50
  }
}
```

#### Response Fields

| Field | Description |
|-------|-------------|
| `start_date` / `end_date` | Your current billing period dates. |
| `credits_used` | Total credits consumed this billing period. |
| `credits_limit` | Your monthly credit allowance based on your subscription plan. |
| `credits_remaining` | Credits left for the current billing period. |
| `requests_made` | Total API requests made this billing period. |
| `usage_percentage` | Percentage of your monthly limit used. |

### CSV to API Request Converter

This is an interactive tool on the documentation page that allows you to upload a CSV file, choose a column to use as product identifiers, and it will generate the HTTP path to request from the API to get product or pricing data for each of those products in a single request.

The tool supports:
- **Pasting CSV content** directly
- **Selecting an identifier column** from your CSV headers
- **Skipping the first row** (header row) toggle
- **Request type selection**: Product Details or Product Offers
- **Retailer filtering**: All Retailers or Single Retailer (with domain input, e.g., `bestbuy.com`)
- **Response format**: CSV or JSON

The generated API request path can be copied and used directly with `curl` or any HTTP client.

### Rate Limits

API requests are subject to rate limiting to ensure fair usage across all subscribers. The `meta` object in every API response includes `rate_limit_remaining` which shows how many requests you can make in the current window.

Rate limit information is included in every API response:

```json
{
  "meta": {
    "credits_used": 2,
    "credits_remaining": 998,
    "rate_limit_remaining": 58
  }
}
```

---

## Quick Reference: All Endpoints

| Method | Endpoint | Description | Cost |
|--------|----------|-------------|------|
| `GET` | `/products?ids={identifiers}` | Get product details | 1 credit/product |
| `GET` | `/products?ids={identifiers}&format=csv` | Get product details in CSV | 1 credit/product |
| `GET` | `/products/search?q={query}` | Search products by keyword | 1 credit/product returned |
| `GET` | `/products/offers?ids={identifiers}` | Get offers from all retailers | 3 credits/product |
| `GET` | `/products/offers?ids={identifiers}&retailer={domain}` | Get offers from single retailer | 2 credits/product |
| `GET` | `/products/offers?ids={identifiers}&format=csv` | Get offers in CSV format | 3 or 2 credits/product |
| `GET` | `/products/offers/history?ids={identifiers}&start={date}&end={date}` | Get price history | Offer cost + 1 credit/day |
| `PUT` | `/products/scheduled?ids={identifiers}&schedule={interval}` | Enable scheduled monitoring | 1 credit + 3 credits/refresh |
| `POST` | `/products/scheduled?ids={identifiers}&schedule={interval}` | Update monitoring schedule | 1 credit + 3 credits/refresh |
| `DELETE` | `/products/scheduled?ids={identifiers}` | Disable scheduled monitoring | 0 credits |
| `GET` | `/products/scheduled` | View all scheduled products | 0 credits |
| `GET` | `/usage` | Get usage statistics | 0 credits |

**Base URL:** `https://api.shopsavvy.com/v1`

**Authentication:** `Authorization: Bearer ss_live_your_api_key_here`

**Supported Identifiers:** UPC, EAN, ISBN, GTIN, Amazon ASIN, Model Number, Product Name, URL at any retailer, ShopSavvy Product ID

**Schedule Intervals:** `"hourly"`, `"daily"`, `"weekly"`

**Response Formats:** JSON (default), CSV (add `&format=csv`)
