Send an email

You can send an email about an entity using the REST API.

Overview

The workspace-level mails resource is available when the referenced entity type supports the mailing feature. The email is sent on behalf of the calling user, who is automatically added to the CC list.

Required permission: Send mail.

Endpoint

POST .../api/shared_spaces/{space_id}/workspaces/{workspace_id}/mails

For example, to send an email about defect 1042:

POST .../api/shared_spaces/1001/workspaces/1002/mails

Request

The request body is a JSON object with a data array. Each item in the array defines one email to send. You can batch multiple emails in a single request.

The top-level request object is a MailsCollection, and each item in data is a MailJson object.

Request body fields

Field Description
subject Email subject line.
message Email body. HTML is supported. Used as comment body when add_as_comment is true.
mail_entities Required. The entities whose details are rendered in the email. Each item requires id and type. At least one entity is required. Duplicates are removed.
to_recipients Primary recipients. See Recipient format below. At least one recipient is required across to_recipients, cc_recipients, and bcc_recipients.
cc_recipients CC recipients. The calling user is added to CC automatically.
bcc_recipients BCC recipients.
include_attachments If true, the entity's file attachments are included in the email. Default: false.
separated_emails If true, one email is sent per entity instead of a combined email, and subject is reset to null. Default: false.
add_as_comment If true, the message is also added as a comment on each entity that supports comments. Requires comment creation permission. Skipped if message is blank after HTML stripping.
mail_importance Written to the MIME Importance header as provided. Common values: High, Normal, Low.
should_check_recipients_limit If true, validates the total number of recipients against the configured site limit. Default: false (limit is not enforced).

Validation rules:

  • subject must be non-empty. Newlines are replaced with spaces.
  • At least one recipient must exist across to_recipients, cc_recipients, and bcc_recipients.
  • mail_entities.data must contain at least one entity.

Recipient format

Each recipient object in a to_recipients, cc_recipients, or bcc_recipients list uses one of the following formats:

Recipient type Format
Workspace user { "id": 1001, "type": "workspace_user" }
Team { "id": 55, "type": "team" } — all team members receive the email.
External address { "type": "external_email", "email": "user@example.com" } — only available if external email is enabled for the site.

Recipient rules:

  • Internal recipient: id is set, email is blank, and type is not external_email.
  • External recipient: id is null, email is non-blank, and type is external_email.
  • type: "team" expands to team members. Any other non-external type is treated as a user ID type.

Example

Send an email about defect 1042 to a workspace user and a team, with an external BCC:

POST .../api/shared_spaces/1001/workspaces/1002/mails
Content-Type: application/json

{
  "data": [
    {
      "subject": "Defect #1042 - Login crash on Safari",
      "message": "<p>Please review this defect.</p>",
      "mail_entities": {
        "data": [
          { "id": 1042, "type": "defect" }
        ]
      },
      "to_recipients": {
        "data": [
          { "id": 1001, "type": "workspace_user" }
        ]
      },
      "cc_recipients": {
        "data": [
          { "id": 55, "type": "team" }
        ]
      },
      "bcc_recipients": {
        "data": [
          { "type": "external_email", "email": "external@example.com" }
        ]
      },
      "include_attachments": false,
      "add_as_comment": false,
            "mail_importance": "High"
    }
  ]
}

Send with file attachments

To include file attachments in the email, send a multipart/form-data request instead of JSON. The request must include:

  • A part named mail containing the JSON payload (Content-Type: application/json).
  • One part named attachments per file to attach.

Example:

POST .../api/shared_spaces/1001/workspaces/1002/mails
Content-Type: multipart/form-data; boundary=a1b2c3d4

--a1b2c3d4
Content-Disposition: form-data; name="mail"
Content-Type: application/json

{
  "data": [
    {
      "subject": "Defect #1042",
      "message": "<p>See attached report.</p>",
      "mail_entities": { "data": [ { "id": 1042, "type": "defect" } ] },
      "to_recipients": { "data": [ { "id": 1001, "type": "workspace_user" } ] }
    }
  ]
}
--a1b2c3d4
Content-Disposition: form-data; name="attachments"; filename="report.pdf"
Content-Type: application/pdf

--a1b2c3d4--

Note: The boundary value (a1b2c3d4 in the example) is arbitrary — use any unique string that does not appear in the body content. Your HTTP client or library reads the file from disk and embeds the bytes automatically when you specify the file path.

Note: Attachment filenames are sanitized ([=+;:'"\[{}\\/|?, ] becomes _) and prefixed with a UUID. Upload size is capped by the STORAGE_MAX_FILE_SIZE site parameter.

Response

The response returns a MailsCollection object with total_count, data (successful mails only), and errors (when failures exist).

Each item in response data is a MailJson object.

Per-mail failures are not fatal to the entire request. Failed mails are removed from data and appended to errors. A partial failure can still return HTTP 200.

External recipients are controlled by ALLOWED_EXTERNAL_EMAIL_DOMAINS (* allows all; empty rejects all external addresses). Sender auto-copy is controlled by SEND_EMAIL_ALWAYS_COPY_SENDER.

Common error codes:

Error code Description
platform.send_mail_error Missing or empty required field (such as subject, mail_entities, or recipients).
platform.general_error An unexpected error occurred while sending the email.