Email templates
The reusable email bodies campaigns send.
Download the full API pública projection: openapi.json.
| Method | Path | What it does |
|---|---|---|
GET | /email-templates | List saved templates |
POST | /email-templates | Save a template |
DELETE | /email-templates/{id} | Delete a template |
GET | /email-templates/{id} | Fetch one template |
PATCH | /email-templates/{id} | Update a template |
POST | /email-templates/{id}/duplicate | Duplicate a template |
GET /email-templates
List saved templates
Every template in the workspace, each with its full design blob and a total. Unpaginated, and the designs are not small — fetch one by id when you only need one.
curl https://api.vitrinadev.com/api/v1/email-templates \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": [
{
"id": "7a7a7a7a-0000-4000-8000-0000000000e7",
"name": "Newsletter mensual",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
},
"created_by": "7a7a7a7a-0000-4000-8000-000000000011",
"created_at": "2026-09-10T09:00:00.000Z",
"updated_at": "2026-09-10T09:00:00.000Z"
}
],
"meta": {
"total": 1
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /email-templates
Save a template
design is stored verbatim and unvalidated beyond being a JSON object. Anything the builder can produce is accepted, and so is anything it cannot — a malformed design saves cleanly here and fails later, wherever it is compiled.
Names are not unique; two templates may share one. created_by is the signed-in teammate and is null for an sk_* API key. Answers 201.
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
name | string | yes | mín. 1, máx. 200 |
design | object | yes |
curl -X POST https://api.vitrinadev.com/api/v1/email-templates \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Newsletter mensual",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
}
}'Example response (201)
{
"data": {
"id": "7a7a7a7a-0000-4000-8000-0000000000e7",
"name": "Newsletter mensual",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
},
"created_by": "7a7a7a7a-0000-4000-8000-000000000011",
"created_at": "2026-09-10T09:00:00.000Z",
"updated_at": "2026-09-10T09:00:00.000Z"
}
}Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429
DELETE /email-templates/{id}
Delete a template
Removes the template. Campaigns built from it are untouched — they copied the design rather than referencing it — so deleting a template never breaks anything already scheduled or sent. A 404 for an id that is not there, so the delete is confirmed.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
curl -X DELETE https://api.vitrinadev.com/api/v1/email-templates/<id> \
-H "Authorization: Bearer $VITRINA_KEY"Answers: 204 · 400 · 401 · 403 · 404 · 409 · 429
GET /email-templates/{id}
Fetch one template
The template with its design blob.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
curl https://api.vitrinadev.com/api/v1/email-templates/<id> \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"id": "7a7a7a7a-0000-4000-8000-0000000000e7",
"name": "Newsletter mensual",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
},
"created_by": "7a7a7a7a-0000-4000-8000-000000000011",
"created_at": "2026-09-10T09:00:00.000Z",
"updated_at": "2026-09-10T09:00:00.000Z"
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
PATCH /email-templates/{id}
Update a template
Applies name, design or both; at least one is required. design is REPLACED wholesale — there is no partial edit of a design, so send the whole blob.
There is no version history. The previous design is gone once this returns, so duplicate first if it might be wanted again. Campaigns already built from this template keep their own copy and are unaffected.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
name | string | — | mín. 1, máx. 200 |
design | object | — |
curl -X PATCH https://api.vitrinadev.com/api/v1/email-templates/<id> \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Newsletter mensual (octubre)"
}'Example response (200)
{
"data": {
"id": "7a7a7a7a-0000-4000-8000-0000000000e7",
"name": "Newsletter mensual (octubre)",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
},
"created_by": "7a7a7a7a-0000-4000-8000-000000000011",
"created_at": "2026-09-10T09:00:00.000Z",
"updated_at": "2026-10-01T14:00:00.000Z"
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /email-templates/{id}/duplicate
Duplicate a template
Copies the design into a new template named "<original> (copia)" and answers 201 with it. Takes no body — the name is not yours to choose here, so PATCH the copy afterwards to rename it.
Duplicating twice produces two templates with the SAME name, and a copy of a copy is named "… (copia) (copia)". The new template is attributed to whoever duplicated it, not to the original author.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
curl -X POST https://api.vitrinadev.com/api/v1/email-templates/<id>/duplicate \
-H "Authorization: Bearer $VITRINA_KEY"Example response (201)
{
"data": {
"id": "7a7a7a7a-0000-4000-8000-0000000000e8",
"name": "Newsletter mensual (copia)",
"design": {
"blocks": [
{
"type": "heading",
"text": "Novedades de octubre"
},
{
"type": "text",
"text": "Hola {{first_name}}, estas son las novedades del mes."
},
{
"type": "button",
"label": "Ver más",
"url": "https://example.cl/novedades"
}
],
"style": {
"background": "#ffffff",
"accent": "#0f766e"
}
},
"created_by": "7a7a7a7a-0000-4000-8000-000000000011",
"created_at": "2026-10-01T14:05:00.000Z",
"updated_at": "2026-10-01T14:05:00.000Z"
}
}Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429