Errors
The REST API uses conventional HTTP status codes and a consistent JSON error shape.
# Error shape
JSON endpoints return:
{ "error": "templateId is required." }
(The signed render URL path returns a short text/plain body
instead, since it serves binary on success.)
# Status codes
| Status | Meaning | Typical cause |
|---|---|---|
200 |
OK | Render/screenshot completed. |
202 |
Accepted | Async job enqueued — poll GET /v1/renders/{id}. |
400 |
Bad request | Missing template, batch over 50, or a disallowed screenshot URL. |
401 |
Unauthorized | Missing, invalid, or revoked API key. |
402 |
Payment required | Free-plan quota exhausted — upgrade to keep rendering. |
403 |
Forbidden | Bad or missing signature on a signed render URL. |
404 |
Not found | Unknown template, job, or path. |
405 |
Method not allowed | Wrong HTTP method for the endpoint. |
500 |
Server error | An unexpected failure (retry; contact support if it persists). |
# Error codes
Generator, job, item and dataset endpoints add a stable machine-readable code (and, for row
problems, an errors array with line numbers), e.g.
{ "error": "2 rows are invalid", "code": "rows-invalid", "errors": [{ "line": 3, "row_key": "g-2", "code": "param-required" }] }.
Branch on code, not on the message. The full list is in Generators.
# Quotas
On the free plan, renders hard-stop at your monthly cap with 402. Paid plans
never block mid-render — overage is metered and billed (so your renders never go dark).
Check your current usage with GET /v1/account or the Usage page in the app.
# Handling errors
const { MostlyRenderError } = require('@mostlytiny/mostlyrender');
try {
const out = await mr.render({ templateId: 'tpl_abc', modifications: { title: 'Hello' } });
} catch (e) {
if (e instanceof MostlyRenderError) console.log(e.status, e.code, e.body); // e.g. 402 { "error": "…quota…" }
}
In a batch, per-item failures don’t fail the whole request — each failed
item is an { "error": … } entry in results.