Appearance
Email templates
A template has a draft you edit and a list of published versions. Sending always uses the current published version, by slug. The Node.js client @funnelsgrove/emails and the fgrove email CLI call these endpoints; see Send lifecycle emails for the workflow.
Every endpoint below takes projectId as a query parameter with an API key.
json
{
"id": "<template-id>",
"slug": "order-confirmation",
"name": "Order confirmation",
"currentPublishedVersionId": null,
"draft": {
"subject": "Order {{ORDER_ID}}",
"previewText": "Your order is confirmed.",
"html": "<p>Order {{ORDER_ID}}</p>",
"text": "Order {{ORDER_ID}}",
"variables": { "ORDER_ID": "string" },
"variableDescriptions": { "ORDER_ID": "Order reference shown on the receipt" }
},
"createdAt": "…",
"updatedAt": "…"
}Draft fields
| Field | Required | Purpose |
|---|---|---|
subject | Yes | Subject line; may use placeholders. |
previewText | Yes | Inbox preview text, or null. |
html | Yes | HTML body. |
text | Yes | Plain-text body. |
variables | Yes | Declared variables and their type: string, number or boolean. |
variableDescriptions | No | Description per variable, shown to authors and by fgrove email library list. |
List templates
Scope: email_templates:read
Request
http
GET /email/templatesExample
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/email/templates" \
-H "Authorization: Bearer <project-sdk-secret-key>"Response
A JSON array of templates.
Get template
Scope: email_templates:read
Request
http
GET /email/templates/:templateIdExample
sh
curl "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>" \
-H "Authorization: Bearer <project-sdk-secret-key>"Response
json
{
"template": { "id": "<template-id>", "slug": "order-confirmation", "…": "…" },
"versions": [{
"id": "<version-id>",
"templateId": "<template-id>",
"version": 1,
"subject": "Order {{ORDER_ID}}",
"previewText": "Your order is confirmed.",
"html": "…",
"text": "…",
"variables": { "ORDER_ID": "string" },
"variableDescriptions": {},
"publishedAt": "…"
}]
}Errors
| Status | Meaning |
|---|---|
400 | templateId is not a UUID. |
404 | The template does not exist in this project. |
Create template
Scope: email_templates:write
Request
http
POST /email/templates
Content-Type: application/jsonParameters
| Field | Required | Purpose |
|---|---|---|
slug | No | Lowercase letters, digits and hyphens, up to 80 characters. |
name | No | Display name, up to 120 characters. |
draft | No | The draft fields. |
starter | No | login-code creates the starter template; if its slug exists, the existing template is returned. |
publish | No | true validates and publishes the draft in the same call. |
Example
sh
curl -X POST "https://sdk-api.funnelsgrove.com/integration/v1/email/templates" \
-H "Authorization: Bearer <project-sdk-secret-key>" \
-H "Content-Type: application/json" \
--data '{
"slug": "order-confirmation",
"name": "Order confirmation",
"draft": {
"subject": "Order {{ORDER_ID}}",
"previewText": "Your order is confirmed.",
"html": "<p>Order {{ORDER_ID}}</p><p>Total: {{PRICE}}</p>",
"text": "Order {{ORDER_ID}}\nTotal: {{PRICE}}",
"variables": { "ORDER_ID": "string", "PRICE": "number" }
}
}'Response
201 with the template. With publish: true, the response is { "template": …, "version": … } as for Publish template.
Errors
| Status | Meaning |
|---|---|
400 | The body is invalid, or the draft fails validation when publishing. |
409 | A template with this slug already exists. |
Update template
Replaces the given draft fields. At least one draft field is required.
Scope: email_templates:write
Request
http
PATCH /email/templates/:templateId
Content-Type: application/jsonParameters
| Field | Required | Purpose |
|---|---|---|
name | No | New display name. |
draft | Yes | Any subset of the draft fields. |
Example
sh
curl -X PATCH "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>" \
-H "Authorization: Bearer <project-sdk-secret-key>" \
-H "Content-Type: application/json" \
--data '{ "draft": { "subject": "Order {{ORDER_ID}} confirmed" } }'Response
The updated template.
Errors
| Status | Meaning |
|---|---|
400 | The body is invalid or draft is empty. |
404 | The template does not exist in this project. |
Validate template
Checks that the draft is valid without publishing it.
Scope: email_templates:read
Request
http
POST /email/templates/:templateId/validateExample
sh
curl -X POST "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>/validate" \
-H "Authorization: Bearer <project-sdk-secret-key>"Response
json
{ "valid": true }Errors
| Status | Meaning |
|---|---|
400 | The draft is invalid; the message names the problem. |
404 | The template does not exist in this project. |
Preview template
Renders the draft with the given values.
Scope: email_templates:read
Request
http
POST /email/templates/:templateId/preview
Content-Type: application/jsonParameters
| Field | Required | Purpose |
|---|---|---|
values | Yes | A value per declared variable: string, number or boolean. |
Example
sh
curl -X POST "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>/preview" \
-H "Authorization: Bearer <project-sdk-secret-key>" \
-H "Content-Type: application/json" \
--data '{ "values": { "ORDER_ID": "MV0002", "PRICE": 39.99 } }'Response
The rendered subject, previewText, html and text.
Errors
| Status | Meaning |
|---|---|
400 | The values do not match the declared variables, or the draft does not render. |
404 | The template does not exist in this project. |
Test-send template
Renders the draft with the given values and sends it to one recipient through the test delivery path.
Scope: email_templates:write
Request
http
POST /email/templates/:templateId/test-send
Content-Type: application/jsonParameters
| Field | Required | Purpose |
|---|---|---|
recipientEmail | Yes | Where to send the test. |
values | Yes | A value per declared variable. |
Example
sh
curl -X POST "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>/test-send" \
-H "Authorization: Bearer <project-sdk-secret-key>" \
-H "Content-Type: application/json" \
--data '{ "recipientEmail": "you@example.com", "values": { "ORDER_ID": "MV0002", "PRICE": 39.99 } }'Response
202 with the queued delivery receipt, { "id": "<delivery-id>", "status": "queued" }.
Errors
| Status | Meaning |
|---|---|
400 | The recipient or values are invalid, or the draft does not render. |
404 | The template does not exist in this project. |
Publish template
Validates the draft and publishes it as a new version. Sending by slug uses this version from now on.
Scope: email_templates:write
Request
http
POST /email/templates/:templateId/publishExample
sh
curl -X POST "https://sdk-api.funnelsgrove.com/integration/v1/email/templates/<template-id>/publish" \
-H "Authorization: Bearer <project-sdk-secret-key>"Response
json
{
"template": { "id": "<template-id>", "currentPublishedVersionId": "<version-id>", "…": "…" },
"version": { "id": "<version-id>", "version": 2, "publishedAt": "…", "…": "…" }
}Errors
| Status | Meaning |
|---|---|
400 | The draft fails validation. |
404 | The template does not exist in this project. |
409 | The draft changed while publishing; read it again and retry. |