API overview
What the JamFrame REST API does, its base URL, how to sign requests with an API key, and the three calls that take you from a template to a finished file.
The JamFrame API makes images and PDFs from your templates, from your own code. You send a template id and the values to fill in. You get back a link to each finished file.
Anything you can render in the app, you can render with the API: single images, carousels, PDFs and other sizes of the same design.
Base URL
Every request goes to this address:
https://api.jamframe.com/v1
Requests and answers are JSON. Send Content-Type: application/json with every request that has a body.
A request body can be up to 5 MB. Times are in UTC, written like 2026-11-14T09:30:00.000Z.
Authentication
Every request needs an API key in the Authorization header:
Authorization: Bearer jf_live_…
You create keys on the API Keys page in the app. A key works in one workspace, so you never send a workspace id. Keep keys on your server and out of web pages. See API keys.
Your first request
This request lists the templates in your workspace. It’s free, so it’s a good way to check that your key works.
curl "https://api.jamframe.com/v1/designs?limit=5" \
-H "Authorization: Bearer $JAMFRAME_API_KEY"const res = await fetch("https://api.jamframe.com/v1/designs?limit=5", {
headers: { Authorization: `Bearer ${process.env.JAMFRAME_API_KEY}` },
});
const { designs } = await res.json();
for (const design of designs) console.log(design.id, design.name);import os
import requests
res = requests.get(
"https://api.jamframe.com/v1/designs",
headers={"Authorization": f"Bearer {os.environ['JAMFRAME_API_KEY']}"},
params={"limit": 5},
)
for design in res.json()["designs"]:
print(design["id"], design["name"])The answer lists your templates, newest first:
{
"designs": [
{
"id": "clx8m2k3p0002abcd1234efgh",
"name": "Coffee tips carousel",
"orientation": "square",
"pages": 3,
"createdAt": "2026-11-01T09:12:44.000Z",
"updatedAt": "2026-11-05T16:03:10.000Z"
}
],
"pagination": { "nextCursor": null, "hasMore": false }
}
The API calls templates “designs”. A template’s id is the templateId you render with.
From template to file in three calls
-
Find the template.
GET /v1/designslists the templates in your workspace. Addq=coffeeto search by name, orsource=libraryto list the ready-made library templates instead. -
See what you can change.
GET /v1/designs/{id}returns the template’sparameters. Each one has thekeyyou send, itstype, thepagesit’s on, and its current value asexample:{ "design": { "id": "clx8m2k3p0002abcd1234efgh", "name": "Coffee tips carousel", "pages": 3, "parameters": [ { "key": "title", "type": "text", "pages": [1, 2, 3], "example": "5 ways to brew better coffee" }, { "key": "photo", "type": "image", "pages": [1], "example": "https://example.com/images/beans.jpg" }, { "key": "brand", "type": "variable", "pages": [1, 3], "example": "Acme Coffee" } ], "sizes": [] } } -
Render.
POST /v1/renderwith thetemplateIdand the values inmodifications:curl https://api.jamframe.com/v1/render \ -H "Authorization: Bearer $JAMFRAME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "templateId": "clx8m2k3p0002abcd1234efgh", "modifications": { "title": "Grind just before brewing" }, "response": { "format": "png" } }'The answer has a link to each image in
data.content. See Render images and PDFs for every option.
Pagination
List endpoints, such as GET /v1/designs and GET /v1/renders, return one page of items at a time.
| Query parameter | What it does |
|---|---|
limit |
How many items per page, from 1 to 100. The default is 25. A larger number counts as 100. |
cursor |
Where the page starts. Leave it out for the first page. For the next page, send the nextCursor of the last answer. |
Each answer has a pagination object. hasMore is true when there are more pages. nextCursor is
null on the last page.
let cursor = null;
do {
const url = new URL("https://api.jamframe.com/v1/designs");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.JAMFRAME_API_KEY}` },
});
const { designs, pagination } = await res.json();
for (const design of designs) console.log(design.id, design.name);
cursor = pagination.nextCursor;
} while (cursor);
Errors, limits and credits
- Errors. Every answer that isn’t a 2xx has the same shape:
{"error": "CODE", "message": "…"}. See Errors. - Rate limits. Your organization can send a set number of requests per minute, depending on your plan.
Too many get a
429. See Rate limits. - Credits. Each image, or each page of a PDF, costs one render credit. Failed renders are free, and so is reading templates and renders. See Credits.
The API guides
| Guide | What it covers |
|---|---|
| API keys | Create, test, rotate and revoke keys |
| Render images and PDFs | POST /v1/render: formats, carousels, PDFs, links and limits |
| Modification keys | How to change text, images and styles, page by page |
| Async renders | Render in the background, then poll a job or get a callback |
| Smart Resize | Render one template at other sizes, one or many per call |
| Signed URLs | Public links that render an image when someone opens them |
| AI at render time | Let AI write text, make images or translate while rendering |
| Generate a template with AI | Design a new template from a text prompt |
| Background removal | Cut a picture out on a transparent background |
| Templates and renders | List templates and library templates, and read your render log |
| Workflows | Start workflow runs and read their results |
| Webhooks | Get told when templates change or background renders finish |
| Errors | Error codes and what to do about them |
| Rate limits | How many requests you can send, and how to slow down |
Every endpoint, field and error code is in the API reference (opens in a new tab).
Last updated
Still stuck?
Email [email protected] and a real person will reply. Tell us the template you were using and what you expected to happen.