Code samples:

propzapi API reference

An image generation API. Send a template and your data, get back a rendered PNG, JPEG or WebP. Base URL https://api.propzapi.com. Every response is JSON, and the image comes back as a URL. propzapi renders your own HTML templates with headless Chromium; there is no design tool to log into.

Overview

A template is HTML and CSS with {{variable}} placeholders. You render it by POSTing its id plus a small object of values; the engine fills the placeholders, rasterises the page, and returns a URL to the image. Fourteen templates ship built in (including a QR code card), and you can create your own. Authenticate with an API key in a header, and read the exact credit cost of every render from a response header.

Base URLhttps://api.propzapi.com
AuthX-API-Key header
OutputPNG / JPEG / WebP / PDF
Free trial50 images, no card

Quickstart

Get a free key with one POST (no card), then render an image. Under a minute end to end.

# 1. get a free key
curl -X POST https://api.propzapi.com/v1/register
# → { "api_key": "pk_live_…", "plan": "free", "credits": 50 }

# 2. render an image
curl -X POST https://api.propzapi.com/v1/images \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"template":"og-article","modifications":{"title":"Hello from propzapi"}}'
# → { "url": "…/renders/img_….png", "width": 1200, "height": 630, "format": "png" }

Authentication

Every /v1 request needs your key in the X-API-Key header. Create and revoke keys in the dashboard. A missing or invalid key returns 401. Keys are secret; keep them server-side.

X-API-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxx

Credits & metering

One credit renders one image. Listing templates and all template CRUD are free. Metering is billed on delivery: you are charged only when a render succeeds, so a failed render returns X-Credits-Cost: 0. Every render also returns your balance in X-Credits-Remaining.

PlanImages / monthPrice
Free trial50 (one-time)$0, no card
Starter1,000$29
Growth3,500$79
Pro12,000$199

Plan credits refresh each billing cycle and do not roll over. Pay-as-you-go packs ($5 → 150 images, $15 → 500) never expire and need no subscription. Full detail on pricing.

Templates

A template holds your HTML and CSS with {{variable}} placeholders and a set of default values. When you render, your modifications override the defaults. Templates render through a sandboxed template engine, so they can branch and loop over your data — see Templating.

Fourteen built-in templates get you started — social cards, quotes, a thumbnail, testimonial, stat, ticket, code card, certificate, story, a QR code card, plus bar / line / donut charts (gallery). They embed the Inter font, so they render identically on any host.
Your own templates are created over the API and stored per account. Limits: width and height 16 to 4000px, HTML up to 100 KB, up to 200 templates per account.
External images in a template load over the public internet only. Requests that resolve to a private or internal address are blocked, so a template cannot be used to probe internal networks.

Templating

Templates render through sandboxed Jinja2, so a template plus an array of data becomes a table, a list, or a chart — not just fill-in-the-blank text.

{{ variable }} · inserted and HTML-escaped. Use {{ variable|safe }} to allow raw HTML.
{% if x %}…{% endif %} · render a block only when a value is set.
{% for row in rows %}…{% endfor %} · loop over an array — tables, lists, leaderboards, charts.
Filters · upper, truncate(40), default("—"), plus number, currency, date.
{% for item in items %}
  <li>{{ item.name }} — {{ item.price|currency }}</li>
{% endfor %}
Total: {{ items|sum(attribute='price')|currency }}

Output & headers

POST /v1/images returns a small JSON object; the image itself is at url. Two headers ride on every render:

X-Credits-Cost · the credits this render charged (0 if it failed)
X-Credits-Remaining · your balance after the render
X-Cache · hit when an identical render (same template + data + format) was served from cache at the same URL, else miss
{ "url": "…/renders/img_9f2c.png", "template": "og-article",
  "width": 1200, "height": 630, "format": "png", "bytes": 91842 }

Errors

Errors return a JSON envelope with a detail message and the matching HTTP status.

{ "detail": "Unknown template 'nope'. See GET /v1/templates." }
CodeMeaning
400Bad request (unknown template, bad format, invalid dimensions)
401Missing or invalid API key
402Out of credits. Top up or upgrade.
404Template not found (or not yours)
429Rate limited (too many keys minted from this IP)
502Render failed. Never charged.

POST /v1/images

Render an image from a template and your data. Returns a URL to the image.

template · required. A built-in id (og-article, quote-square) or one of your tpl_… ids.
modifications · object of variable → value overrides. Any variable you omit uses the template's default.
format · png (default), jpeg, webp or pdf (a one-page PDF at the template's size).
scale · 1 to 3, the device-pixel ratio. 2 doubles the output resolution (raster formats).
quality · 1 to 100, for jpeg and webp.
curl -X POST https://api.propzapi.com/v1/images \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"template":"og-article","format":"png","scale":2,
       "modifications":{"title":"How we cut render costs by 95%","eyebrow":"ENGINEERING"}}'

POST /v1/images/batch

Render many images in one call — the bulk "a card for every row" job. Send an array of up to 25 render specs, each the same shape as /v1/images. You get a result per item and pay one credit only for each image that actually renders; items that error, or that you can't afford, cost nothing and come back as per-item errors.

curl -X POST https://api.propzapi.com/v1/images/batch \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"images":[
        {"template":"og-article","modifications":{"title":"First post"}},
        {"template":"og-article","modifications":{"title":"Second post"}}
      ]}'
# → { "count": 2, "rendered": 2, "failed": 0, "credits_cost": 2,
#     "results": [ {"url":"…/img_….png","format":"png","bytes":95332}, {"url":"…"} ] }

POST /v1/screenshot

Screenshot any public web page to an image, or print it to a PDF — same engine and 1-credit meter as a template render. Private, localhost and cloud-metadata targets are blocked.

url · required. A public http(s) URL.
full_page · capture the whole scrollable page (default false = just the viewport).
width / height · viewport, 16 to 4000 (default 1280 × 800).
format · png (default), jpeg, webp or pdf. scale 1 to 3.
paper · when format:pdfA4 (default), A3, A5, Letter, Legal, Tabloid or Ledger. landscape optional.
curl -X POST https://api.propzapi.com/v1/screenshot \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","full_page":true}'
# → { "url": "…/renders/shot_….png", "source": "https://example.com", "format": "png" }

# Same URL, printed to a paginated A4 PDF:
curl -X POST https://api.propzapi.com/v1/screenshot \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","format":"pdf","paper":"A4"}'
# → { "url": "…/renders/shot_….pdf", "source": "https://example.com", "format": "pdf", "paper": "A4" }

Embed URLs — a template as an og:image

Turn a template into a URL you drop straight into <meta og:image>. Sign it once; the URL renders on first fetch and is cached and free on every refetch after that (crawlers hit og:image constantly). Only the first render costs a credit, and the signature stops anyone forging a different render on your account.

curl -X POST https://api.propzapi.com/v1/embed-url \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{"template":"og-article","modifications":{"title":"How we cut render costs by 95%"}}'
# → { "url": "…/v1/og/og-article?title=…&a=…&sig=…",
#     "og_image_tag": "<meta property=\"og:image\" content=\"…\">" }

Drop the returned og_image_tag into your page <head> and every share preview renders itself — no build step, no storing a URL per page.

Template CRUD

Create and manage the templates you render from. Every one of these is scoped to your account; you can only read and change your own.

Method & pathDoes
POST /v1/templatesCreate a template: name, width, height, html, variables. Returns its tpl_… id.
GET /v1/templatesList built-in templates plus your own.
GET /v1/templates/{id}One template, including its HTML.
PATCH /v1/templates/{id}Update any of name, width, height, html, variables.
DELETE /v1/templates/{id}Delete your template.
curl -X POST https://api.propzapi.com/v1/templates \
  -H "X-API-Key: pk_live_…" -H "Content-Type: application/json" \
  -d '{
    "name": "Product card",
    "width": 1200, "height": 675,
    "html": "<div style=\"font:700 72px sans-serif;padding:80px\">{{title}}</div>",
    "variables": { "title": "Default title" }
  }'
# → { "template": "tpl_9c3f…", "name": "Product card", "width": 1200, "height": 675 }

Iterating on a template? POST /v1/templates/preview renders your HTML (or a template id) and returns a data: image without spending a credit — for live preview while you edit. It's rate-limited and needs your key; the dashboard's template editor is built on it.

Built-in templates

Fourteen templates ship ready to render, including a QR code card and three data-driven charts (pass a data array) — see the live gallery. Pass any subset of a template's variables in modifications.

TemplateSizeVariables
og-article1200 × 630title, eyebrow, author, site, accent, bg
product-launch1200 × 630badge, title, tagline, brand, accent, bg
youtube-thumbnail1280 × 720title, kicker, accent, bg
testimonial1200 × 630quote, avatar, name, role, accent, bg
quote-square1080 × 1080quote, author, brand, accent, bg
stat-card1080 × 1080metric, label, context, brand, accent, bg
event-ticket1200 × 630event, date, time, venue, seat, accent, bg
code-snippet1200 × 675filename, code, accent
certificate1600 × 1130recipient, course, date, issuer, accent
instagram-story1080 × 1920title, subtitle, cta, accent, bg
bar-chart1200 × 675title, subtitle, data, accent, bg
line-chart1200 × 675title, subtitle, data, accent, bg
donut-chart1080 × 1080title, subtitle, data, center_label, accent, bg

Account & registration

POST /v1/register · mint a free key (50-image trial, no card, no auth). Returns the key, plan and balance.
GET /v1/account · your plan and remaining credits. Needs your key.

Recipe: an OG image on every publish

Generate the share image for a post from its own data at publish time, and store the returned URL on the record. Here with the built-in card; swap in your own template id once you have one.

import requests

def og_image(api_key, title, eyebrow="BLOG"):
    r = requests.post(
        "https://api.propzapi.com/v1/images",
        headers={"X-API-Key": api_key},
        json={"template": "og-article",
              "modifications": {"title": title, "eyebrow": eyebrow}},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["url"]          # save this on your post

print(og_image("pk_live_…", "How we cut render costs by 95%"))

Recipe: create a template once, reuse it forever

Create a template with your own HTML, then render it per record by passing different variables. The template lives on your account, so you only design it once.

import requests
H = {"X-API-Key": "pk_live_…"}

tpl = requests.post("https://api.propzapi.com/v1/templates", headers=H, json={
    "name": "Certificate", "width": 1400, "height": 990,
    "html": "<div style='font:600 60px sans-serif;text-align:center;padding:120px'>"
            "{{name}}<br><span style='font-size:30px'>{{course}}</span></div>",
    "variables": {"name": "", "course": ""},
}).json()["template"]

for student in [("Ada Lovelace", "Systems"), ("Alan Turing", "Computation")]:
    url = requests.post("https://api.propzapi.com/v1/images", headers=H, json={
        "template": tpl,
        "modifications": {"name": student[0], "course": student[1]},
    }).json()["url"]
    print(url)

Recipe: render from an AI agent

An MCP client sends one tools/call. generate_image renders and returns the image itself as an image content block, so the agent has the picture, not just a URL.

POST /mcp
{
  "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": {
    "name": "generate_image",
    "arguments": {
      "template": "og-article",
      "modifications": { "title": "Generated by an agent" }
    }
  }
}
# → content: [ { type: "image", data: "<base64>", mimeType: "image/png" }, { type: "text", … } ]

MCP & AI agents

propzapi is built for agents. It ships a Model Context Protocol server so an assistant can render images directly as a tool, plus a plain-text brief models read on their own.

https://api.propzapi.com/mcp · hosted MCP server, streamable HTTP
https://api.propzapi.com/.well-known/mcp/server-card.json · server card
https://api.propzapi.com/openapi.json · OpenAPI 3.1 spec
/llms.txt and /llms-full.txt · plain-text brief for models

The server exposes these image tools:

ToolArgumentsReturns
generate_imagetemplate (required), modifications, formatThe rendered image as an MCP image block, plus a text line. 1 credit.
screenshot_urlurl (required), full_page, width, height, formatA screenshot of any public page as an MCP image block. 1 credit.
list_templatesnoneBuilt-in templates and your own, with each one's variables. Free.

Point Claude, Cursor, Cline or n8n at the MCP server and an agent can render an image in one call. More on the agents page.

Zapier & Make (no code)

Wire propzapi into a no-code automation in minutes. Both work today with a generic HTTP step — no custom app needed.

Zapier · add a Webhooks by Zapier → Custom Request action: POST to https://api.propzapi.com/v1/images, header X-API-Key = your key, JSON body {"template":"og-article","modifications":{"title":"…"}}. The response url is your image.

Make · add an HTTP → Make a request module: same URL, method POST, header X-API-Key, raw JSON body, and turn on Parse response to map url downstream.

Official Zapier and Make apps (with a template dropdown and named actions) are on the way; the CLI app and Make blueprint live in the repo under integrations/.

Frequently asked questions

Do I need a credit card to use propzapi?

No. One POST to /v1/register mints a free key with a 50-image trial, no card and no signup form. When it runs out, buy a pay-as-you-go pack from $5 or subscribe from $29 a month. You can render your first image within a minute.

How much does a render cost?

One credit per image, and only when a render actually succeeds. A render that fails charges nothing. Every response returns the exact charge in the X-Credits-Cost header and your balance in X-Credits-Remaining, so you never guess.

Can I use my own templates?

Yes. Fourteen are built in, but the point is your own. POST /v1/templates with your HTML and {{variables}}, then render it as often as you like by passing different data. Caps: width/height 16 to 4000px, HTML up to 100 KB, up to 200 templates per account.

What image formats are supported?

png (default), jpeg with an optional quality, webp, and pdf — a one-page PDF at the template's size. Pass scale 1 to 3 for retina output on the raster formats.

How long do the returned image URLs last?

Treat them as short-lived. Rendered images are served by URL from the API; download the bytes or re-render when you need them again. Persistent object storage is being added.

Can an AI agent call propzapi directly?

Yes. There is a hosted Model Context Protocol server at /mcp with generate_image and list_templates tools, plus llms.txt and an OpenAPI spec. generate_image returns the actual image to the agent, not just a link.

Is there a rate limit?

There is no hard per-key limit today, so build normally. Anonymous key minting via /v1/register is throttled per IP and returns 429 on abuse. Concurrent renders per account are bounded so one caller can't starve the engine.

Changelog

  • Aug 1, 2026 · User-created templates: POST/GET/PATCH/DELETE /v1/templates. Build your own HTML templates and render them per record.
  • Aug 1, 2026 · generate_image and list_templates added to the MCP server. Agents render images and get the picture back inline.
  • Aug 1, 2026 · Image rendering shipped: POST /v1/images, headless Chromium, PNG / JPEG / WebP, billed on delivery.