Official Swift SDK for the ShopSavvy Data API. Access comprehensive product data, real-time pricing, and historical price trends across thousands of retailers and millions of products.
// Add to Package.swift or Xcode Package Dependencies:
// https://github.com/shopsavvy/sdk-swift.git
import ShopSavvySDK
let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
Task {
let product = try await client.getProductDetails(identifier: "012345678901")
let offers = try await client.getCurrentOffers(identifier: "012345678901")
let bestOffer = offers.data.min { $0.price ?? 0 < $1.price ?? 0 }
print("\(product.data.name) - Best price: $\(bestOffer?.price ?? 0) at \(bestOffer?.retailer ?? "")")
}| Feature | Free Tier | Pro | Enterprise |
|---|---|---|---|
| API Calls/Month | 1,000 | 100,000 | Unlimited |
| Product Details | β | β | β |
| Real-time Pricing | β | β | β |
| Price History | 30 days | 1 year | 5+ years |
| Bulk Operations | 10/batch | 100/batch | 1000/batch |
| Retailer Coverage | 50+ | 500+ | 1000+ |
| Rate Limiting | 60/hour | 1000/hour | Custom |
| Support | Community | Phone + Dedicated |
- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+
- Swift 5.5+ / Xcode 13.0+
Method 1: Xcode
- File β Add Package Dependencies
- Enter:
https://github.com/shopsavvy/sdk-swift.git - Select version and add to target
Method 2: Package.swift
dependencies: [
.package(url: "https://github.com/shopsavvy/sdk-swift.git", from: "1.0.0")
]pod 'ShopSavvySDK', '~> 1.0.0'- Sign up: Visit shopsavvy.com/data
- Choose plan: Select based on your usage needs
- Get API key: Copy from your dashboard
- Test: Run the 30-second example above
import ShopSavvySDK
// Basic configuration
let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
// Advanced configuration
let client = ShopSavvyClient(
apiKey: "ss_live_your_api_key_here",
baseURL: "https://api.shopsavvy.com/v1", // Custom base URL
timeoutInterval: 60.0, // Request timeout
retryAttempts: 3, // Retry failed requests
userAgent: "MyApp/1.0.0" // Custom user agent
)
// Environment variable configuration
let apiKey = ProcessInfo.processInfo.environment["SHOPSAVVY_API_KEY"] ?? ""
let client = ShopSavvyClient(apiKey: apiKey)import ShopSavvySDK
class ProductService {
private let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
func lookupProduct() async {
do {
// Look up by barcode, ASIN, URL, model number, or ShopSavvy ID
let product = try await client.getProductDetails(identifier: "012345678901")
let amazonProduct = try await client.getProductDetails(identifier: "B08N5WRWNW")
let urlProduct = try await client.getProductDetails(identifier: "https://www.amazon.com/dp/B08N5WRWNW")
let modelProduct = try await client.getProductDetails(identifier: "MQ023LL/A") // iPhone model number
print("π¦ Product: \(product.data.name)")
print("π·οΈ Brand: \(product.data.brand ?? "N/A")")
print("π Category: \(product.data.category ?? "N/A")")
print("π’ Product ID: \(product.data.id)")
if let asin = product.data.asin {
print("π¦ ASIN: \(asin)")
}
if let model = product.data.modelNumber {
print("π§ Model: \(model)")
}
} catch {
print("Error: \(error)")
}
}
}func lookupMultipleProducts() async {
// Process up to 100 products at once (Pro plan)
let identifiers = [
"012345678901", "B08N5WRWNW", "045496590048",
"https://www.bestbuy.com/site/product/123456",
"MQ023LL/A", "SM-S911U" // iPhone and Samsung model numbers
]
do {
let products = try await client.getProductDetailsBatch(identifiers: identifiers)
for (index, product) in products.data.enumerated() {
if let product = product {
print("β Found: \(product.name) by \(product.brand ?? "Unknown")")
} else {
print("β Failed to find product: \(identifiers[index])")
}
}
} catch {
print("Batch lookup error: \(error)")
}
}import SwiftUI
import ShopSavvySDK
struct PriceComparisonView: View {
@State private var offers: [Offer] = []
@State private var isLoading = false
@State private var errorMessage: String?
private let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
private let productIdentifier = "012345678901"
var body: some View {
NavigationView {
VStack {
if isLoading {
ProgressView("Loading offers...")
} else if let error = errorMessage {
Text("Error: \(error)")
.foregroundColor(.red)
} else {
List(offers, id: \.retailer) { offer in
HStack {
VStack(alignment: .leading) {
Text(offer.retailer)
.font(.headline)
Text(offer.availability ?? "Unknown")
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
VStack(alignment: .trailing) {
Text("$\(offer.price ?? 0, specifier: "%.2f")")
.font(.title2)
.fontWeight(.semibold)
.foregroundColor(offer == bestOffer ? .green : .primary)
if offer == bestOffer {
Text("BEST PRICE")
.font(.caption)
.foregroundColor(.green)
.fontWeight(.bold)
}
}
}
}
}
}
.navigationTitle("Price Comparison")
.task {
await loadOffers()
}
.refreshable {
await loadOffers()
}
}
}
private var bestOffer: Offer? {
offers.min { ($0.price ?? Double.max) < ($1.price ?? Double.max) }
}
private func loadOffers() async {
isLoading = true
errorMessage = nil
do {
let response = try await client.getCurrentOffers(identifier: productIdentifier)
await MainActor.run {
self.offers = response.data.sorted { ($0.price ?? 0) < ($1.price ?? 0) }
self.isLoading = false
}
} catch {
await MainActor.run {
self.errorMessage = error.localizedDescription
self.isLoading = false
}
}
}
}func analyzeOffers() async {
do {
let response = try await client.getCurrentOffers(identifier: "012345678901")
let offers = response.data
print("Found \(offers.count) offers across retailers")
// Sort by price
let sortedOffers = offers.sorted { ($0.price ?? 0) < ($1.price ?? 0) }
guard let cheapest = sortedOffers.first,
let mostExpensive = sortedOffers.last else { return }
let total = offers.compactMap { $0.price }.reduce(0, +)
let average = total / Double(offers.count)
print("π° Best price: \(cheapest.retailer) - $\(cheapest.price ?? 0)")
print("πΈ Highest price: \(mostExpensive.retailer) - $\(mostExpensive.price ?? 0)")
print("π Average price: $\(String(format: "%.2f", average))")
print("π‘ Potential savings: $\(String(format: "%.2f", (mostExpensive.price ?? 0) - (cheapest.price ?? 0)))")
// Filter by availability and condition
let inStockOffers = offers.filter { $0.availability == "in_stock" }
let newConditionOffers = offers.filter { $0.condition == "new" }
print("β
In-stock offers: \(inStockOffers.count)")
print("π New condition: \(newConditionOffers.count)")
} catch {
print("Error analyzing offers: \(error)")
}
}import SwiftUI
import ShopSavvySDK
// MARK: - View Model
@MainActor
class PriceTrackingViewModel: ObservableObject {
@Published var products: [TrackedProduct] = []
@Published var isLoading = false
@Published var errorMessage: String?
private let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
func addProduct(identifier: String, targetPrice: Double) async {
isLoading = true
do {
// Get product details
let productResponse = try await client.getProductDetails(identifier: identifier)
// Get current offers
let offersResponse = try await client.getCurrentOffers(identifier: identifier)
let bestOffer = offersResponse.data.min { ($0.price ?? 0) < ($1.price ?? 0) }
// Schedule monitoring
_ = try await client.scheduleProductMonitoring(identifier: identifier, frequency: "daily")
let trackedProduct = TrackedProduct(
identifier: identifier,
name: productResponse.data.name,
currentPrice: bestOffer?.price ?? 0,
targetPrice: targetPrice,
retailer: bestOffer?.retailer ?? "Unknown"
)
products.append(trackedProduct)
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}
func refreshPrices() async {
for index in products.indices {
do {
let offers = try await client.getCurrentOffers(identifier: products[index].identifier)
if let bestOffer = offers.data.min(by: { ($0.price ?? 0) < ($1.price ?? 0) }) {
products[index].currentPrice = bestOffer.price ?? 0
products[index].retailer = bestOffer.retailer
// Check if target price reached
if let price = bestOffer.price, price <= products[index].targetPrice {
sendPriceAlert(for: products[index])
}
}
} catch {
print("Error refreshing price for \(products[index].name): \(error)")
}
}
}
private func sendPriceAlert(for product: TrackedProduct) {
// Send local notification
let content = UNMutableNotificationContent()
content.title = "Price Alert!"
content.body = "\(product.name) is now $\(product.currentPrice) at \(product.retailer)"
content.sound = .default
let request = UNNotificationRequest(
identifier: UUID().uuidString,
content: content,
trigger: nil
)
UNUserNotificationCenter.current().add(request)
}
}
// MARK: - Model
struct TrackedProduct: Identifiable {
let id = UUID()
let identifier: String
let name: String
var currentPrice: Double
let targetPrice: Double
var retailer: String
}
// MARK: - View
struct PriceTrackingView: View {
@StateObject private var viewModel = PriceTrackingViewModel()
@State private var showingAddProduct = false
var body: some View {
NavigationView {
List(viewModel.products) { product in
VStack(alignment: .leading, spacing: 8) {
Text(product.name)
.font(.headline)
HStack {
Text("Current: $\(product.currentPrice, specifier: "%.2f")")
Spacer()
Text("Target: $\(product.targetPrice, specifier: "%.2f")")
}
.font(.subheadline)
Text("Best at: \(product.retailer)")
.font(.caption)
.foregroundColor(.secondary)
}
.padding(.vertical, 4)
}
.navigationTitle("Price Tracking")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
showingAddProduct = true
}
}
}
.refreshable {
await viewModel.refreshPrices()
}
}
.sheet(isPresented: $showingAddProduct) {
AddProductView(viewModel: viewModel)
}
}
}import BackgroundTasks
import ShopSavvySDK
class BackgroundPriceMonitor {
static let shared = BackgroundPriceMonitor()
private let client = ShopSavvyClient(apiKey: "ss_live_your_api_key_here")
func scheduleBackgroundRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.myapp.price-refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes
try? BGTaskScheduler.shared.submit(request)
}
func handleBackgroundRefresh(task: BGAppRefreshTask) {
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
Task {
await checkPrices()
task.setTaskCompleted(success: true)
scheduleBackgroundRefresh()
}
}
private func checkPrices() async {
// Get tracked products from UserDefaults or Core Data
let trackedProducts = getTrackedProducts()
for product in trackedProducts {
do {
let offers = try await client.getCurrentOffers(identifier: product.identifier)
if let bestOffer = offers.data.min(by: { ($0.price ?? 0) < ($1.price ?? 0) }),
let price = bestOffer.price,
price <= product.targetPrice {
// Send push notification
await sendPriceAlert(product: product, price: price, retailer: bestOffer.retailer)
}
} catch {
print("Background price check failed for \(product.identifier): \(error)")
}
}
}
private func sendPriceAlert(product: TrackedProduct, price: Double, retailer: String) async {
// Implementation for sending notifications
}
private func getTrackedProducts() -> [TrackedProduct] {
// Implementation to retrieve tracked products
return []
}
}# Clone the repository
git clone https://github.com/shopsavvy/sdk-swift.git
cd sdk-swift
# Open in Xcode
open Package.swift
# Or build from command line
swift build
# Run tests
swift testimport ShopSavvySDK
class SDKTester {
private let client = ShopSavvyClient(apiKey: "ss_test_your_test_key_here")
func runTests() async {
do {
// Test product lookup
let product = try await client.getProductDetails(identifier: "012345678901")
print("β
Product lookup: \(product.data.name)")
// Test current offers
let offers = try await client.getCurrentOffers(identifier: "012345678901")
print("β
Current offers: \(offers.data.count) found")
// Test usage info
let usage = try await client.getUsage()
print("β
API usage: \(usage.data.creditsRemaining ?? 0) credits remaining")
print("\nπ All tests passed! SDK is working correctly.")
} catch {
print("β Test failed: \(error)")
}
}
}- ShopSavvy Data API Documentation - Complete API reference
- API Dashboard - Manage your API keys and usage
- GitHub Repository - Source code and issues
- Swift Package Index - Package documentation
- Support - Get help from our team
We welcome contributions! Please see our Contributing Guide for details on:
- Reporting bugs
- Suggesting enhancements
- Submitting pull requests
- Development workflow
- Code standards
This project is licensed under the MIT License - see the LICENSE file for details.
ShopSavvy is the world's first mobile shopping app, helping consumers find the best deals since 2008. With over 40 million downloads and millions of active users, ShopSavvy has saved consumers billions of dollars.
- π E-commerce platforms with competitive intelligence
- π Market research with real-time pricing data
- πͺ Retailers with inventory and pricing optimization
- π± Mobile apps with product lookup and price comparison
- π€ Business intelligence with automated price monitoring
- β Trusted by millions - Proven at scale since 2008
- β Comprehensive coverage - 1000+ retailers, millions of products
- β Real-time accuracy - Fresh data updated continuously
- β Developer-friendly - Easy integration, great documentation
- β Reliable infrastructure - 99.9% uptime, enterprise-grade
- β Flexible pricing - Plans for every use case and budget
Ready to get started? Sign up for your API key β’ Need help? Contact us