POST
/templates/previewPOST /templates/preview
Render unsaved HTML or a block document exactly as a send would compose it, without saving a template.
Request
curl -X POST 'https://api.sendheron.com/api/v1/templates/preview' \
-H 'Authorization: Bearer <YOUR_API_KEY>' \
-H 'Content-Type: application/json'Required scopes
The key must carry these:
- templates:read
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
| bodyHtml | string | No | Raw HTML to preview. Send exactly one of bodyHtml or document. |
| document | object | No | Block document to compile and preview. Send exactly one of bodyHtml or document. |
| emailType | MARKETING | TRANSACTIONAL | No | Which type to preview as, which decides whether an unsubscribe is owed. Omitting it previews as marketing: an unknown type never weakens compliance. |
| channel | CAMPAIGN | BULK | SEQUENCE | DIRECT | TRANSACTIONAL_API | CAMPAIGN_TEST | No | Which channel to preview through. CAMPAIGN and BULK are always marketing whatever the template says, TRANSACTIONAL_API and CAMPAIGN_TEST are always transactional, and SEQUENCE and DIRECT follow the template. CAMPAIGN_TEST is the proof of a campaign sent to a teammate before the blast, which is why it carries no unsubscribe. Defaults to DIRECT. |
| sampleData | object | No | Values for the Handlebars variables, so the preview renders real-looking content instead of empty placeholders. |
| subject | string | No | Subject to render with sampleData; returned as renderedSubject. |
| previewText | string | No | Preview text to render with sampleData. It is placed in renderedHtml as the hidden preheader, returned as renderedPreviewText, and counted by the size check. |
Responses
Returns 201 on success.
- 400
- The payload failed validation, or the request is not valid for the current state. The body's
descriptionnames the field and says what was wrong with it in words, e.g. "domain: domain must be a bare hostname such as acme.com, with no scheme, path, or port". Theerrorcode is stable and safe to branch on;descriptionis for the human reading the log. - 401
- Missing or invalid API key.
- 403
- Valid key, but it does not carry the required scope. The
errorcode isapiKeys.insufficientScopesand thedescriptionnames both halves of the problem: "Missing required scope(s): X. This key holds: Y." Neither is a secret, since the required scopes are on this page and the held ones are your own credential, and a bare "Forbidden" costs a debugging pass to work out which of the two it was. - 404
- No such record in this workspace. An id belonging to a different workspace returns this too, never a 403, because the API will not confirm that a record exists outside the workspace your key was issued in. Read it as "not yours or not there" rather than as "definitely gone".
- 409
- A duplicate, or an idempotency key reused with a different payload.
- 429
- Either rate-limit ceiling was exceeded.
- 400
- Neither or both of
bodyHtmlanddocumentwere supplied. Anullor blankbodyHtmlcounts as absent, matching the save path. - 400
templates.renderFailed: the body failed to compile as a Handlebars template. The preview fails exactly as the send would.- 400
templates.previewTextTooLong:previewTextis longer than 200 characters. Merge tags count as written, before they are filled in.
Rate limits
100/min per key, counted against the organization's READ ceiling (1200/min). Both windows are one minute.