Edit in GitHubLog an issue

Email triggering through the REST API

Previously, you could only send emails when events were triggered, such as during customer registration or order purchase. In Adobe Commerce as a Cloud Service, you can send emails through the REST API on demand by specifying a template ID, recipient email, and template variables.

The V1/custom-email/send endpoint allows third-party systems, such as integrations and external services, to send emails on demand by specifying:

  • Template ID – Email template ID.
  • Recipient email – The target email address for this request.
  • Variables – (Optional) Custom defined key-value pairs to inject into the template, such as customer_name or order_id.

REST contract

The following section explains how to send transactional emails on demand using the REST API.

Endpoint

  • URL - POST /rest/V1/custom-email/send

  • Authorization - Only service-to-service IMS authorization is supported. The caller must have access to the Send Custom Email via API (Magento_CustomEmailSend::send_custom_email) resource. Refer to REST authentication for more information.

  • Async usage (recommended) - Although this endpoint is implemented synchronously, we recommend calling it using the asynchronous REST API so that the request is queued and processed by a consumer, avoiding long-lived HTTP connections. In Adobe Commerce as a Cloud Service, you can use the route with /async after V1, for example: POST https://<server>.api.commerce.adobe.com/<tenant-id>/V1/async/custom-email/send.

    Refer to Asynchronous web endpoints for more information.

Request body

  • templateId (integer, required) – Email template ID as defined in the Admin under Marketing > Communications > Email Templates.

  • recipientEmail (string, required) – The target email address. Must be a valid email format. Missing or empty values trigger a validation error.

  • variables (object, optional) – Key-value map injected into the template as an UnstructuredArray.

    If you are not using variables, pass an empty object or omit it. In the email template body and subject, use the variable syntax to reference a variable, for example var order_id. The subject also supports the same custom variables and syntax described in Supported template scenarios.

Example request

Copied to your clipboard
{
"templateId": 5,
"recipientEmail": "john@example.com",
"variables": {
"customer_name": "John",
"order_id": "100000123",
"delivery_date": "Feb 15"
}
}

Success response (HTTP 200)

The API returns HTTP 200 on successful send.

Copied to your clipboard
{
"message": "Email accepted for delivery",
"reference_id": "a1b2c3d4e5f6-1707571800",
"recipient_email": "john@example.com",
"template_id": 5,
"template_code": "order_update_notification"
}

Error responses

  • HTTP 400 – Validation error

    The integration must supply a valid templateId and recipientEmail for each request.

    • "message": "Invalid recipient email format" – invalid or malformed recipient address
    • "message": "Recipient email is required." – missing or empty recipientEmail
    • "message": "Template ID must be a positive integer." – missing, zero, or invalid templateId
  • HTTP 404 – Template not found

    Example: "message": "Email template with ID \"999\" does not exist."

Supported template scenarios

The following template features are supported in both the email body and the template subject:

  • Include directive – to include other design templates, such as an email header.

    Copied to your clipboard
    {{template config_path="design/email/header_template"}}
  • Simple variables – use var variableName, for example var order_id or var g.

    Copied to your clipboard
    {{var order.test}}
    {{var g}}
    {{var order_id}}
  • Nested/dot notation – for nested keys passed in the request variables, in translations use dollar-prefixed names, such as $order_data.customer_name, $order.increment_id, or $order_data.frontend_status_label.

    Copied to your clipboard
    {{trans "%name," name=$order_data.customer_name}}
    {{trans "Your order #%increment_id has been updated with a status of **%order_status**." increment_id=$order.increment_id order_status=$order_data.frontend_status_label |raw}}
  • Translation (trans) – parameterized text, multi-line translations with multiple placeholders and HTML tags.

    Copied to your clipboard
    {{trans "%name," name=$order_data.customer_name}}
    {{trans "Your order #%increment_id has been updated with a status of **%order_status**." increment_id=$order.increment_id order_status=$order_data.frontend_status_label |raw}}
  • Raw output – use the |raw filter when the translated or variable content contains HTML (for example, <strong> or <a>).

    Copied to your clipboard
    {{trans "Your order #%increment_id has been updated with a status of **%order_status**." increment_id=$order.increment_id order_status=$order_data.frontend_status_label |raw}}
  • URL helper – for store URLs inside translations.

    Copied to your clipboard
    {{trans 'You can check the status of your order by [logging into your account](%account_url).' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}}
Was this helpful?
  • Privacy
  • Terms of Use
  • Do not sell or share my personal information
  • AdChoices
Copyright © 2026 Adobe. All rights reserved.