HomeGuidesAPI Reference
ChangelogHelp CenterCommunityContact Us
API Reference

Templates API overview

OpenAPI Spec

Machine-readable spec for the Templates API: stable/categories/templates.json

Before you begin

Check out our general API overview before getting started with specific endpoints.

Use the Templates API to seamlessly create, update, and manage email templates programmatically. Whether you use fully custom HTML, hybrid templates compatible with Klaviyo’s drag-and-drop editor, or native drag-and-drop templates, the Templates API offers flexibility for tailored email experiences.

📘

When calling the Templates API, your authentication key must have the appropriate scopes (templates:read, templates:write).

Use cases

The Templates API supports the following use cases:

  • Get, create, and manage templates.
  • Create and update HTML, Hybrid and native drag-and-drop templates.
  • Render a template with the given template ID and context.
  • Clone a template.
  • Convert an HTML template into a drag-and-drop template.

📘

Looking to assign a template to a campaign message or fetch template data for a specific campaign message? Check out our Messages endpoints within the Campaigns API.

Data model

A template has the following:

  • id

    The template ID.

  • attributes

    • name (required)

      The name of the template.

    • editor_type (required)

      The type of editor. Supported values:

      • CODE — custom HTML templates.
      • USER_DRAGGABLE — hybrid templates edited as HTML in the API but compatible with the drag-and-drop editor.
      • SYSTEM_DRAGGABLE — native drag-and-drop templates backed by a structured definition object.
    • html

      The HTML contents of the template. Used for CODE and USER_DRAGGABLE templates. Not used when editor_type is SYSTEM_DRAGGABLE (use definition instead).

    • text

      The plaintext version of the template.

    • definition

      Structured drag-and-drop template content (body, styles, and related metadata) for SYSTEM_DRAGGABLE templates. Required when creating a SYSTEM_DRAGGABLE template. On Get Templates, the definition attribute is omitted by default; pass additional-fields[template]=definition to include it in list responses. Get Template includes definition for SYSTEM_DRAGGABLE templates. For the exact JSON shape, refer to the endpoint schemas in the API reference.

    • amp

      The AMP version of the template. Requires an enabled AMP email to access in-app. Not used when editor_type is SYSTEM_DRAGGABLE.

    • created

      The timestamp of when the template was last created.

    • updated

      The timestamp of when the metric was last updated.

Create a template

When creating a template with the Create Template endpoint, your request payload must include at least a template name and an editor type.

  • For CODE or USER_DRAGGABLE templates, include the appropriate HTML-related fields as described in the API reference.
  • For SYSTEM_DRAGGABLE templates, include a definition to define the template content (body, styles, rows, columns, blocks etc).

Create a HTML template

The example below is a CODE template. It utilizes dynamic variables including first_name, last_name, discount_code, and order_total to tailor the content for each recipient. These variables enable seamless personalization when rendering the template.

{
   "data": {
       "type": "template",
       "attributes": {
           "name": "Personalized Discount Email",
           "editor_type": "CODE",
           "html": "<html>\n  <head>\n    <meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\" />\n    <title>Special Discount for You</title>\n    <style>\n      body {\n        background-color: #f6f6f6;\n        font-family: sans-serif;\n        margin: 20px;\n      }\n      .main {\n        background: #ffffff;\n        border-radius: 3px;\n        width: 100%;\n      }\n      .container {\n        margin: 0 auto !important;\n        width: 600px;\n      }\n      .wrapper {\n        box-sizing: border-box;\n        padding: 15px;\n      }\n      table {\n        width: 100%;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <table class=\"main\">\n        <tr>\n          <td class=\"wrapper\">\n            <p>Hello {{ first_name }} {{ last_name }},</p>\n            <p>Thank you for your order of ${{ order_total }}!</p>\n            <p>As a thank you, here’s a special discount code just for you: <strong>{{ discount_code }}</strong></p>\n            <p>Use it at checkout to enjoy your discount.</p>\n          </td>\n        </tr>\n        <tr>\n          <td class=\"wrapper\">{% unsubscribe %}</td>\n        </tr>\n      </table>\n    </div>\n  </body>\n</html>"
       }
   }
}
{
    "data": {
        "type": "template",
        "id": "TuG2Zd",
        "attributes": {
            "name": "Personalized Discount Email",
            "editor_type": "CODE",
            "html": "<html>\n<head>\n<meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\"/>\n<title>Special Discount for You</title>\n<style>body {\n    background-color: #f6f6f6;\n    font-family: sans-serif;\n    margin: 20px\n    }\n.main {\n    background: #fff;\n    border-radius: 3px;\n    width: 100%\n    }\n.container {\n    margin: 0 auto !important;\n    width: 600px\n    }\n.wrapper {\n    box-sizing: border-box;\n    padding: 15px\n    }\ntable {\n    width: 100%\n    }</style></head>\n<body>\n<div class=\"container\">\n<table class=\"main\">\n<tr>\n<td class=\"wrapper\">\n<p>Hello {{ first_name }} {{ last_name }},</p>\n<p>Thank you for your order of ${{ order_total }}!</p>\n<p>As a thank you, here’s a special discount code just for you: <strong>{{ discount_code }}</strong></p>\n<p>Use it at checkout to enjoy your discount.</p>\n</td>\n</tr>\n<tr>\n<td class=\"wrapper\">{% unsubscribe %}</td>\n</tr>\n</table>\n</div>\n</body>\n</html>",
            "text": null,
            "amp": null,
            "created": "2025-02-05T19:12:51.599729+00:00",
            "updated": "2025-02-05T19:12:51.599758+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/TuG2Zd/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/templates"
    }
}

Create a drag-and-drop template

The example below is a SYSTEM_DRAGGABLE template. The definition in the request below matches the definition object in the Get Template response for SYSTEM_DRAGGABLE templates (see Get a drag-and-drop template under Fetch templates).

{
   "data": {
       "type": "template",
       "attributes": {
           "name": "Spring welcome (DnD)",
           "editor_type": "SYSTEM_DRAGGABLE",
           "text": "Hi there, thanks for subscribing.",
           "definition": {
               "body": {
                   "properties": {},
                   "styles": {},
                   "sections": [
                       {
                           "content_type": "section",
                           "type": "section",
                           "data": {
                               "properties": {},
                               "display_options": {},
                               "styles": {}
                           },
                           "rows": [
                               {
                                   "data": {
                                       "styles": {
                                           "column_layout": "1-column-full-width"
                                       }
                                   },
                                   "columns": [
                                       {
                                           "data": {},
                                           "blocks": [
                                               {
                                                   "content_type": "block",
                                                   "type": "text",
                                                   "data": {
                                                       "content": "<p>Hi {{ person.first_name|default:'there' }}, thanks for subscribing.</p>",
                                                       "display_options": {},
                                                       "styles": {}
                                                   }
                                               }
                                           ]
                                       }
                                   ]
                               }
                           ]
                       }
                   ]
               },
               "styles": [
                   {"style_type": "base-styles", "properties": {}, "styles": {}},
                   {"style_type": "text-styles", "styles": {}},
                   {"style_type": "link-styles", "styles": {}},
                   {"style_type": "heading-1-styles", "styles": {}},
                   {"style_type": "heading-2-styles", "styles": {}},
                   {"style_type": "heading-3-styles", "styles": {}},
                   {"style_type": "heading-4-styles", "styles": {}},
                   {"style_type": "mobile-styles", "properties": {}, "styles": {}}
               ]
           }
       }
   }
}
{
    "data": {
        "type": "template",
        "id": "V2kMn9",
        "attributes": {
            "name": "Spring welcome (DnD)",
            "editor_type": "SYSTEM_DRAGGABLE",
            "html": "<html><head><meta charset=\"utf-8\"/><title>Spring welcome</title></head><body><p>Hi {{ person.first_name|default:'there' }}, thanks for subscribing.</p></body></html>",
            "text": "Hi there, thanks for subscribing.",
            "definition": {
                "body": {
                    "properties": {},
                    "styles": {},
                    "sections": [
                        {
                            "content_type": "section",
                            "type": "section",
                            "data": {
                                "properties": {},
                                "display_options": {},
                                "styles": {}
                            },
                            "rows": [
                                {
                                    "data": {
                                        "styles": {
                                            "column_layout": "1-column-full-width"
                                        }
                                    },
                                    "columns": [
                                        {
                                            "data": {},
                                            "blocks": [
                                                {
                                                    "content_type": "block",
                                                    "type": "text",
                                                    "data": {
                                                        "content": "<p>Hi {{ person.first_name|default:'there' }}, thanks for subscribing.</p>",
                                                        "display_options": {},
                                                        "styles": {}
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                "styles": [
                    {"style_type": "base-styles", "properties": {}, "styles": {}},
                    {"style_type": "text-styles", "styles": {}},
                    {"style_type": "link-styles", "styles": {}},
                    {"style_type": "heading-1-styles", "styles": {}},
                    {"style_type": "heading-2-styles", "styles": {}},
                    {"style_type": "heading-3-styles", "styles": {}},
                    {"style_type": "heading-4-styles", "styles": {}},
                    {"style_type": "mobile-styles", "properties": {}, "styles": {}}
                ]
            },
            "amp": null,
            "created": "2026-04-10T15:30:00+00:00",
            "updated": "2026-04-10T15:30:00+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/V2kMn9/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/templates"
    }
}

📘

Adding universal content to a template

Currently, our APIs do not natively support referencing universal content blocks directly in the payload. You'll need to fetch the block's content (via Get Universal Content), add the content to your template, and upload the final HTML. See our Universal Content API overview for more information on managing universal content blocks via API.

Render a template

Render a template with a given template ID and context attribute (a JSON object with the context the email template is rendered with). A call to Render Template returns the AMP, HTML, and plain text versions of the email template.

Here’s the request and response for rendering the template we created above:

{
   "data": {
       "type": "template",
       "id": "TuG2Zd",
       "attributes": {
           "context": {
               "first_name": "John",
               "last_name": "Doe",
               "discount_code": "WELCOME10",
               "order_total": 49.99
           }
       }
   }
}
{
    "data": {
        "type": "template",
        "id": "TuG2Zd",
        "attributes": {
            "name": "Personalized Discount Email",
            "editor_type": "CODE",
            "html": "<html>\n<head>\n<meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\"/>\n<title>Special Discount for You</title>\n<style>body {\n    background-color: #f6f6f6;\n    font-family: sans-serif;\n    margin: 20px\n    }\n.main {\n    background: #fff;\n    border-radius: 3px;\n    width: 100%\n    }\n.container {\n    margin: 0 auto !important;\n    width: 600px\n    }\n.wrapper {\n    box-sizing: border-box;\n    padding: 15px\n    }\ntable {\n    width: 100%\n    }</style></head>\n<body>\n<div class=\"container\">\n<table class=\"main\">\n<tr>\n<td class=\"wrapper\">\n<p>Hello John Doe,</p>\n<p>Thank you for your order of $49.99!</p>\n<p>As a thank you, here’s a special discount code just for you: <strong>WELCOME10</strong></p>\n<p>Use it at checkout to enjoy your discount.</p>\n</td>\n</tr>\n<tr>\n<td class=\"wrapper\"><a class=\"unsubscribe-link\" href=\"[unsubscribe_tag]\">Unsubscribe</a></td>\n</tr>\n</table>\n</div>\n</body>\n</html>",
            "text": null,
            "amp": null,
            "created": "2025-02-05T19:12:52+00:00",
            "updated": "2025-02-05T19:12:52+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/TuG2Zd/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/template-render"
    }
}

Clone a template

To clone the template we created and rendered above, your request payload for Clone Template should look like the following:

{
   "data": {
       "type": "template",
       "id": "TuG2Zd",
       "attributes": {
           "name": "Clone of Personalized Discount Email"
       }
   }
}
{
    "data": {
        "type": "template",
        "id": "XRPRey",
        "attributes": {
            "name": "Clone of Personalized Discount Email",
            "editor_type": "CODE",
            "html": "<html>\n<head>\n<meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\"/>\n<title>Special Discount for You</title>\n<style>body {\n    background-color: #f6f6f6;\n    font-family: sans-serif;\n    margin: 20px\n    }\n.main {\n    background: #fff;\n    border-radius: 3px;\n    width: 100%\n    }\n.container {\n    margin: 0 auto !important;\n    width: 600px\n    }\n.wrapper {\n    box-sizing: border-box;\n    padding: 15px\n    }\ntable {\n    width: 100%\n    }</style></head>\n<body>\n<div class=\"container\">\n<table class=\"main\">\n<tr>\n<td class=\"wrapper\">\n<p>Hello {{ first_name }} {{ last_name }},</p>\n<p>Thank you for your order of ${{ order_total }}!</p>\n<p>As a thank you, here’s a special discount code just for you: <strong>{{ discount_code }}</strong></p>\n<p>Use it at checkout to enjoy your discount.</p>\n</td>\n</tr>\n<tr>\n<td class=\"wrapper\">{% unsubscribe %}</td>\n</tr>\n</table>\n</div>\n</body>\n</html>",
            "text": null,
            "amp": null,
            "created": "2025-02-05T19:35:59.752156+00:00",
            "updated": "2025-02-05T19:35:59.832098+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/XRPRey/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/template-clone"
    }
}

🚧

Cloning and creating templates will fail if your account contains 1,000 or more templates, as the Templates API has a limit of 1,000 templates.

Convert an HTML template to drag-and-drop

Convert a CODE template into a new SYSTEM_DRAGGABLE template with Create Template Conversion Job. The conversion runs asynchronously, so the request returns a job instead of the new template. The source template does not change. The new template is named after the source template, followed by (converted).

Starting a conversion requires an account on a paid plan. Requests from other accounts return a 403 error. Any account can still get and list its conversion jobs.

Only CODE templates can be converted. If the source template is a different editor type, the request returns a 400 error. If the source template does not exist, the request returns a 404 error.

📘

Creating a conversion job requires the templates:write scope and is limited to 1 request/second burst and 1 request/minute steady. Reading conversion jobs requires the templates:read scope.

Start a conversion

To convert the HTML template we created above, set it as the source-template relationship:

{
   "data": {
       "type": "template-conversion-job",
       "relationships": {
           "source-template": {
               "data": {
                   "type": "template",
                   "id": "TuG2Zd"
               }
           }
       }
   }
}
{
    "data": {
        "type": "template-conversion-job",
        "id": "XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE",
        "attributes": {
            "status": "queued",
            "created_at": "2026-10-15T14:00:00+00:00",
            "error": null,
            "completed_at": null
        },
        "relationships": {
            "source-template": {
                "data": {
                    "type": "template",
                    "id": "TuG2Zd"
                }
            }
        },
        "links": {
            "self": "https://a.klaviyo.com/api/template-conversion-jobs/XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/template-conversion-jobs/"
    }
}

Check the job status

Poll Get Template Conversion Job until the job's status is complete or failed. A job has one of these statuses:

  • queued — the job is waiting to start.
  • processing — the conversion is running.
  • complete — the new template exists. Its ID is in the converted-template relationship.
  • failed — the conversion did not finish. The error attribute says why.

The converted-template relationship is only included when the status is complete.

curl --request GET \
     --url https://a.klaviyo.com/api/template-conversion-jobs/XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/vnd.api+json' \
     --header 'revision: 2026-10-15'
{
    "data": {
        "type": "template-conversion-job",
        "id": "XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE",
        "attributes": {
            "status": "complete",
            "created_at": "2026-10-15T14:00:00+00:00",
            "error": null,
            "completed_at": "2026-10-15T14:03:00+00:00"
        },
        "relationships": {
            "source-template": {
                "data": {
                    "type": "template",
                    "id": "TuG2Zd"
                }
            },
            "converted-template": {
                "data": {
                    "type": "template",
                    "id": "Rw4pLk"
                }
            }
        },
        "links": {
            "self": "https://a.klaviyo.com/api/template-conversion-jobs/XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/template-conversion-jobs/XyZ123-01JA8ZQ5M0V3T7N6K2H4B9C1DE/"
    }
}

Get the new template with Get Template, using the ID from the converted-template relationship.

List conversion jobs

Get Template Conversion Jobs returns the conversion jobs created in the last 7 days, newest first. This endpoint does not support filtering or pagination.

Manage templates

Update and delete templates with the Update Template and Delete Template endpoints, respectively.

Fetch templates

All template types are returned when making a Get Template or Get Templates request.

For SYSTEM_DRAGGABLE templates, the structured definition attribute behaves differently by endpoint:

To include definition on each item in a list response, add ?additional-fields[template]=definition to the URL. Learn more in the guide to additional fields. CODE and USER_DRAGGABLE templates do not use definition.

Get an HTML template

curl --request GET \
     --url https://a.klaviyo.com/api/templates/U7bDHv \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/vnd.api+json' \
     --header 'revision: 2026-04-15'
{
    "data": {
        "type": "template",
        "id": "U7bDHv",
        "attributes": {
            "name": "Clone of Monthly Newsletter Template",
            "editor_type": "CODE",
            "html": "<html><head></head><body>Template HTML content</body></html>",
            "text": null,
            "amp": null,
            "created": "2025-02-04T20:39:18+00:00",
            "updated": "2025-02-04T20:39:18+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/U7bDHv/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/templates/U7bDHv"
    }
}

Get a drag-and-drop template

For SYSTEM_DRAGGABLE templates, the response includes a structured definition and a rendered html preview. The definition object matches the payload in the Create a drag-and-drop template example earlier in this overview (under Create a template).

curl --request GET \
     --url https://a.klaviyo.com/api/templates/Qw8tRm \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/vnd.api+json' \
     --header 'revision: 2026-04-15'
{
    "data": {
        "type": "template",
        "id": "Qw8tRm",
        "attributes": {
            "name": "Spring welcome (DnD)",
            "editor_type": "SYSTEM_DRAGGABLE",
            "html": "<html><head><meta charset=\"utf-8\"/><title>Spring welcome</title></head><body><p>Hi {{ person.first_name|default:'there' }}, thanks for subscribing.</p></body></html>",
            "text": "Hi there, thanks for subscribing.",
            "definition": {
                "body": {
                    "properties": {},
                    "styles": {},
                    "sections": [
                        {
                            "content_type": "section",
                            "type": "section",
                            "data": {
                                "properties": {},
                                "display_options": {},
                                "styles": {}
                            },
                            "rows": [
                                {
                                    "data": {
                                        "styles": {
                                            "column_layout": "1-column-full-width"
                                        }
                                    },
                                    "columns": [
                                        {
                                            "data": {},
                                            "blocks": [
                                                {
                                                    "content_type": "block",
                                                    "type": "text",
                                                    "data": {
                                                        "content": "<p>Hi {{ person.first_name|default:'there' }}, thanks for subscribing.</p>",
                                                        "display_options": {},
                                                        "styles": {}
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                "styles": [
                    {"style_type": "base-styles", "properties": {}, "styles": {}},
                    {"style_type": "text-styles", "styles": {}},
                    {"style_type": "link-styles", "styles": {}},
                    {"style_type": "heading-1-styles", "styles": {}},
                    {"style_type": "heading-2-styles", "styles": {}},
                    {"style_type": "heading-3-styles", "styles": {}},
                    {"style_type": "heading-4-styles", "styles": {}},
                    {"style_type": "mobile-styles", "properties": {}, "styles": {}}
                ]
            },
            "amp": null,
            "created": "2026-04-10T14:22:00+00:00",
            "updated": "2026-04-10T14:22:00+00:00"
        },
        "links": {
            "self": "https://a.klaviyo.com/api/templates/Qw8tRm/"
        }
    },
    "links": {
        "self": "https://a.klaviyo.com/api/templates/Qw8tRm"
    }
}

Querying templates

Querying templates with the Templates API can help you achieve many use cases, such as sorting templates by the date they were created. Check out the supported query parameters below and test them with our latest Postman collection. Note that support for given operators and fields is endpoint-specific. Review the API reference documentation for more information on allowed fields and query operators.

ParameterDescriptionQuery example
filterRetrieve a subset of templates, e.g., templates that have been created within a given time frame. Learn about the filter query parameter.GET /api/templates?filter=greater-than(created,"2023-06-05T12:30:00+00:00")
sortSort templates, e.g., by date created in ascending order (oldest to newest). Learn about the sort query parameter.GET /api/templates?sort=created
fieldsRequest for only specified template data, e.g., name. Learn more about sparse fieldsets.GET /api/templates?fields[template]=name
additional-fields[template]Include the definition attribute for each template in Get Templates responses (needed for SYSTEM_DRAGGABLE templates). Learn more about additional fields.GET /api/templates?additional-fields[template]=definition

Additional resources