Signed render URLs
Render-on-the-fly from a plain URL — perfect for <img> tags, Open Graph images, and
email. No API key travels to the browser: the URL carries a signature made with your
account’s URL-signing secret, so nobody can change its data or point it at another
template. Repeat hits are served from cache and never counted twice.
GET https://api.mostlyrender.com/v1/templates/{id}/render.{ext}?<modifications>&sig=<signature>
# Example
<img src="https://api.mostlyrender.com/v1/templates/tpl_abc/render.png?title=Hello&theme=dusk&sig=8f3c…" />
{ext}ispng,jpg/jpeg,webp, orpdf.- Every query param other than the reserved
sig,scale,q, andexpis passed to the template as a modification. scale(1–3) sets the device scale factor;q(0–100) sets JPEG/WebP quality.
# Getting a signed URL
From the dashboard: open the Playground, pick a template and press Get signed URL —
it’s ready to paste into an <img> tag.
From your backend, with your API key: ask us to sign it.
curl -X POST https://api.mostlyrender.com/v1/templates/tpl_abc/signed-url \
-H "Authorization: Bearer $MOSTLYRENDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"modifications":{"title":"Hello"},"output":"png"}'
# → { "url": "https://api.mostlyrender.com/v1/templates/tpl_abc/render.png?title=Hello&sig=…", "expires_at": null }
Pass "expiresIn": 2592000 (seconds) for a URL that stops working after 30 days.
Sign it yourself (no request to us per URL): copy your URL signing secret from
Settings. The sig is an HMAC-SHA256 over the template id, the extension, and the
canonicalised query string (params sorted, sig excluded):
import crypto from 'node:crypto';
function signRenderUrl(secret, id, ext, params) {
const query = Object.keys(params).sort()
.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`).join('&');
const sig = crypto.createHmac('sha256', secret).update(`${id}:${ext}:${query}`).digest('hex');
return `https://api.mostlyrender.com/v1/templates/${id}/render.${ext}?${query}&sig=${sig}`;
}
// Optional expiry: include exp (unix seconds) BEFORE signing — it's covered by the signature.
signRenderUrl(process.env.MOSTLYRENDER_SIGNING_SECRET, 'tpl_abc', 'png',
{ title: 'Hello', exp: Math.floor(Date.now() / 1000) + 86400 });
Keep the signing secret server-side, like an API key. Rotating it in Settings invalidates every URL signed with the old one.
# Responses
| Status | Meaning |
|---|---|
200 |
The image. X-MR-Cache: hit when served from cache. |
402 |
The template owner’s free-plan quota is used up. |
403 |
Missing or wrong sig — or an unknown template (we don’t reveal which). |
410 |
The URL’s exp has passed. |
429 |
Too many uncached renders for this template right now; cached URLs keep serving. Retry after Retry-After. |
# When to use which
| Use | Reach for |
|---|---|
| Server-side generation, store the URL | POST /v1/renders |
| Many at once | Batch |
Embed in <img>/OG/email, no key in the client |
Signed render URLs |