Ruby SDK
The official Pictify SDK for Ruby provides an idiomatic Ruby interface for the Pictify API.Installation
Add to your Gemfile:gem 'pictify'
bundle install
gem install pictify
Quick Start
require 'pictify'
client = Pictify::Client.new('pk_live_your_api_key')
image = client.images.create(
html: '<h1 style="color: #667eea;">Hello World</h1>',
width: 1200,
height: 630
)
puts image['url']
Configuration
Basic Configuration
client = Pictify::Client.new('pk_live_your_api_key')
Advanced Configuration
client = Pictify::Client.new(
'pk_live_your_api_key',
base_url: 'https://api.pictify.io/v1',
timeout: 30,
max_retries: 3
)
Environment Variables
# Reads PICTIFY_API_KEY from environment
client = Pictify::Client.new(ENV['PICTIFY_API_KEY'])
Rails Configuration
# config/initializers/pictify.rb
Pictify.configure do |config|
config.api_key = Rails.application.credentials.pictify_api_key
config.timeout = 30
end
image = Pictify.images.create(html: '...', width: 1200, height: 630)
Images
Generate from HTML
image = client.images.create(
html: <<~HTML,
<div style="width: 1200px; height: 630px; background: #667eea;
display: flex; align-items: center; justify-content: center;">
<h1 style="color: white; font-size: 48px;">Hello World</h1>
</div>
HTML
width: 1200,
height: 630,
format: 'png'
)
puts image['url'] # https://cdn.pictify.io/renders/...
puts image['id'] # img_abc123
puts image['width'] # 1200
puts image['height'] # 630
Generate from URL
screenshot = client.images.create(
url: 'https://example.com',
width: 1200,
height: 630,
full_page: false
)
Canvas Rendering
image = client.images.canvas(
fabric_js_data: {
version: '5.3.0',
objects: [
{ type: 'rect', fill: '#667eea', width: 1200, height: 630 },
{ type: 'textbox', text: '{{title}}', fill: 'white', fontSize: 48 }
]
},
variables: { title: 'Dynamic Content' },
width: 1200,
height: 630
)
Agent Screenshot
screenshot = client.images.agent_screenshot(
prompt: 'Take a screenshot of the pricing section on stripe.com'
)
GIFs
Create from HTML
gif = client.gifs.create(
html: <<~HTML,
<div class="container">
<style>
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.pulse { animation: pulse 1s infinite; }
</style>
<div class="pulse">Animated!</div>
</div>
HTML
width: 400,
height: 400
)
Capture from URL
gif = client.gifs.capture(
url: 'https://example.com/animated',
width: 800,
height: 600,
quality: 'high',
frame_duration_seconds: 5
)
PDFs
Single Page
pdf = client.pdfs.render(
template_uid: 'tmpl_invoice',
variables: {
invoiceNumber: 'INV-001',
items: [{ name: 'Service', price: 99.00 }],
total: 99.00
},
options: {
preset: 'A4',
margins: { top: 40, bottom: 40, left: 30, right: 30 }
}
)
Multi-Page
pdf = client.pdfs.multi_page(
template_uid: 'tmpl_report',
variable_sets: [
{ pageTitle: 'Introduction', content: '...' },
{ pageTitle: 'Analysis', content: '...' },
{ pageTitle: 'Conclusion', content: '...' }
],
options: { preset: 'A4' }
)
Templates
List Templates
result = client.templates.list(page: 1, limit: 20)
templates = result['templates']
pagination = result['pagination']
Create Template
template = client.templates.create(
name: 'Social Card',
html: '<h1>{{title}}</h1><p>{{description}}</p>',
width: 1200,
height: 630
)
Render Template
image = client.templates.render(
'tmpl_abc123',
variables: {
title: 'My Post',
description: 'An interesting article'
},
format: 'png'
)
Get Variables
result = client.templates.get_variables('tmpl_abc123')
variables = result['variables']
# [{ 'name' => 'title', 'type' => 'string', 'required' => true }, ...]
Batch Render
batch = client.templates.batch_render(
'tmpl_abc123',
variable_sets: [
{ title: 'Post 1' },
{ title: 'Post 2' },
{ title: 'Post 3' }
],
webhook_url: 'https://your-server.com/webhooks/batch'
)
# Later, get results
results = client.templates.get_batch_results(batch['id'])
Webhooks
Create Subscription
subscription = client.webhooks.create(
event: 'render.completed',
target_url: 'https://your-server.com/webhooks/pictify'
)
# Store this secret securely!
puts subscription['secret']
Verify Signature
require 'openssl'
def verify_webhook_signature(payload, signature_header, secret)
parts = signature_header.split(',').map { |p| p.split('=') }.to_h
timestamp = parts['t'].to_i
provided_signature = parts['v1']
# Reject if timestamp is older than 5 minutes
if (Time.now.to_i - timestamp).abs > 300
raise 'Webhook timestamp too old'
end
signed_payload = "#{timestamp}.#{payload}"
expected_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, signed_payload)
Rack::Utils.secure_compare(provided_signature, expected_signature)
end
Rails Controller
# app/controllers/webhooks_controller.rb
class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def pictify
signature = request.headers['X-Pictify-Signature']
payload = request.raw_post
begin
unless verify_webhook_signature(payload, signature, ENV['PICTIFY_WEBHOOK_SECRET'])
return head :unauthorized
end
event = JSON.parse(payload)
Rails.logger.info "Received Pictify event: #{event['event']}"
# Handle the event
case event['event']
when 'render.completed'
handle_render_completed(event['data'])
when 'render.failed'
handle_render_failed(event['data'])
end
head :ok
rescue => e
Rails.logger.error "Webhook error: #{e.message}"
head :bad_request
end
end
private
def verify_webhook_signature(payload, signature_header, secret)
# ... signature verification code
end
def handle_render_completed(data)
# Update your records, notify users, etc.
end
def handle_render_failed(data)
# Log error, retry, notify, etc.
end
end
Sinatra Example
require 'sinatra'
require 'json'
post '/webhooks/pictify' do
signature = request.env['HTTP_X_PICTIFY_SIGNATURE']
payload = request.body.read
begin
unless verify_webhook_signature(payload, signature, ENV['WEBHOOK_SECRET'])
halt 401, 'Invalid signature'
end
event = JSON.parse(payload)
puts "Received event: #{event['event']}"
status 200
'OK'
rescue => e
halt 400, e.message
end
end
Bindings
Create Binding
binding = client.bindings.create(
name: 'GitHub Stats',
template_uid: 'tmpl_github',
data_url: 'https://api.github.com/repos/your/repo',
data_mapping: {
stars: 'stargazers_count',
forks: 'forks_count'
},
schedule: '0 * * * *' # Hourly
)
# Permanent image URL that auto-updates
puts binding['imageUrl']
Trigger Refresh
client.bindings.refresh('bind_abc123')
Error Handling
begin
image = client.images.create(...)
rescue Pictify::RateLimitError => e
# Wait and retry
puts "Rate limited. Retry after #{e.retry_after}s"
sleep(e.retry_after)
retry
rescue Pictify::ValidationError => e
# Fix validation issues
puts "Validation errors: #{e.errors}"
rescue Pictify::AuthenticationError
# Check API key
puts "Invalid API key"
rescue Pictify::APIError => e
# General API error
puts "API Error: #{e.message} (status: #{e.status})"
end
Rails Integration
Model Concern
# app/models/concerns/pictify_renderable.rb
module PictifyRenderable
extend ActiveSupport::Concern
included do
after_commit :generate_og_image, on: [:create, :update], if: :should_regenerate_og_image?
end
def og_image_url
return unless og_image_id
"https://cdn.pictify.io/renders/#{og_image_id}.png"
end
private
def should_regenerate_og_image?
saved_change_to_title? || saved_change_to_description?
end
def generate_og_image
GenerateOgImageJob.perform_later(self.class.name, id)
end
end
Background Job
# app/jobs/generate_og_image_job.rb
class GenerateOgImageJob < ApplicationJob
queue_as :default
def perform(model_class, model_id)
record = model_class.constantize.find(model_id)
image = Pictify.templates.render(
'tmpl_og',
variables: {
title: record.title,
description: record.description,
author: record.author&.name
}
)
record.update!(og_image_id: image['id'])
end
end
View Helper
# app/helpers/pictify_helper.rb
module PictifyHelper
def pictify_og_image(record)
return unless record.respond_to?(:og_image_url) && record.og_image_url
tag.meta property: 'og:image', content: record.og_image_url
end
end