PDF generation in Rails usually means pdf-kit (which wraps wkhtmltopdf and requires a system binary), Prawn (a programmatic builder with no HTML support), or WickedPDF — all of which add server dependencies or rendering limitations.
A hosted REST API removes every constraint. You send HTML, you get PDF bytes back. No gem native extensions, no binary on your server, no Docker image bloat.
Make the Request with Net::HTTP
Ruby's standard library handles this cleanly. No additional gems required:
require 'net/http'
require 'json'
class PdfService
API_URI = URI('https://platform.htmltopdfapi.co/api/v1/pdf/generate').freeze
def self.from_html(html, paper_size: 'a4', orientation: 'portrait')
http = Net::HTTP.new(API_URI.host, API_URI.port)
http.use_ssl = true
req = Net::HTTP::Post.new(API_URI.path)
req['Authorization'] = "Bearer #{ENV.fetch('HTMLTOPDF_API_KEY')}"
req['Content-Type'] = 'application/json'
req['Accept'] = 'application/pdf'
req.body = { html:, paper_size:, orientation: }.to_json
res = http.request(req)
raise "PDF API error #{res.code}" unless res.code == '200'
res.body
end
endStream from a Rails Controller
class InvoicesController < ApplicationController
def download
@invoice = Invoice.find(params[:id])
authorize @invoice
html = render_to_string('invoices/pdf', layout: false)
bytes = PdfService.from_html(html)
send_data bytes,
type: 'application/pdf',
disposition: 'inline',
filename: "invoice-#{@invoice.number}.pdf"
end
endOr Use Faraday
If you're already using Faraday in your app:
conn = Faraday.new('https://platform.htmltopdfapi.co') do |f|
f.response :raise_error
end
res = conn.post('/api/v1/pdf/generate') do |req|
req.headers['Authorization'] = "Bearer #{ENV.fetch('HTMLTOPDF_API_KEY')}"
req.headers['Content-Type'] = 'application/json'
req.headers['Accept'] = 'application/pdf'
req.body = { html:, paper_size: 'a4' }.to_json
end
pdf_bytes = res.bodyWhat You Remove
Switching to a REST API removes wkhtmltopdf and its system-level dependencies from every server and Docker image. Your buildpack config disappears, your images shrink, and rendering keeps pace with modern CSS automatically. The engine is updated on the API side.