Official SDK

Ruby

Ruby 2.7+ with Rails integration and idiomatic Ruby patterns. Clean API design with automatic retries and proper exception handling.

Ruby 2.7+MIT licensed

Rename PDFs, split multi-page documents, and extract structured data using the official Ruby SDK for Renamed.to.

  1. 1Add gem "renamed" to your Gemfile or run gem install renamed
  2. 2Call rename(), pdf_split(), or extract() with PDF bytes
  3. 3Integrate with Rails using the built-in generator and initializer

MIT licensed, open source on GitHub, published on RubyGems.

Installation

Shell
gem install renamed

Quickstart

Initialize the client and start making API calls.

example.rb
Ruby
require 'renamed'# Initialize the clientclient = Renamed::Client.new(api_key: ENV['RENAMED_API_KEY'])# Rename a PDFresult = client.rename(File.read('invoice.pdf'))puts result.suggested_filename# -> "2024-01-15_AcmeCorp_INV-1234.pdf"# Split a multi-page PDFjob = client.pdf_split(File.read('documents.pdf'), mode: 'smart')puts job.documents# -> [{ filename: "...", download_url: "..." }, ...]# Extract structured datadata = client.extract(File.read('receipt.pdf'))puts data# -> { vendor: "...", date: "...", amount: "..." }

Rename a PDF

Pass PDF bytes to get an AI-generated filename. Use custom instructions to control the naming format.

rename.rb
Ruby
require 'renamed'# Initialize the clientclient = Renamed::Client.new(api_key: ENV['RENAMED_API_KEY'])# Read the PDF filepdf_bytes = File.binread('./documents/invoice.pdf')# Rename the PDFresult = client.rename(pdf_bytes)puts "Suggested filename: #{result.suggested_filename}"puts "Confidence: #{result.confidence}"# Output:# Suggested filename: 2024-01-15_AcmeCorp_INV-1234.pdf# Confidence: 0.95# Access extracted metadataputs "Vendor: #{result.metadata[:vendor]}"puts "Date: #{result.metadata[:date]}"puts "Type: #{result.metadata[:type]}"# Use custom naming instructionscustom_result = client.rename(pdf_bytes,  instructions: 'Format: YYYY-MM-DD_VendorName_Amount')puts custom_result.suggested_filename# -> "2024-01-15_AcmeCorp_$1250.pdf"# Rename from a URLurl_result = client.rename_from_url('https://example.com/document.pdf')# Use a block for cleaner file handlingresult = File.open('./documents/invoice.pdf', 'rb') do |file|  client.rename(file.read)end

Split a PDF

Split multi-page PDFs into separate documents. The API uses async jobs for large files—poll for completion or use the built-in wait helper.

split.rb
Ruby
require 'renamed'require 'fileutils'client = Renamed::Client.new(api_key: ENV['RENAMED_API_KEY'])# Read a multi-page PDFpdf_bytes = File.binread('./documents/combined.pdf')# Submit the split job with smart mode (AI detects document boundaries)job = client.pdf_split(pdf_bytes, mode: 'smart')puts "Job ID: #{job.job_id}"puts "Status: #{job.state}"# Option 1: Wait for completion (built-in polling)completed = job.wait_for_completion# Option 2: Manual polling for progress updates# while job.state == 'processing'#   puts "Progress: #{job.progress}%"#   sleep 1#   job = client.get_job(job.job_id)# end# Process the split documentsputs "Split into #{completed.documents.length} documents:"completed.documents.each_with_index do |doc, i|  puts "  [#{i + 1}] #{doc.filename} (pages #{doc.pages.join(', ')})"  # Output:  # [1] invoice_1.pdf (pages 1, 2)  # [2] invoice_2.pdf (pages 3, 4)  # Download each split document  doc_bytes = client.download_file(doc.download_url)  # Save to output directory  output_path = File.join('./output', doc.filename)  FileUtils.mkdir_p(File.dirname(output_path))  File.binwrite(output_path, doc_bytes)  puts "  Saved: #{output_path}"end# With a timeoutcompleted = job.wait_for_completion(timeout: 300) # 5 minutes

Extract Data

Extract structured data from invoices, receipts, and other documents. Use Ruby structs or classes for type-safe extraction.

extract.rb
Ruby
require 'renamed'# Define typed structs for invoice extractionLineItem = Struct.new(:description, :quantity, :unit_price, keyword_init: true)Invoice = Struct.new(  :invoice_number,  :vendor,  :date,  :line_items,  :subtotal,  :tax,  :total,  keyword_init: true)# Initialize the clientclient = Renamed::Client.new(api_key: ENV['RENAMED_API_KEY'])# Read the PDF filepdf_bytes = File.binread('./documents/invoice.pdf')# Basic extraction (returns a Hash with symbol keys)data = client.extract(pdf_bytes)puts "Vendor: #{data[:vendor]}"puts "Date: #{data[:date]}"puts "Total: #{data[:total]}"# Output:# Vendor: Acme Corp# Date: 2024-01-15# Total: 1250.00# Typed extraction: convert to a structline_items = data[:line_items].map do |item|  LineItem.new(    description: item[:description],    quantity: item[:quantity],    unit_price: item[:unit_price]  )endinvoice = Invoice.new(  invoice_number: data[:invoice_number],  vendor: data[:vendor],  date: data[:date],  line_items: line_items,  subtotal: data[:subtotal],  tax: data[:tax],  total: data[:total])# Now you have typed accessputs "Invoice ##{invoice.invoice_number} from #{invoice.vendor}"puts "Line items: #{invoice.line_items.length}"invoice.line_items.each do |item|  puts "  - #{item.description}: #{item.quantity} x $#{'%.2f' % item.unit_price}"endputs "Total: $#{'%.2f' % invoice.total}"# Output:# Invoice #INV-2024-1234 from Acme Corp# Line items: 2#   - Widget Pro: 5 x $199.00#   - Support Plan: 1 x $342.50# Total: $1337.50

Framework Integrations

Common integration patterns for popular frameworks.

Rails Controller

Handle PDF uploads in a Rails controller with proper error handling and response formatting.

app/controllers/api/documents_controller.rb
Ruby
# app/controllers/api/documents_controller.rbmodule Api  class DocumentsController < ApplicationController    before_action :validate_file, only: [:rename, :split, :extract]    # POST /api/documents/rename    def rename      result = renamed_client.rename(        file_param.read,        instructions: params[:instructions]      )      render json: {        suggested_filename: result.suggested_filename,        confidence: result.confidence,        metadata: result.metadata      }    rescue Renamed::RateLimitError => e      response.headers['Retry-After'] = e.retry_after.to_s      render json: { error: 'Rate limited', retry_after: e.retry_after }, status: :too_many_requests    rescue Renamed::ApiError => e      render json: { error: e.message, code: e.code }, status: :bad_gateway    end    # POST /api/documents/split    def split      job = renamed_client.pdf_split(        file_param.read,        mode: params[:mode] || 'smart'      )      completed = job.wait_for_completion      render json: {        job_id: completed.job_id,        documents: completed.documents.map do |doc|          {            filename: doc.filename,            pages: doc.pages,            download_url: doc.download_url          }        end      }    rescue Renamed::ApiError => e      render json: { error: e.message }, status: :bad_gateway    end    # POST /api/documents/extract    def extract      data = renamed_client.extract(file_param.read)      render json: data    rescue Renamed::ApiError => e      render json: { error: e.message }, status: :bad_gateway    end    private    def file_param      params.require(:file)    end    def validate_file      unless file_param.present?        render json: { error: 'No file provided' }, status: :bad_request        return      end      unless file_param.content_type == 'application/pdf'        render json: { error: 'Only PDF files are supported' }, status: :bad_request        return      end    end    def renamed_client      @renamed_client ||= Renamed::Client.new    end  endend

Rails Initializer

Configure the SDK globally in a Rails initializer with environment-based settings.

config/initializers/renamed.rb
Ruby
# config/initializers/renamed.rbRenamed.configure do |config|  # API key from Rails credentials or environment  config.api_key = Rails.application.credentials.dig(:renamed, :api_key) ||                   ENV['RENAMED_API_KEY']  # Request timeout in seconds  config.timeout = 30  # Number of automatic retries for transient errors  config.max_retries = 3  # Custom logger (optional, defaults to Rails.logger in Rails apps)  config.logger = Rails.logger  # Base URL override (optional, for testing or custom endpoints)  # config.base_url = 'https://api.renamed.to/v1'end# Verify configuration on startup (optional)Rails.application.config.after_initialize do  unless Renamed.configuration.api_key.present?    Rails.logger.warn '[Renamed] API key not configured!'  endend

Active Job Integration

Process PDF files asynchronously using Active Job for background processing.

app/jobs/rename_document_job.rb
Ruby
# app/jobs/rename_document_job.rbclass RenameDocumentJob < ApplicationJob  queue_as :documents  retry_on Renamed::RateLimitError, wait: :polynomially_longer, attempts: 5  discard_on Renamed::InvalidFileError  def perform(document_id)    document = Document.find(document_id)    # Download the file from storage    pdf_bytes = document.file.download    # Rename via the API    result = Renamed::Client.new.rename(      pdf_bytes,      instructions: document.naming_instructions    )    # Update the document record    document.update!(      suggested_filename: result.suggested_filename,      confidence: result.confidence,      metadata: result.metadata,      processed_at: Time.current    )    # Notify the user    DocumentMailer.rename_complete(document).deliver_later  rescue Renamed::ApiError => e    document.update!(      processing_error: e.message,      processed_at: Time.current    )    raise # Re-raise to trigger job retry  endend# app/jobs/split_document_job.rbclass SplitDocumentJob < ApplicationJob  queue_as :documents  retry_on Renamed::RateLimitError, wait: :polynomially_longer, attempts: 5  def perform(document_id, mode: 'smart')    document = Document.find(document_id)    pdf_bytes = document.file.download    # Start the split job    job = Renamed::Client.new.pdf_split(pdf_bytes, mode: mode)    # Poll for completion (job handles this internally)    completed = job.wait_for_completion(timeout: 600) # 10 minutes    # Create child documents for each split    completed.documents.each do |doc|      doc_bytes = Renamed::Client.new.download_file(doc.download_url)      child = document.children.create!(        filename: doc.filename,        pages: doc.pages      )      child.file.attach(        io: StringIO.new(doc_bytes),        filename: doc.filename,        content_type: 'application/pdf'      )    end    document.update!(      split_completed_at: Time.current,      split_document_count: completed.documents.length    )  endend

Error Handling

The SDK raises Ruby exceptions that you can rescue and handle appropriately. Use begin/rescue blocks for error handling.

error_handling.rb
Ruby
require 'renamed'client = Renamed::Client.new(api_key: ENV['RENAMED_API_KEY'])begin  pdf_bytes = File.binread('invoice.pdf')  result = client.rename(pdf_bytes)  puts "Renamed to: #{result.suggested_filename}"rescue Renamed::RateLimitError => e  # Rate limited - wait and retry  puts "Rate limited. Retry after #{e.retry_after} seconds"  sleep e.retry_after  # Retry the request...rescue Renamed::InvalidFileError => e  # File is not a valid PDF or is corrupted  puts "Invalid file: #{e.message}"rescue Renamed::AuthenticationError => e  # API key is invalid or expired  puts "Authentication failed: #{e.message}"rescue Renamed::ApiError => e  # Other API errors  puts "API Error [#{e.code}]: #{e.message}"  puts "Details: #{e.details}" if e.detailsrescue Renamed::NetworkError => e  # Network/connection errors  puts "Network error: #{e.message}"rescue StandardError => e  # Other errors (file I/O, etc.)  puts "Unexpected error: #{e.message}"end# Using retry with exponential backoffdef rename_with_retry(client, pdf_bytes, max_retries: 3)  retries = 0  begin    client.rename(pdf_bytes)  rescue Renamed::RateLimitError => e    retries += 1    raise if retries > max_retries    sleep_time = e.retry_after || (2 ** retries)    puts "Rate limited, retrying in #{sleep_time}s (attempt #{retries}/#{max_retries})"    sleep sleep_time    retry  rescue Renamed::ApiError => e    retries += 1    raise if retries > max_retries || !e.retryable?    sleep_time = 2 ** retries    puts "API error, retrying in #{sleep_time}s (attempt #{retries}/#{max_retries})"    sleep sleep_time    retry  endend

Full documentation on GitHub

For more examples, advanced usage patterns, and detailed API documentation, see the full Ruby SDK README on GitHub.

Read the Ruby SDK docs

Frequently asked questions

What Ruby versions are supported?
The Ruby SDK supports Ruby 2.7 and above. It works with both MRI Ruby and JRuby.
Does it integrate with Rails?
Yes, the SDK includes a Rails generator for easy configuration. Run rails g renamed:install to set up the initializer.
How do I handle errors?
The SDK raises Ruby exceptions that you can rescue. Specific error types include Renamed::RateLimitError and Renamed::APIError.
Is the client thread-safe?
Yes, the Renamed::Client is thread-safe. You can share a single instance across threads or create new instances as needed.
Does it support file uploads from Active Storage?
Yes, you can use document.file.download to get bytes from Active Storage and pass them to the SDK methods.

Related resources

Other languages