API Documentation

Everything you need to generate screenshots and images with Rendly.

Base URL: https://rendly-api.fly.dev

Authentication

All API requests require a Bearer token in the Authorization header.

Authorization: Bearer ren_live_your_api_key_here

Get your API key by registering an account, or from the dashboard.

Quick Start

Take a screenshot in your language of choice:

Node.js

const res = await fetch('https://rendly-api.fly.dev/api/v1/screenshots', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ url: 'https://example.com' })
});
const data = await res.json();
console.log(data.image_url);

Python

import requests

resp = requests.post('https://rendly-api.fly.dev/api/v1/screenshots',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={'url': 'https://example.com'})
print(resp.json()['image_url'])

Ruby

require 'net/http'
require 'json'

uri = URI('https://rendly-api.fly.dev/api/v1/screenshots')
req = Net::HTTP::Post.new(uri, 'Authorization' => 'Bearer YOUR_API_KEY',
                                'Content-Type' => 'application/json')
req.body = { url: 'https://example.com' }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts JSON.parse(res.body)['image_url']

Error Codes

CodeMeaning
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing API key
404Not found — resource doesn't exist
422Unprocessable — validation failed
429Rate limited — too many requests
500Server error — something went wrong on our end

Error responses include a JSON body:

{ "error": "Plan limit reached. Upgrade at /api/v1/billing/checkout" }

Rate Limits

API requests are limited to 60 requests per minute per API key. Additionally, renders are limited by your plan's monthly allowance.

Screenshots

POST /api/v1/screenshots

Capture a screenshot of any URL.

Parameters

ParamTypeRequiredDescription
urlstringYesURL to screenshot
viewportobjectNo{ width, height } — default 1280×720
device_scalenumberNo1 or 2 (retina) — default 1
formatstringNopng, jpeg, webp — default png
full_pagebooleanNoCapture full scrollable page
selectorstringNoCSS selector to crop to
wait_forstringNoCSS selector to wait for before capture
delay_msnumberNoExtra delay after page load (ms)
dark_modebooleanNoEmulate dark color scheme
custom_cssstringNoInject custom CSS
custom_jsstringNoInject custom JavaScript

Example

curl -X POST https://rendly-api.fly.dev/api/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "viewport": {"width": 1280, "height": 720},
    "format": "png",
    "device_scale": 2
  }'

Response

{
  "id": "render_abc123",
  "status": "completed",
  "url": "https://cdn.rendly.io/render_abc123.png",
  "width": 2560,
  "height": 1440,
  "format": "png",
  "render_time_ms": 1240,
  "created_at": "2026-02-14T15:00:00Z"
}

HTML to Image

POST /api/v1/images

Render HTML/CSS to an image.

Parameters

ParamTypeRequiredDescription
htmlstringYesHTML content to render
cssstringNoCSS styles to apply
viewportobjectNo{ width, height } — default 1200×630
device_scalenumberNo1 or 2 (retina)
formatstringNopng, jpeg, webp
google_fontsarrayNoGoogle Fonts to load
selectorstringNoCSS selector to crop to

Example

curl -X POST https://rendly-api.fly.dev/api/v1/images \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "
Hello World
", "viewport": {"width": 1200, "height": 630}, "format": "png" }'

Templates

GET /api/v1/templates

List all available templates (built-in and custom).

curl https://rendly-api.fly.dev/api/v1/templates \
  -H "Authorization: Bearer YOUR_API_KEY"
POST /api/v1/templates

Create a custom template (paid plans).

curl -X POST https://rendly-api.fly.dev/api/v1/templates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Blog Card",
    "slug": "blog-card",
    "html": "
{{ title }} by {{ author }}
", "css": "div { font-size: 32px; padding: 40px; }", "variables_schema": { "title": {"type": "string", "required": true}, "author": {"type": "string", "required": true} } }'

Render Template

POST /api/v1/templates/:id/render

Render a template with variables.

curl -X POST https://rendly-api.fly.dev/api/v1/templates/og-blog-post/render \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "variables": {
      "title": "How to Build an API",
      "author": "Thomas",
      "date": "Feb 14, 2026",
      "read_time": "5 min"
    },
    "format": "png"
  }'

Usage

GET /api/v1/usage

Check current usage and plan limits.

curl https://rendly-api.fly.dev/api/v1/usage \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "plan": "free",
  "renders_used": 42,
  "renders_limit": 100,
  "overage_count": 0,
  "period_start": "2026-02-01",
  "period_end": "2026-02-28"
}

Billing

POST /api/v1/billing/checkout

Create a Stripe checkout session to upgrade your plan.

curl -X POST https://rendly-api.fly.dev/api/v1/billing/checkout \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plan": "growth"}'
POST /api/v1/billing/portal

Get a Stripe customer portal URL to manage your subscription.

Register

POST /auth/register

Create an account and get your first API key.

curl -X POST https://rendly-api.fly.dev/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com",
    "password": "securepassword",
    "password_confirmation": "securepassword"
  }'

Response

{
  "user": {"id": 1, "email": "dev@example.com"},
  "api_key": {"id": 1, "key": "ren_live_abc123...", "name": null}
}

API Keys

POST /auth/api_keys

Create an additional API key.

curl -X POST https://rendly-api.fly.dev/auth/api_keys \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "production"}'
DELETE /auth/api_keys/:id

Revoke an API key.