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 owner pre-signs the URL, so it
always serves (it never blocks on quota the way the API does), and repeat hits are
CDN-cached and deduped from metering.
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, andqis passed to the template as a modification. scale(1–3) sets the device scale factor;q(0–100) sets JPEG/WebP quality.
# Signing
The easiest path: open a template in the app and copy its signed embed URL — it’s
pre-signed and ready to paste into an <img> tag.
To mint URLs yourself, the sig is an HMAC-SHA256 over the template id, the extension,
and the canonicalised query string (params sorted, sig excluded), using your signing
secret:
import crypto from 'node:crypto';
function signRenderUrl(base, 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 `${base}/v1/templates/${id}/render.${ext}?${query}&sig=${sig}`;
}
A request with a missing or wrong sig returns 403. The signature only covers the
params you signed, so a tampered URL (an extra or changed param) is rejected.
# 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 |