Uploadcare Ruby SDK
uploadcare-ruby is a framework-agnostic client for the Uploadcare Upload API and REST API.
The gem is built around:
- explicit
Uploadcare::Clientinstances - client-scoped configuration for multi-account use
- a small convenience layer for common workflows
full endpoint coverage through
client.api.restandclient.api.upload
Requirements
- Ruby 3.3+
Compatibility
This gem is intended for plain Ruby applications and for framework integrations built on top of it.
- Use explicit
Uploadcare::Clientinstances when you need multiple accounts in one process. - Use
Uploadcare.configureandUploadcare.clientwhen one global default client is enough. - Use
client.api.restandclient.api.uploadwhen you want endpoint-level parity with the official API references.
Installation
Add the gem to your Gemfile:
gem "uploadcare-ruby"
Then install:
bundle
Set credentials with environment variables:
export UPLOADCARE_PUBLIC_KEY=your_public_key
export UPLOADCARE_SECRET_KEY=your_secret_key
Design
The gem has two public layers:
Convenience layer
This is the default API you should use in applications:
client.filesclient.groupsclient.uploadsclient.projectclient.webhooksclient.file_metadataclient.addonsclient.conversions
This layer returns resources and collections, and it raises typed exceptions on failure.
Raw parity layer
This layer mirrors Uploadcare’s REST and Upload APIs:
client.api.restclient.api.upload
This layer returns Uploadcare::Result objects so you can inspect success and failure explicitly.
That split keeps app code clean without losing full API coverage.
Quick Start
require "uploadcare"
client = Uploadcare::Client.new(
public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
)
file = File.open("photo.jpg", "rb") do |io|
client.files.upload(io, store: true)
end
puts file.uuid
puts file.cdn_url
You can also configure a default global client:
Uploadcare.configure do |config|
config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
end
file = File.open("photo.jpg", "rb") do |io|
Uploadcare.files.upload(io, store: true)
end
The recommended style is explicit Uploadcare::Client instances. Global configuration is best treated as a default.
Example Usage
This is the shortest end-to-end flow for the main public API:
require "uploadcare"
client = Uploadcare::Client.new(
public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
)
file = File.open("photo.jpg", "rb") do |io|
client.files.upload(io, store: true)
end
group = client.groups.create(uuids: [file.uuid])
puts file.uuid
puts file.cdn_url
puts group.id
puts group.cdn_url
Configuration
Use Uploadcare.configure to set process-wide defaults:
Uploadcare.configure do |config|
config.public_key = "public_key"
config.secret_key = "secret_key"
config.auth_type = "Uploadcare"
config.use_subdomains = false
end
Or build configuration objects directly:
base_config = Uploadcare::Configuration.new(
public_key: "public_key",
secret_key: "secret_key"
)
client = Uploadcare::Client.new(config: base_config)
Configuration objects are copyable:
account_a = Uploadcare::Client.new(config: base_config.with(public_key: "pk-a", secret_key: "sk-a"))
account_b = Uploadcare::Client.new(config: base_config.with(public_key: "pk-b", secret_key: "sk-b"))
Common configuration options:
public_keysecret_keyauth_typemultipart_size_thresholdmultipart_chunk_sizeupload_threadsupload_timeoutmax_upload_retriessign_uploadsupload_signature_lifetimeuse_subdomainscdn_base_postfixdefault_cdn_base
CDN helpers:
Uploadcare.configure do |config|
config.use_subdomains = true
config.cdn_base_postfix = "https://ucarecd.net/"
config.default_cdn_base = "https://ucarecdn.com/"
end
Uploadcare.configuration.custom_cname
Uploadcare.configuration.cdn_base
Multi-Account Usage
The gem is designed to support multiple Uploadcare projects in the same process:
primary = Uploadcare::Client.new(public_key: "pk-1", secret_key: "sk-1")
secondary = Uploadcare::Client.new(public_key: "pk-2", secret_key: "sk-2")
primary_file = primary.files.find(uuid: "uuid-1")
secondary_file = secondary.files.find(uuid: "uuid-2")
You can also derive temporary variants from an existing client:
admin_client = primary.with(secret_key: "different-secret")
Resource objects retain their client context, so subsequent instance operations stay bound to the correct account.
Uploads
Smart upload
client.uploads.upload accepts:
- an IO or file object
- an array of IO or file objects
- an HTTP or HTTPS URL string
file = File.open("photo.jpg", "rb") do |io|
client.uploads.upload(io, store: true)
end
remote_file = client.uploads.upload("https://example.com/image.jpg", store: true)
Single file upload
file = File.open("photo.jpg", "rb") do |io|
client.files.upload(io, store: true, metadata: { subsystem: "avatars" })
end
Multiple file upload
files = [
File.open("photo-1.jpg", "rb"),
File.open("photo-2.jpg", "rb")
]
uploaded = client.uploads.upload(files, store: true)
files.each(&:close)
Upload from URL
Synchronous:
file = client.files.upload_from_url("https://example.com/image.jpg", store: true)
Async:
job = client.uploads.upload_from_url(url: "https://example.com/image.jpg", async: true, store: true)
status = client.uploads.upload_from_url_status(token: job.fetch("token"))
When async mode is enabled, the convenience layer returns the raw status token hash because the file does not exist yet.
Polling options for synchronous URL uploads:
poll_interval(default:1) initial status polling interval in secondspoll_max_interval(default:10) maximum polling interval in secondspoll_timeout(default:300) maximum total polling time in seconds
Multipart upload with progress
File.open("large-video.mp4", "rb") do |io|
file = client.uploads.multipart_upload(file: io, store: true, threads: 4) do |progress|
uploaded = progress[:uploaded]
total = progress[:total]
puts "#{uploaded}/#{total}"
end
puts file.uuid
end
Signed uploads
You can enable signed uploads globally:
client = Uploadcare::Client.new(
public_key: "public",
secret_key: "secret",
sign_uploads: true
)
Or pass explicit signature data per request:
File.open("photo.jpg", "rb") do |io|
client.files.upload(io, signature: "signature", expire: 1_900_000_000)
end
Upload options
Common upload options:
store: true | false | "auto"metadata: { key: value }signature: "..."expire: unix_timestampasync: truefor URL uploadsthreads:andpart_size:for multipart uploads
If you prefer the older top-level style, the same flows can still be written through the global client:
Uploadcare.configure do |config|
config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
end
file = File.open("photo.jpg", "rb") do |io|
Uploadcare.files.upload(io, store: true)
end
Files
Find a file
file = client.files.find(uuid: "file-uuid")
List files
files = client.files.list(limit: 100)
files.each { |file| puts file.uuid }
List responses are Uploadcare::Collections::Paginated:
files.next_page
files.previous_page
files.all
Filters and API parameters can still be passed through:
files = client.files.list(stored: true, removed: false, limit: 100)
Resource operations
file.store
file.delete
file.reload
file.reload(params: { include: "appdata" })
Batch operations
result = client.files.batch_store(uuids: ["uuid-1", "uuid-2"])
puts result.status
puts result.result.map(&:uuid)
puts result.problems
The same shape applies to client.files.batch_delete.
Copy operations
copied = client.files.copy_to_local(source: file.uuid, options: { store: true })
remote_url = client.files.copy_to_remote(source: file.uuid, target: "custom_storage")
Instance-level variants are also available:
copied = file.copy_to_local(options: { store: true })
remote_url = file.copy_to_remote(target: "custom_storage")
Groups
Create a group:
group = client.groups.create(uuids: ["uuid-1", "uuid-2"])
Find and list groups:
group = client.groups.find(group_id: "group-uuid~2")
groups = client.groups.list(limit: 50)
Delete a group:
group.delete
Useful group helpers:
group.cdn_url
group.file_cdn_urls
Project
Fetch the current project:
project = client.project.current
puts project.name
puts project.pub_key
puts project.collaborators
Metadata
client..update(uuid: file.uuid, key: "category", value: "avatar")
client..show(uuid: file.uuid, key: "category")
client..index(uuid: file.uuid)
client..delete(uuid: file.uuid, key: "category")
Uploadcare::FileMetadata is also available as a resource if you need to hold metadata state locally.
Webhooks
webhook = client.webhooks.create(
target_url: "https://example.com/uploadcare",
event: "file.uploaded",
is_active: true
)
client.webhooks.list
client.webhooks.update(id: webhook.id, is_active: false)
client.webhooks.delete(target_url: webhook.target_url)
Add-ons
execution = client.addons.aws_rekognition_detect_labels(uuid: file.uuid)
client.addons.aws_rekognition_detect_labels_status(request_id: execution.request_id)
scan = client.addons.uc_clamav_virus_scan(uuid: file.uuid)
client.addons.uc_clamav_virus_scan_status(request_id: scan.request_id)
background = client.addons.remove_bg(uuid: file.uuid)
client.addons.remove_bg_status(request_id: background.request_id)
These methods return Uploadcare::AddonExecution resources.
Conversions
Document conversions:
info = client.conversions.documents.info(uuid: file.uuid)
job = client.conversions.documents.convert(uuid: file.uuid, format: :pdf)
status = client.conversions.documents.status(token: job.fetch("result").first.fetch("token"))
Video conversions:
job = client.conversions.videos.convert(uuid: file.uuid, format: :webm, quality: :normal)
status = client.conversions.videos.status(token: job.result.first.fetch("token"))
Document conversion convert returns the API response hash.
Video conversion convert returns a Uploadcare::VideoConversion resource.
Secure Delivery
The gem includes signed URL generators for delivery workflows.
generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(
cdn_host: "example.com",
secret_key: "your_hex_encoded_akamai_secret"
)
signed_url = generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
Custom ACL and wildcard examples:
generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", "/*")
generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", wildcard: true)
Errors and Results
The convenience layer raises exceptions:
Uploadcare::Exception::RequestErrorUploadcare::Exception::InvalidRequestErrorUploadcare::Exception::NotFoundErrorUploadcare::Exception::UploadErrorUploadcare::Exception::MultipartUploadErrorUploadcare::Exception::UploadTimeoutErrorUploadcare::Exception::ThrottleError
Example:
begin
client.files.find(uuid: "missing")
rescue Uploadcare::Exception::NotFoundError => e
warn e.
end
The raw API layer returns Uploadcare::Result:
result = client.api.rest.files.info(uuid: "file-uuid")
if result.success?
puts result.success
else
warn result.
end
Request Options
Most API calls accept request_options: and pass them to the HTTP layer.
Example:
client.files.find(uuid: "file-uuid", request_options: { timeout: 10 })
Use this when you need per-request timeout control without changing the client’s default configuration.
Raw API Access
The gem exposes full endpoint-level access through client.api.
REST API:
client.api.rest.files.list(params: { limit: 10 })
client.api.rest.files.info(uuid: "file-uuid")
client.api.rest.project.show
client.api.rest.webhooks.list
Upload API:
File.open("photo.jpg", "rb") do |io|
client.api.upload.files.direct(file: io, store: true)
end
client.api.upload.files.from_url(source_url: "https://example.com/image.jpg", async: true)
client.api.upload.groups.create(files: ["uuid-1", "uuid-2"])
Use this layer when you want exact control over the documented endpoints or when you are wrapping the gem from another library.
The raw layer is part of the public surface, but it is intentionally less promoted than client.files, client.groups, and the other convenience accessors.
Examples
- api_examples/README.md: one canonical script per documented REST and Upload API endpoint
- examples/README.md: workflow-oriented demos built on the public client API
Run examples with project-managed Ruby:
mise exec -- ruby api_examples/rest_api/get_project.rb
mise exec -- ruby examples/simple_upload.rb spec/fixtures/kitten.jpeg
Upgrading from v4.x
See: