Documentation Index
Fetch the complete documentation index at: https://docs.pictify.io/llms.txt
Use this file to discover all available pages before exploring further.
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