Official Go SDK for the Sirv REST API. Provides a simple, type-safe way to interact with Sirv's image hosting and processing platform.
- Complete coverage of all 40+ Sirv REST API endpoints
- Automatic token management with configurable expiry
- Context support for cancellation and timeouts
- Retry logic with exponential backoff
- Thread-safe client
- Iterator patterns for paginated results
- Comprehensive type definitions
go get github.com/sirv/sirv-rest-api-go- Go 1.21 or later
package main
import (
"context"
"fmt"
"log"
sirv "github.com/sirv/sirv-rest-api-go"
)
func main() {
// Create client
client, err := sirv.NewClient(sirv.ClientConfig{
ClientID: "your-client-id",
ClientSecret: "your-client-secret",
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Connect (authenticate)
token, err := client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Connected! Token expires in %d seconds\n", token.ExpiresIn)
// Get account info
account, err := client.GetAccountInfo(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Account: %s\n", account.Alias)
fmt.Printf("CDN URL: %s\n", account.CdnURL)
// List folder contents
folder, err := client.ReadFolderContents(ctx, "/", "")
if err != nil {
log.Fatal(err)
}
for _, item := range folder.Contents {
if item.IsDirectory {
fmt.Printf("[DIR] %s\n", item.Filename)
} else {
fmt.Printf("[FILE] %s\n", item.Filename)
}
}
}client, err := sirv.NewClient(sirv.ClientConfig{
// Required
ClientID: "your-client-id",
ClientSecret: "your-client-secret",
// Optional
BaseURL: "https://api.sirv.com", // Default
AutoRefreshToken: sirv.BoolPtr(true), // Default: true
TokenRefreshBuffer: 60, // Seconds before expiry to refresh (default: 60)
Timeout: 30 * time.Second, // Request timeout (default: 30s)
MaxRetries: 3, // Max retries on 5xx errors (default: 3)
})You can customize how long the token is valid (5-604800 seconds):
// Request a token valid for 1 hour (3600 seconds)
token, err := client.Connect(ctx, 3600)
// Request a token valid for 7 days (604800 seconds)
token, err := client.Connect(ctx, 604800)// Connect and get token
token, err := client.Connect(ctx)
token, err := client.Connect(ctx, 3600) // With custom expiry
// Check connection status
isConnected := client.IsConnected()
// Get current token
token := client.GetAccessToken()// Get account info
account, err := client.GetAccountInfo(ctx)
// Update account settings
err := client.UpdateAccount(ctx, &sirv.AccountUpdateOptions{
Minify: &sirv.MinifyOptions{Enabled: sirv.BoolPtr(true)},
})
// Get rate limits
limits, err := client.GetAccountLimits(ctx)
// Get storage info
storage, err := client.GetStorageInfo(ctx)
// Get billing plan
plan, err := client.GetBillingPlan(ctx)
// Get account users
users, err := client.GetAccountUsers(ctx)
// Search events
events, err := client.SearchEvents(ctx, &sirv.EventSearchParams{
Level: "error",
From: "2024-01-01",
})// Get file info
info, err := client.GetFileInfo(ctx, "/path/to/file.jpg")
// Read folder contents
folder, err := client.ReadFolderContents(ctx, "/my-folder", "")
// Iterate folder (handles pagination)
fileCh, errCh := client.IterateFolderContents(ctx, "/my-folder")
for file := range fileCh {
fmt.Println(file.Filename)
}
if err := <-errCh; err != nil {
log.Fatal(err)
}
// Search files
results, err := client.SearchFiles(ctx, &sirv.SearchParams{
Query: "*.jpg",
Size: sirv.IntPtr(10),
})
// Iterate search results (handles pagination)
fileCh, errCh := client.IterateSearchResults(ctx, &sirv.SearchParams{Query: "*"})
for file := range fileCh {
fmt.Println(file.Filename)
}
// Upload file from bytes
err := client.UploadFile(ctx, "/path/to/dest.jpg", imageBytes, nil)
// Upload file from local path
err := client.UploadFileFromPath(ctx, "/path/to/dest.jpg", "./local-file.jpg", nil)
// Download file
data, err := client.DownloadFile(ctx, "/path/to/file.jpg")
// Download file to local path
err := client.DownloadFileTo(ctx, "/path/to/file.jpg", "./local-file.jpg")
// Create folder
err := client.CreateFolder(ctx, "/new-folder")
// Delete file
err := client.DeleteFile(ctx, "/path/to/file.jpg")
// Copy file
err := client.CopyFile(ctx, &sirv.CopyParams{From: "/source.jpg", To: "/dest.jpg"})
// Rename/move file
err := client.RenameFile(ctx, &sirv.RenameParams{From: "/old.jpg", To: "/new.jpg"})
// Fetch from URL
err := client.FetchURL(ctx, &sirv.FetchURLParams{
URL: "https://example.com/image.jpg",
Filename: "/fetched/image.jpg",
})// Get file metadata
meta, err := client.GetFileMeta(ctx, "/path/to/file.jpg")
// Set file metadata
err := client.SetFileMeta(ctx, "/path/to/file.jpg", &sirv.FileMeta{
Title: "My Image",
Description: "A beautiful image",
Tags: []string{"nature", "landscape"},
})
// Get/set individual metadata fields
title, err := client.GetFileTitle(ctx, "/path/to/file.jpg")
err := client.SetFileTitle(ctx, "/path/to/file.jpg", "New Title")
tags, err := client.GetFileTags(ctx, "/path/to/file.jpg")
err := client.AddFileTags(ctx, "/path/to/file.jpg", []string{"tag1", "tag2"})
err := client.RemoveFileTags(ctx, "/path/to/file.jpg", []string{"tag1"})
// Product metadata
product, err := client.GetProductMeta(ctx, "/path/to/file.jpg")
err := client.SetProductMeta(ctx, "/path/to/file.jpg", &sirv.ProductMeta{
Name: "Product Name",
SKU: "SKU-123",
Brand: "Brand Name",
})
// Approval flag
approved, err := client.GetApprovalFlag(ctx, "/path/to/file.jpg")
err := client.SetApprovalFlag(ctx, "/path/to/file.jpg", true)jwt, err := client.GenerateJWT(ctx, &sirv.JWTParams{
Filename: "/protected/image.jpg",
ExpiresIn: sirv.IntPtr(3600), // 1 hour
})
fmt.Printf("Protected URL: %s\n", jwt.URL)// Convert spin to video
videoFile, err := client.Spin2Video(ctx, &sirv.SpinConvertParams{
Filename: "/spin/product.spin",
Options: &sirv.SpinConvertOptions{
Width: sirv.IntPtr(800),
Height: sirv.IntPtr(600),
},
})
// Convert video to spin
spinFile, err := client.Video2Spin(ctx, &sirv.Video2SpinParams{
Filename: "/video/product.mp4",
})
// Export spin to marketplaces
err := client.ExportSpinToAmazon(ctx, &sirv.ExportSpinParams{
Filename: "/spin/product.spin",
ASIN: "B01234567",
})// HTTP transfer stats
httpStats, err := client.GetHTTPStats(ctx, &sirv.StatsParams{
From: "2024-01-01",
To: "2024-01-31",
})
// Spin views stats (max 5-day range)
spinStats, err := client.GetSpinViewsStats(ctx, &sirv.StatsParams{
From: "2024-01-01",
To: "2024-01-05",
})
// Storage stats
storageStats, err := client.GetStorageStats(ctx, &sirv.StatsParams{
From: "2024-01-01",
To: "2024-01-31",
})account, err := client.GetAccountInfo(ctx)
if err != nil {
if apiErr := sirv.GetAPIError(err); apiErr != nil {
fmt.Printf("API Error: %s (status %d)\n", apiErr.Message, apiErr.StatusCode)
} else {
fmt.Printf("Error: %v\n", err)
}
}All API methods accept a context for cancellation and timeout control:
// With timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
account, err := client.GetAccountInfo(ctx)
// With cancellation
ctx, cancel := context.WithCancel(context.Background())
go func() {
// Cancel after some condition
cancel()
}()The Client is thread-safe and can be used concurrently from multiple goroutines:
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
info, err := client.GetFileInfo(ctx, fmt.Sprintf("/file%d.jpg", i))
// ...
}(i)
}
wg.Wait()MIT License - see LICENSE for details.