Documentation
Render anything in three calls.
Authenticate with a key, then send a URL or HTML. Every endpoint returns the file directly — no polling, no webhooks, no SDK to install.
Quickstart
Create a free key (email-verified, 500 renders a month, no card), then make your first call. The response body is the image.
# a full-page screenshot, saved as PNG curl -X POST https://renderkit.keelhelm.com/v1/screenshot \ -H "Authorization: Bearer sk_your_key" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com","full_page":true}' \ --output shot.png
// app/api/shot/route.ts — Next.js route handler export async function GET() { const r = await fetch("https://renderkit.keelhelm.com/v1/screenshot", { method: "POST", headers: { Authorization: `Bearer ${process.env.RENDERKIT_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://example.com" }), }); return new Response(r.body, { headers: { "Content-Type": "image/png" } }); }
// src/pages/shot.png.ts — Astro endpoint export const GET = async () => fetch("https://renderkit.keelhelm.com/v1/screenshot", { method: "POST", headers: { Authorization: `Bearer ${import.meta.env.RENDERKIT_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://example.com" }), });
Authentication
Pass your secret key as a bearer token: Authorization: Bearer sk_…. Keys are created at signup and scoped to your account. For Open Graph images you embed in HTML, use your public key plus a signature (see below) so the secret never appears in a URL.
Screenshot
POST /v1/screenshot
Capture any URL or your own HTML as a PNG or JPEG. Viewport by default; full-page on request.
| Field | Type | Notes |
|---|---|---|
url / html | string | One is required (not both). |
full_page | boolean | Capture the whole scroll height. Counts as 2 renders. |
format | png · jpeg | Defaults to png. |
viewport_width / viewport_height | number | Defaults 1280 × 800. |
response | binary · url | Image bytes, or a JSON link to the cached result. |
POST /v1/pdf
Turn a live page or your own markup into a paginated PDF. Counts as 2 renders.
| Field | Type | Notes |
|---|---|---|
url / html | string | One is required. |
format | A4 · Letter | Defaults to A4. |
landscape | boolean | Defaults to false. |
margin_mm | number | Uniform page margin in millimetres. |
curl -X POST https://renderkit.keelhelm.com/v1/pdf \ -H "Authorization: Bearer sk_your_key" -H "Content-Type: application/json" \ -d '{"url":"https://example.com","format":"A4"}' --output page.pdf
Open Graph image
GET /v1/og/:template.png
Generate the preview image that appears when a link is shared, from a reusable template. Because it's a plain GET, you embed it with a single tag — pass your public key and a signature so the URL is safe to ship in your HTML.
<!-- in your page <head> --> <meta property="og:image" content="https://renderkit.keelhelm.com/v1/og/blog-header.png?title=Hello&pk=pk_you&sig=…">
Browse the template gallery for every template, its parameters, and a live example. Identical parameters return instantly from cache.
Limits & units
A screenshot or Open Graph image is one render; a full-page capture or a PDF is two; a cache hit is zero. Plans set a monthly render budget plus a per-minute rate — see pricing. Identical requests are served from cache and never counted.
Errors
Every error returns JSON: {"error":{"code","message","doc_url"}} with the right HTTP status.
| Code | Status | Meaning |
|---|---|---|
unauthorized | 401 | Missing or invalid key. |
bad_signature | 401 | Open Graph signature didn't match the parameters. |
blocked_target | 400 | The target URL isn't allowed (private/reserved address). |
rate_limited | 429 | Too many requests this minute — slow down. |
quota_exceeded | 429 | Monthly render budget reached. |
payload_too_large | 413 | Inline HTML exceeds 2 MB. |
render_failed | 500 | The page couldn't be rendered — retry. |