Sirv REST API Ruby SDK

Official Ruby SDK for the Sirv REST API. Provides a simple, type-safe way to interact with Sirv's image hosting and processing platform.

Features

  • Complete coverage of all 40+ Sirv REST API endpoints
  • Automatic token management with configurable expiry
  • Thread-safe client
  • Retry logic with exponential backoff
  • Comprehensive model classes
  • Iterator patterns for paginated results
  • Zero external dependencies (uses Ruby stdlib only)

Installation

Add this line to your application's Gemfile:

gem 'sirv_rest_api'

And then execute:

bundle install

Or install it yourself:

gem install sirv_rest_api

Requirements

  • Ruby 2.7 or later

Quick Start

require 'sirv_rest_api'

# Create client
client = SirvRestApi::Client.new(
  client_id: 'your-client-id',
  client_secret: 'your-client-secret'
)

# Connect (authenticate)
token = client.connect
puts "Connected! Token expires in #{token.expires_in} seconds"

# Get account info
 = client.
puts "Account: #{account.alias}"
puts "CDN URL: #{account.cdn_url}"

# List folder contents
folder = client.read_folder_contents('/')
folder.contents.each do |item|
  type = item.directory? ? '[DIR]' : '[FILE]'
  puts "#{type} #{item.filename}"
end

Configuration

client = SirvRestApi::Client.new(
  # Required
  client_id: 'your-client-id',
  client_secret: 'your-client-secret',

  # Optional
  base_url: 'https://api.sirv.com',  # Default
  auto_refresh_token: true,           # Default: true
  token_refresh_buffer: 60,           # Seconds before expiry to refresh (default: 60)
  timeout: 30,                         # Request timeout in seconds (default: 30)
  max_retries: 3                       # Max retries on 5xx errors (default: 3)
)

Custom Token Expiry

You can customize how long the token is valid (5-604800 seconds):

# Request a token valid for 1 hour (3600 seconds)
token = client.connect(expires_in: 3600)

# Request a token valid for 7 days (604800 seconds)
token = client.connect(expires_in: 604800)

API Reference

Authentication

# Connect and get token
token = client.connect
token = client.connect(expires_in: 3600)  # Custom expiry

# Check connection status
client.connected?

# Get current token
client.access_token

Account Operations

# Get account info
 = client.

# Update account settings
client.(minify: { enabled: true })

# Get rate limits
limits = client.

# Get storage info
storage = client.get_storage_info

# Get billing plan
plan = client.get_billing_plan

# Get account users
users = client.

# Search events
events = client.search_events(level: 'error', from: '2024-01-01')

File Operations

# Get file info
info = client.get_file_info('/path/to/file.jpg')

# Read folder contents
folder = client.read_folder_contents('/my-folder')

# Iterate folder (handles pagination)
client.each_folder_item('/my-folder') do |file|
  puts file.filename
end

# Search files
results = client.search_files(query: '*.jpg', size: 10)

# Iterate search results (handles pagination)
client.each_search_result(query: '*') do |file|
  puts file.filename
end

# Upload file
client.upload_file('/path/to/dest.jpg', File.binread('./image.jpg'))

# Upload from local path
client.upload_file_from_path('/path/to/dest.jpg', './local-file.jpg')

# Download file
content = client.download_file('/path/to/file.jpg')

# Download file to local path
client.download_file_to('/path/to/file.jpg', './local-file.jpg')

# Create folder
client.create_folder('/new-folder')

# Delete file
client.delete_file('/path/to/file.jpg')

# Copy file
client.copy_file(from: '/source.jpg', to: '/dest.jpg')

# Rename/move file
client.rename_file(from: '/old.jpg', to: '/new.jpg')

# Fetch from URL
client.fetch_url(url: 'https://example.com/image.jpg', filename: '/fetched/image.jpg')

Metadata Operations

# Get file metadata
meta = client.get_file_meta('/path/to/file.jpg')

# Set file metadata
client.set_file_meta('/path/to/file.jpg', {
  title: 'My Image',
  description: 'A beautiful image',
  tags: ['nature', 'landscape']
})

# Get/set individual metadata fields
title = client.get_file_title('/path/to/file.jpg')
client.set_file_title('/path/to/file.jpg', 'New Title')

tags = client.get_file_tags('/path/to/file.jpg')
client.add_file_tags('/path/to/file.jpg', ['tag1', 'tag2'])
client.remove_file_tags('/path/to/file.jpg', ['tag1'])

# Product metadata
product = client.get_product_meta('/path/to/file.jpg')
client.set_product_meta('/path/to/file.jpg', {
  name: 'Product Name',
  sku: 'SKU-123',
  brand: 'Brand Name'
})

# Approval flag
approved = client.get_approval_flag('/path/to/file.jpg')
client.set_approval_flag('/path/to/file.jpg', true)

JWT Protected URLs

jwt = client.generate_jwt(filename: '/protected/image.jpg', expires_in: 3600)
puts "Protected URL: #{jwt.url}"

Spins/360 Operations

# Convert spin to video
video_file = client.spin_to_video('/spin/product.spin', options: {
  width: 800,
  height: 600
})

# Convert video to spin
spin_file = client.video_to_spin('/video/product.mp4')

# Export spin to marketplaces
client.export_spin_to_amazon(filename: '/spin/product.spin', asin: 'B01234567')
client.export_spin_to_walmart(filename: '/spin/product.spin')
client.export_spin_to_home_depot(filename: '/spin/product.spin')
client.export_spin_to_lowes(filename: '/spin/product.spin')
client.export_spin_to_grainger(filename: '/spin/product.spin')

Statistics

# HTTP transfer stats
http_stats = client.get_http_stats(from: '2024-01-01', to: '2024-01-31')

# Spin views stats (max 5-day range)
spin_stats = client.get_spin_views_stats(from: '2024-01-01', to: '2024-01-05')

# Storage stats
storage_stats = client.get_storage_stats(from: '2024-01-01', to: '2024-01-31')

Error Handling

begin
   = client.
rescue SirvRestApi::AuthenticationError => e
  puts "Authentication failed: #{e.message}"
rescue SirvRestApi::NotFoundError => e
  puts "Not found: #{e.message}"
rescue SirvRestApi::RateLimitError => e
  puts "Rate limit exceeded: #{e.message}"
rescue SirvRestApi::ApiError => e
  puts "API error: #{e.message} (status #{e.status_code})"
end

Thread Safety

The client is thread-safe and can be used from multiple threads:

threads = 10.times.map do |i|
  Thread.new do
    info = client.get_file_info("/file#{i}.jpg")
    puts info.filename
  end
end
threads.each(&:join)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests.

To install this gem onto your local machine, run bundle exec rake install.

License

MIT License - see LICENSE for details.