From 72776a0ae992bf37647525ba999a8fc075a78a82 Mon Sep 17 00:00:00 2001 From: Jared Hoover Date: Wed, 2 Sep 2026 17:45:02 -0500 Subject: [PATCH 1/3] update custom email --- .../saas-integrations/custom-email/index.md | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/pages/rest/saas-integrations/custom-email/index.md b/src/pages/rest/saas-integrations/custom-email/index.md index cfee71b18..4b1082dc4 100644 --- a/src/pages/rest/saas-integrations/custom-email/index.md +++ b/src/pages/rest/saas-integrations/custom-email/index.md @@ -99,13 +99,15 @@ The API returns HTTP 200 on successful send. The `reply_to_email` field is only ## Manage custom email templates -Use the following endpoints to list, retrieve, and create custom email templates from the REST API. +Use the following endpoints to list, retrieve, create, update, and delete custom email templates from the REST API. | Method | Endpoint | Description | | --- | --- | --- | | `GET` | `/V1/custom-email/templates` | List custom email templates, returning each template's ID, code, subject, and type. | | `GET` | `/V1/custom-email/templates/{id}` | Retrieve a single template, including its body and styles. | | `POST` | `/V1/custom-email/templates` | Create a custom email template and return its server-assigned ID. | +| `PUT` | `/V1/custom-email/templates/{id}` | Update an existing custom email template. | +| `DELETE` | `/V1/custom-email/templates/{id}` | Delete a custom email template. | @@ -260,6 +262,85 @@ The response returns the created template in the same shape as [Retrieve a custo Example: `"message": "A custom email template with code \"my_code\" already exists."` +### Update a custom email template + +Use the following endpoint to update an existing custom email template by its ID. + +#### Endpoint + +- **URL** - `PUT /rest/V1/custom-email/templates/{id}` + +The `{id}` in the URL identifies the template to update. A `template_id` supplied in the request body is ignored. + +#### Request body + +Use a `template` object to contain the fields to update. This is a **partial update**, which means that only the fields present in the request body are changed. Fields that are not included keep their previous value. + +- **template_code** (string, optional) – Must remain unique across templates. Maximum 150 characters. The template being updated is excluded from the uniqueness check, so keeping the existing code is allowed. +- **template_subject** (string, optional) – Maximum 200 characters. Supports the same directive syntax as create, described in [Supported template scenarios](#supported-template-scenarios). +- **template_text** (string, optional) – Raw template body. Directives are stored as-is and are not rendered at update time. +- **template_type** (string, optional) – `html` or `text`. Switching to `text` forces `template_styles` to an empty string. +- **template_styles** (string, optional) – CSS for the template. Ignored when the `template_type` is `text`. + + + +Included fields cannot contain empty values. Sending an empty `template_code`, `template_subject`, or `template_text` returns an **HTTP 400** error. To leave a field unchanged, do not include it. + +#### Example request + +```json +{ + "template": { + "template_subject": "You *still* left something behind", + "template_text": "

Hi {{var customer.name}}, your cart really misses you.

" + } +} +``` + +#### Success response (HTTP 200) + +The response returns the updated template in the same shape as [Retrieve a custom email template](#retrieve-a-custom-email-template). + +#### Error responses + +- **HTTP 400 – Validation error** + + Returned for an over-length value, an invalid `template_type`, or a required field that was supplied as an empty value. + +- **HTTP 404 – Template not found** + + Returned when no custom template matches the given `id`. + +- **HTTP 409 – Duplicate template code** + + Returned when the new `template_code` collides with another existing template. + + Example: `"message": "A custom email template with code \"my_code\" already exists."` + +### Delete a custom email template + +Use the following endpoint to delete a custom email template by its ID. + +#### Endpoint + +- **URL** - `DELETE /rest/V1/custom-email/templates/{id}` + +#### Success response (HTTP 200) + +The API returns `true` in the response body on successful deletion. + +#### Error responses + +- **HTTP 404 – Template not found** + + Returned when no custom template matches the given `id`. + +- **HTTP 409 – Template in use** + + Returned when the template is currently referenced by store configuration, for example assigned as the template for a Sales Email under **Stores** > _Configuration_ > **Sales** > **Sales Emails**. Clear or reassign the configuration, then try the delete call again. + + Example: `"message": "The custom email template with id \"5\" is currently in use and cannot be deleted."` + ## Supported template scenarios The following template features are supported in both the **email body** and the **template subject**: From b75d78c051e9ac3efe92a0415e0b2effa2af88f2 Mon Sep 17 00:00:00 2001 From: Jared Hoover Date: Thu, 3 Sep 2026 12:52:46 -0500 Subject: [PATCH 2/3] review - template object unified --- .../saas-integrations/custom-email/index.md | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/pages/rest/saas-integrations/custom-email/index.md b/src/pages/rest/saas-integrations/custom-email/index.md index 4b1082dc4..cc086a71c 100644 --- a/src/pages/rest/saas-integrations/custom-email/index.md +++ b/src/pages/rest/saas-integrations/custom-email/index.md @@ -14,7 +14,7 @@ Previously, you could only send emails when events were triggered, such as durin -Currently, only newly created, custom templates can be sent. Predefined and system templates are not supported. +Currently, only customer-created custom templates can be sent. Predefined and system templates are not supported. The `V1/custom-email/send` endpoint allows **third-party systems**, such as integrations and external services, to send emails on demand by specifying: @@ -113,6 +113,21 @@ Use the following endpoints to list, retrieve, create, update, and delete custom Use the `template_id` returned by these endpoints with `POST /V1/custom-email/send` instead of looking up the ID manually. +### Template object + +The `template` object represents a custom email template. Create and update requests wrap these fields in a `template` object, while list and retrieve responses return the same fields at the top level of the response. + +| Field | Type | Description | +| --- | --- | --- | +| `template_id` | integer | Server-assigned identifier. Use it as-is with `POST /V1/custom-email/send`. Read-only, and ignored if supplied in a request body. | +| `template_code` | string | Unique template name. Maximum 150 characters. | +| `template_subject` | string | Template subject, stored as raw, unrendered directive source. Maximum 200 characters. Supports the directive syntax described in [Supported template scenarios](#supported-template-scenarios). | +| `template_text` | string | Raw, unrendered template body. Directives such as `{{var}}` and `{{trans}}` are stored as-is and preserved verbatim. Not returned by the list endpoint. | +| `template_type` | string | `html` or `text`. Defaults to `html` on create. Switching to `text` forces `template_styles` to an empty string. | +| `template_styles` | string | CSS for the template. Empty string for text templates. Not returned by the list endpoint. | +| `added_at` | string | Creation timestamp. Read-only. | +| `modified_at` | string | Last-modified timestamp. Read-only. | + ### List custom email templates Use the following endpoint to list all custom email templates. @@ -125,14 +140,7 @@ The endpoint accepts standard `searchCriteria` parameters for pagination, sortin #### Response fields -| Field | Type | Description | -| --- | --- | --- | -| `template_id` | integer | Usable as-is with `POST /V1/custom-email/send`. | -| `template_code` | string | Template name. | -| `template_subject` | string | Template subject, as raw, unrendered directive source. | -| `template_type` | string | `html` or `text`. | -| `added_at` | string | Creation timestamp. | -| `modified_at` | string | Last-modified timestamp. | +The response includes the [template object](#template-object) fields, except `template_text` and `template_styles`. #### Example request @@ -170,12 +178,7 @@ Use the following endpoint to retrieve a single custom email template by its ID. - **URL** - `GET /rest/V1/custom-email/templates/{id}` -The response includes every field from the list response, plus: - -| Field | Type | Description | -| --- | --- | --- | -| `template_text` | string | Raw, unrendered template body. Directives such as `{{var}}` and `{{trans}}` are preserved, so the value can be sent back verbatim when creating another template. | -| `template_styles` | string | CSS for the template. Empty string for text templates. | +The response includes all [template object](#template-object) fields, including `template_text` and `template_styles`. #### Example request @@ -218,15 +221,12 @@ Commerce returns HTTP 200 (not 201) on success, consistent with other Commerce R #### Request body -Wrap the template fields in a `template` object. - -- **template_code** (string, required) – Unique template name. Maximum 150 characters. -- **template_subject** (string, required) – Maximum 200 characters. May contain directive syntax, as described in [Supported template scenarios](#supported-template-scenarios). -- **template_text** (string, required) – Raw template body. Directives are stored as-is and are not rendered at creation time. -- **template_type** (string, optional) – `html` (default) or `text`. -- **template_styles** (string, optional) – CSS for the template. Ignored, and forced to an empty string, when `template_type` is `text`. +Wrap the template fields in a `template` object. See [Template object](#template-object) for the full field definitions. -The API ignores any value supplied for `template_id`, `added_at`, or `modified_at`, Commerce assigns these automatically. +- **Required** - `template_code`, `template_subject`, and `template_text` +- **Optional** - `template_type` and `template_styles` +- **Read-only** - `template_id`, `added_at`, and `modified_at` + - Commerce assigns these automatically and ignores any supplied values. @@ -274,13 +274,10 @@ The `{id}` in the URL identifies the template to update. A `template_id` supplie #### Request body -Use a `template` object to contain the fields to update. This is a **partial update**, which means that only the fields present in the request body are changed. Fields that are not included keep their previous value. +Wrap the fields to change in a `template` object. The request accepts the same [template object](#template-object) fields as create, with these differences: -- **template_code** (string, optional) – Must remain unique across templates. Maximum 150 characters. The template being updated is excluded from the uniqueness check, so keeping the existing code is allowed. -- **template_subject** (string, optional) – Maximum 200 characters. Supports the same directive syntax as create, described in [Supported template scenarios](#supported-template-scenarios). -- **template_text** (string, optional) – Raw template body. Directives are stored as-is and are not rendered at update time. -- **template_type** (string, optional) – `html` or `text`. Switching to `text` forces `template_styles` to an empty string. -- **template_styles** (string, optional) – CSS for the template. Ignored when the `template_type` is `text`. +- All fields are **optional**. This is a **partial update**, so only the fields present in the request body are changed. Fields that are not included keep their previous value. +- `template_code` is excluded from its own uniqueness check, so keeping the existing code is allowed. From f19952e2f484f144a8a207ac916d89906896e1d0 Mon Sep 17 00:00:00 2001 From: Jared Hoover Date: Thu, 3 Sep 2026 12:58:17 -0500 Subject: [PATCH 3/3] heading change --- src/pages/rest/saas-integrations/custom-email/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/rest/saas-integrations/custom-email/index.md b/src/pages/rest/saas-integrations/custom-email/index.md index cc086a71c..3625945ad 100644 --- a/src/pages/rest/saas-integrations/custom-email/index.md +++ b/src/pages/rest/saas-integrations/custom-email/index.md @@ -113,7 +113,7 @@ Use the following endpoints to list, retrieve, create, update, and delete custom Use the `template_id` returned by these endpoints with `POST /V1/custom-email/send` instead of looking up the ID manually. -### Template object +### Template object parameters The `template` object represents a custom email template. Create and update requests wrap these fields in a `template` object, while list and retrieve responses return the same fields at the top level of the response. @@ -140,7 +140,7 @@ The endpoint accepts standard `searchCriteria` parameters for pagination, sortin #### Response fields -The response includes the [template object](#template-object) fields, except `template_text` and `template_styles`. +The response includes the [template object](#template-object-parameters) fields, except `template_text` and `template_styles`. #### Example request @@ -178,7 +178,7 @@ Use the following endpoint to retrieve a single custom email template by its ID. - **URL** - `GET /rest/V1/custom-email/templates/{id}` -The response includes all [template object](#template-object) fields, including `template_text` and `template_styles`. +The response includes all [template object](#template-object-parameters) fields, including `template_text` and `template_styles`. #### Example request @@ -221,7 +221,7 @@ Commerce returns HTTP 200 (not 201) on success, consistent with other Commerce R #### Request body -Wrap the template fields in a `template` object. See [Template object](#template-object) for the full field definitions. +Wrap the template fields in a `template` object. See [Template object](#template-object-parameters) for the full field definitions. - **Required** - `template_code`, `template_subject`, and `template_text` - **Optional** - `template_type` and `template_styles` @@ -274,7 +274,7 @@ The `{id}` in the URL identifies the template to update. A `template_id` supplie #### Request body -Wrap the fields to change in a `template` object. The request accepts the same [template object](#template-object) fields as create, with these differences: +Wrap the fields to change in a `template` object. The request accepts the same [template object](#template-object-parameters) fields as create, with these differences: - All fields are **optional**. This is a **partial update**, so only the fields present in the request body are changed. Fields that are not included keep their previous value. - `template_code` is excluded from its own uniqueness check, so keeping the existing code is allowed.