Apertur Ruby SDK
Official Ruby client for the Apertur image upload and delivery API.
Installation
Add to your Gemfile:
gem "apertur-sdk"
Or install directly:
gem install apertur-sdk
Quick Start
require "apertur"
client = Apertur::Client.new(api_key: "aptr_test_your_key_here")
# Create an upload session
session = client.sessions.create(max_images: 10)
puts session["uuid"]
# Upload an image
result = client.upload.image(session["uuid"], "/path/to/photo.jpg")
# Upload with encryption
server_key = client.encryption.get_server_key
client.upload.image_encrypted(
session["uuid"],
"/path/to/photo.jpg",
server_key["publicKey"]
)
Authentication
The SDK accepts an API key (prefixed aptr_ or aptr_test_) or an OAuth token. The environment is auto-detected from the key prefix:
aptr_test_*keys target the sandbox athttps://sandbox.api.aptr.caaptr_*keys target production athttps://api.aptr.ca
You can override the base URL:
client = Apertur::Client.new(api_key: "aptr_...", base_url: "http://localhost:3000")
Resources
Sessions
client.sessions.create(max_images: 5, expires_in_hours: 24)
client.sessions.get("uuid")
client.sessions.update("uuid", max_images: 10)
client.sessions.list(page: 1, page_size: 20)
client.sessions.recent(limit: 5)
client.sessions.qr("uuid", format: "png", size: 300)
client.sessions.verify_password("uuid", "secret")
client.sessions.delivery_status("uuid")
Upload
# Multipart upload from file path
client.upload.image("uuid", "/path/to/image.jpg")
# Upload from IO
File.open("photo.png", "rb") do |f|
client.upload.image("uuid", f, filename: "photo.png", mime_type: "image/png")
end
# Encrypted upload
client.upload.image_encrypted("uuid", "/path/to/image.jpg", public_key_pem)
Uploads
client.uploads.list(page: 1, page_size: 20)
client.uploads.recent(limit: 10)
Polling
# One-shot poll
result = client.polling.list("uuid")
data = client.polling.download("uuid", image_id)
client.polling.ack("uuid", image_id)
# Blocking loop
client.polling.poll_and_process("uuid", interval: 3) do |image, data|
File.binwrite("downloads/#{image['id']}.jpg", data)
end
Destinations
client.destinations.list("project_id")
client.destinations.create("project_id", type: "s3", bucket: "my-bucket")
client.destinations.update("project_id", "dest_id", bucket: "other-bucket")
client.destinations.delete("project_id", "dest_id")
client.destinations.test("project_id", "dest_id")
Keys
client.keys.list("project_id")
client.keys.create("project_id", name: "My Key")
client.keys.update("project_id", "key_id", name: "Renamed Key")
client.keys.delete("project_id", "key_id")
client.keys.set_destinations("key_id", ["dest_1", "dest_2"], long_polling_enabled: true)
Webhooks
client.webhooks.list("project_id")
client.webhooks.create("project_id", url: "https://example.com/hook", events: ["upload.completed"])
client.webhooks.update("project_id", "webhook_id", url: "https://example.com/hook2")
client.webhooks.delete("project_id", "webhook_id")
client.webhooks.test("project_id", "webhook_id")
client.webhooks.deliveries("project_id", "webhook_id", page: 1, limit: 20)
client.webhooks.retry_delivery("project_id", "webhook_id", "delivery_id")
Encryption
server_key = client.encryption.get_server_key
Stats
stats = client.stats.get
Webhook Signature Verification
# Simple webhook
Apertur::Signature.verify_webhook(request_body, signature_header, secret)
# Event webhook with timestamp
Apertur::Signature.verify_event(request_body, , signature_header, secret)
# Svix-style webhook
Apertur::Signature.verify_svix(request_body, svix_id, , svix_signature, secret)
Client-Side Encryption
encrypted = Apertur::Crypto.encrypt_image(raw_bytes, public_key_pem)
# => { "encrypted_key" => "...", "iv" => "...", "encrypted_data" => "...", "algorithm" => "RSA-OAEP+AES-256-GCM" }
Error Handling
begin
client.sessions.get("nonexistent")
rescue Apertur::NotFoundError => e
puts "Not found: #{e.}"
rescue Apertur::AuthenticationError => e
puts "Auth failed: #{e.}"
rescue Apertur::RateLimitError => e
puts "Rate limited, retry after #{e.retry_after}s"
rescue Apertur::ValidationError => e
puts "Invalid request: #{e.}"
rescue Apertur::Error => e
puts "API error #{e.status_code}: #{e.}"
end
Requirements
- Ruby >= 3.0
- No external dependencies (uses
net/http,json, andopensslfrom stdlib)
License
MIT