PromoRails API
Create banners from your own apps: pick a template, send your texts and image URLs, export, and download the PNGs of every size.
Authentication
Create a key in Account → API keys and send it in the Authorization header. The API acts as your account, with your plan's limits (projects, banners per project, premium templates, watermark on the Free plan). An account has one key: generating a new one revokes the old one.
curl https://promorails.com/api/v1/me \ -H "Authorization: Bearer pr_your_key"
Base URL: https://promorails.com/api/v1. Requests and responses are JSON. Each key may make 60 requests per minute; the X-RateLimit-* headers show what is left, and a 429 carries Retry-After.
Errors
Errors use HTTP status codes and a body like:
{ "error": { "code": "unknown_field", "message": "values.title: unknown field. Fields: headline, photo." } }400 invalid request · 401 missing or invalid key · 403 plan limit (project_limit, banner_limit, premium_template, storage_full) · 404 not found · 409 export in progress · 422 an image URL could not be loaded · 429 rate limited.
How it works
GET /templates— choose a template; note itssizesandfields.POST /projects— create a project with field values and banners, and"export": true.GET /projects/:id— poll every few seconds untilstatusiscompleted(orfailed); the PNG URLs are inoutputs.
Endpoints
GET/templates
Your own templates (My templates, own: true) first, then the published catalog. Templates with several sizes have a separate layout per size; fields are shared by all sizes.
{
"data": [{
"id": "tpl_123",
"name": "Podium Sale",
"own": false,
"premium": false,
"available": true,
"preview_url": "https://…/preview.png",
"sizes": [{ "key": "1200x630", "width": 1200, "height": 630 },
{ "key": "1080x1920", "width": 1080, "height": 1920 }],
"fields": [{ "key": "headline", "label": "Headline", "type": "text" },
{ "key": "photo", "label": "Product photo", "type": "image" }]
}]
}POST/projects
Creates a project. sizes picks sizes of the template (default: all). values apply to every banner; each banner's own values override them. Text fields take a string (up to 500 characters); image fields take a public JPEG, PNG, WebP or GIF URL (up to 10 MB, at most 50 per request), which is copied into your storage. Without banners, the design is exported once per size.
curl -X POST https://promorails.com/api/v1/projects \
-H "Authorization: Bearer pr_your_key" \
-H "Content-Type: application/json" \
-d '{
"template_id": "tpl_123",
"name": "Black Friday",
"sizes": ["1200x630", "1080x1920"],
"values": { "headline": "Black Friday -50%" },
"banners": [
{ "values": { "photo": "https://example.com/shoes.jpg" } },
{ "values": { "photo": "https://example.com/bag.png", "headline": "Bags -30%" } }
],
"export": true
}'Answers 201 with the project (see below).
GET/projects/:id
The project. status: draft, queued, processing, completed or failed. Each banner's outputs maps a size key to its PNG; a project without banners has them in the top-level outputs.
{
"id": "proj_456",
"name": "Black Friday",
"status": "completed",
"template_id": "tpl_123",
"sizes": [{ "key": "1200x630", "width": 1200, "height": 630 }, …],
"fields": [{ "key": "headline", "label": "Headline", "type": "text" }, …],
"values": { "headline": "Black Friday -50%" },
"banners": [{
"id": "ban_1",
"position": 1,
"values": { "photo": { "url": "https://…", "width": 1200, "height": 900 } },
"outputs": { "1200x630": "https://…/1.png", "1080x1920": "https://…/1-1080x1920.png" }
}],
"outputs": {},
"created_at": "2026-11-11T10:00:00.000Z",
"updated_at": "2026-11-11T10:00:05.000Z"
}GET/projects
Your projects, newest first, in data. ?limit= 1–100 (default 20).
POST/projects/:id/export
Exports the project again (every banner in every size). Answers 202; poll the project. 409 while an export is running. Each PNG counts as one generation.
DELETE/projects/:id
Deletes the project with its banners, uploaded images and exports. Answers 204.
GET/me
Your plan, its limits, how many projects you have and how much storage your files take (in bytes).
{ "email": "you@example.com", "plan": "pro",
"limits": { "projects": null, "banners_per_project": 30, "premium_templates": true,
"watermark": false, "storage_bytes": 2147483648 },
"usage": { "projects": 4, "storage_bytes": 52428800 } }