Skip to main content

Official Python SDK for Sirv REST API - Image CDN, 360 Spins, and Media Management

Project description

Sirv REST API Python SDK

Official Python SDK for the Sirv REST API - Image CDN, 360 Spins, and Media Management.

PyPI version Python versions License: MIT

Features

  • Full API Coverage: All Sirv REST API endpoints implemented
  • Type Hints: Complete type annotations for IDE support
  • Automatic Token Management: Auto-refresh tokens before expiry
  • Pagination Helpers: Generators for iterating through large result sets
  • Context Manager Support: Use with with statement for automatic cleanup
  • Retry Logic: Built-in retry mechanism for failed requests

Installation

pip install sirv-rest-api

Or with optional async support:

pip install sirv-rest-api[async]

Quick Start

from sirv_rest_api import SirvClient

# Initialize the client
client = SirvClient(
    client_id="your-client-id",
    client_secret="your-client-secret"
)

# Connect to get access token
client.connect()

# Get account information
account = client.get_account_info()
print(f"CDN URL: {account['cdnURL']}")

# Upload a file
client.upload_file("/images/photo.jpg", "./local/photo.jpg")

# Search for files
results = client.search_files({"query": "*.jpg", "size": 100})
for file in results['hits']:
    print(file['filename'])

Using Context Manager

from sirv_rest_api import SirvClient

with SirvClient(
    client_id="your-client-id",
    client_secret="your-client-secret"
) as client:
    account = client.get_account_info()
    print(f"Account: {account['alias']}")
# Session automatically closed

API Reference

Authentication

Connect

Authenticate and obtain a bearer token. Tokens are automatically refreshed before expiry.

token_info = client.connect()
print(f"Token expires in: {token_info['expiresIn']} seconds")
print(f"Scopes: {token_info['scope']}")

# Optional: Request a token with custom expiry time (5-604800 seconds)
token_info = client.connect(expires_in=3600)  # Token valid for 1 hour

The connect() method accepts an optional expires_in parameter to customize token lifetime:

  • Range: 5 to 604800 seconds (7 days)
  • Default: 1200 seconds (20 minutes)

Check Connection Status

if client.is_connected():
    print("Client is connected")

Account Management

Get Account Info

account = client.get_account_info()
print(f"CDN URL: {account['cdnURL']}")
print(f"Alias: {account['alias']}")
print(f"Created: {account['dateCreated']}")

Update Account Settings

client.update_account({
    "minify": {"enabled": True},
    "fetching": {
        "enabled": True,
        "type": "http",
        "http": {"url": "https://example.com/images"}
    }
})

Get API Rate Limits

limits = client.get_account_limits()
print(f"REST API - Remaining: {limits['rest']['remaining']}/{limits['rest']['limit']}")

Get Storage Info

storage = client.get_storage_info()
print(f"Used: {storage['used'] / 1e9:.2f} GB of {storage['allowance'] / 1e9:.2f} GB")
print(f"Files: {storage['files']}")

Get Account Users

users = client.get_account_users()
for user in users:
    print(f"{user['email']} - {user['role']}")

Get Billing Plan

plan = client.get_billing_plan()
print(f"Plan: {plan['name']}")
print(f"Storage: {plan['storage'] / 1e9:.2f} GB")

Search Account Events

events = client.search_events({
    "level": "error",
    "module": "files",
    "from_": "2024-01-01",
    "to": "2024-01-31"
})
for event in events:
    print(f"{event['timestamp']}: {event['message']}")

Mark Events as Seen

client.mark_events_seen(["event-id-1", "event-id-2"])

User Management

Get User Info

# Current user
user = client.get_user_info()
print(f"Email: {user['email']}")
print(f"S3 Key: {user.get('s3Key')}")

# Specific user
user = client.get_user_info(user_id="user-123")

File Operations

Upload Files

# Upload from file path
client.upload_file("/images/photo.jpg", "./local/photo.jpg")

# Upload from bytes
with open("photo.jpg", "rb") as f:
    photo_bytes = f.read()
client.upload_file("/images/photo.jpg", photo_bytes)

# Upload with options
client.upload_file(
    "/images/photo.jpg",
    "./local/photo.jpg",
    options={"content_type": "image/jpeg"}
)

Download Files

# Download to bytes
content = client.download_file("/images/photo.jpg")

# Download to local file
client.download_file_to("/images/photo.jpg", "./downloads/photo.jpg")

Get File Info

info = client.get_file_info("/images/photo.jpg")
print(f"Size: {info['size']} bytes")
print(f"Content-Type: {info['contentType']}")
print(f"Modified: {info['mtime']}")

Copy Files

client.copy_file("/images/photo.jpg", "/backup/photo.jpg")

Rename/Move Files

client.rename_file("/images/old-name.jpg", "/images/new-name.jpg")

# Move to different folder
client.rename_file("/images/photo.jpg", "/archive/photo.jpg")

Delete Files

# Delete single file
client.delete_file("/images/old-photo.jpg")

# Batch delete
result = client.batch_delete(["/old/file1.jpg", "/old/file2.jpg", "/old/file3.jpg"])
print(f"Job ID: {result.get('jobId')}")

# Check batch delete status
status = client.get_batch_delete_status(result['jobId'])
print(f"Status: {status['status']}")

Fetch from URL

client.fetch_url(
    url="https://example.com/image.jpg",
    filename="/fetched/image.jpg",
    wait=True  # Wait for completion
)

Folder Operations

Create Folder

client.create_folder("/images/2024")

Read Folder Contents

# Single page
contents = client.read_folder_contents("/images")
for item in contents['contents']:
    if item['isDirectory']:
        print(f"[DIR] {item['filename']}")
    else:
        print(f"[FILE] {item['filename']} - {item['size']} bytes")

# With pagination
contents = client.read_folder_contents("/images")
while True:
    for item in contents['contents']:
        print(item['filename'])
    if not contents.get('continuation'):
        break
    contents = client.read_folder_contents("/images", contents['continuation'])

Iterate All Folder Contents

# Automatically handles pagination
for item in client.iterate_folder_contents("/images"):
    print(f"{item['filename']}: {item.get('size', 'dir')}")

Folder Options

# Get folder options
options = client.get_folder_options("/spins")
print(f"Scan spins: {options.get('scanSpins')}")

# Set folder options
client.set_folder_options("/spins", {"scanSpins": True})

Search

Search Files

results = client.search_files({
    "query": "*.jpg",
    "size": 100,
    "sort": {"field": "mtime", "order": "desc"},
    "filters": {
        "dirname": "/images",
        "minSize": 10000,
        "maxSize": 5000000
    }
})
print(f"Found {results['total']} files")
for file in results['hits']:
    print(f"{file['filename']} - {file['size']} bytes")

Paginated Search

results = client.search_files({"query": "*.png"})
all_files = results['hits']

while results.get('scrollId') and results['hits']:
    results = client.scroll_search(results['scrollId'])
    all_files.extend(results['hits'])

print(f"Total files found: {len(all_files)}")

Iterate Search Results

# Automatically handles pagination
for file in client.iterate_search_results({"query": "*.png", "size": 1000}):
    print(file['filename'])

Metadata Management

File Metadata

# Get all metadata
meta = client.get_file_meta("/images/photo.jpg")
print(f"Title: {meta.get('title')}")
print(f"Description: {meta.get('description')}")
print(f"Tags: {meta.get('tags')}")

# Set metadata
client.set_file_meta("/images/photo.jpg", {
    "title": "Beautiful Sunset",
    "description": "Photo taken at the beach during sunset",
    "tags": ["sunset", "beach", "nature", "landscape"]
})

Title

# Get title
result = client.get_file_title("/images/photo.jpg")
print(result['title'])

# Set title
client.set_file_title("/images/photo.jpg", "My Beautiful Photo")

Description

# Get description
result = client.get_file_description("/images/photo.jpg")
print(result['description'])

# Set description
client.set_file_description("/images/photo.jpg", "A stunning landscape photograph")

Tags

# Get tags
result = client.get_file_tags("/images/photo.jpg")
print(result['tags'])

# Add tags
client.add_file_tags("/images/photo.jpg", ["nature", "landscape"])

# Remove tags
client.remove_file_tags("/images/photo.jpg", ["old-tag"])

Product Metadata

# Get product metadata
product = client.get_product_meta("/products/item.jpg")
print(f"SKU: {product.get('sku')}")
print(f"Brand: {product.get('brand')}")

# Set product metadata
client.set_product_meta("/products/item.jpg", {
    "id": "PROD-123",
    "name": "Blue Widget",
    "sku": "BW-001",
    "brand": "Acme",
    "category": "Widgets"
})

Approval Flag

# Get approval status
result = client.get_approval_flag("/images/photo.jpg")
print(f"Approved: {result['approved']}")

# Set approval flag
client.set_approval_flag("/images/photo.jpg", True)

ZIP Operations

# Create ZIP archive
result = client.batch_zip({
    "filenames": ["/images/1.jpg", "/images/2.jpg", "/images/3.jpg"],
    "filename": "/archives/photos.zip"
})
print(f"Job ID: {result.get('jobId')}")

# Check ZIP job status
status = client.get_zip_status(result['jobId'])
if status['status'] == 'completed':
    print(f"ZIP created: {status['filename']}")

JWT Protected URLs

jwt = client.generate_jwt({
    "filename": "/protected/image.jpg",
    "expiresIn": 3600,  # 1 hour
    "secureParams": {
        "w": "800",
        "h": "600"
    }
})
print(f"Protected URL: {jwt['url']}")
print(f"Token: {jwt['token']}")

360 Spin Operations

Convert Spin to Video

result = client.spin2video({
    "filename": "/spins/product.spin",
    "options": {
        "width": 1920,
        "height": 1080,
        "loops": 2,
        "format": "mp4"
    }
})
print(f"Video created: {result['filename']}")

Convert Video to Spin

result = client.video2spin({
    "filename": "/videos/turntable.mp4",
    "targetFilename": "/spins/product.spin",
    "options": {
        "frames": 36,
        "start": 0,
        "duration": 10
    }
})
print(f"Spin created: {result['filename']}")

Export Spin to Marketplaces

# Amazon
client.export_spin_to_amazon({
    "filename": "/spins/product.spin",
    "asin": "B08N5WRWNW"
})

# Walmart
client.export_spin_to_walmart({
    "filename": "/spins/product.spin",
    "productId": "123456789"
})

# Home Depot
client.export_spin_to_home_depot({
    "filename": "/spins/product.spin",
    "productId": "123456789"
})

# Lowe's
client.export_spin_to_lowes({
    "filename": "/spins/product.spin",
    "productId": "123456789"
})

# Grainger
client.export_spin_to_grainger({
    "filename": "/spins/product.spin",
    "productId": "123456789"
})

Points of Interest

# Get POIs
pois = client.get_points_of_interest("/spins/product.spin")
for poi in pois:
    print(f"{poi['name']}: ({poi['x']}, {poi['y']}) frame {poi.get('frame')}")

# Set POI
client.set_point_of_interest("/spins/product.spin", {
    "name": "logo",
    "x": 0.5,
    "y": 0.3,
    "frame": 0
})

# Delete POI
client.delete_point_of_interest("/spins/product.spin", "logo")

Statistics

HTTP Transfer Stats

stats = client.get_http_stats("2024-01-01", "2024-01-31")
for day in stats:
    print(f"{day['date']}: {day['transfer'] / 1e9:.2f} GB transferred")

Spin Views Stats

# Max 5-day range
stats = client.get_spin_views_stats("2024-01-01", "2024-01-05")
for day in stats:
    print(f"{day['date']}: {day['views']} views, {day.get('spins', 0)} interactions")

Storage Stats

stats = client.get_storage_stats("2024-01-01", "2024-01-31")
for day in stats:
    print(f"{day['date']}: {day['storage'] / 1e9:.2f} GB, {day.get('files', 0)} files")

Error Handling

from sirv_rest_api import SirvClient, SirvApiError

client = SirvClient(
    client_id="your-client-id",
    client_secret="your-client-secret"
)

try:
    client.connect()
    info = client.get_file_info("/nonexistent/file.jpg")
except SirvApiError as e:
    print(f"API Error: {e.message}")
    print(f"Status Code: {e.status_code}")
    print(f"Error Code: {e.error_code}")
except Exception as e:
    print(f"Unexpected error: {e}")

Configuration Options

client = SirvClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    base_url="https://api.sirv.com",  # API base URL
    auto_refresh_token=True,           # Auto-refresh tokens (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 for failed requests (default: 3)
)

Getting Your API Credentials

  1. Log in to your Sirv account
  2. Go to Settings > API
  3. Create a new API client or use existing credentials
  4. Copy your Client ID and Client Secret

Links

License

MIT License - see LICENSE file for details.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sirv_rest_api-1.0.0.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sirv_rest_api-1.0.0-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

Details for the file sirv_rest_api-1.0.0.tar.gz.

File metadata

  • Download URL: sirv_rest_api-1.0.0.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for sirv_rest_api-1.0.0.tar.gz
Algorithm Hash digest
SHA256 52f04c09fbd50e36397414791bf995bc15eaf039a75b77ca81573c6a2c762f35
MD5 6c2e370f508cf3a02f4871b7f4f7152e
BLAKE2b-256 09630a8fbf428198de2be48c90f68bf3b8507e94af44f5f02592dc8d48cbae0b

See more details on using hashes here.

File details

Details for the file sirv_rest_api-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: sirv_rest_api-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 20.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for sirv_rest_api-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f657c3971529810a14f8af75e937b9f3ca54c40642c1c8119b3c0eeea3fe4c0e
MD5 d20fff4f01e72f735f4bc209bcfdf1d3
BLAKE2b-256 cb1966d715daf713347cd07c9910eb0b945035b021f00580e5b262730b04eb62

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page