> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailchannels.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send an Email Asynchronously

> Queues an email message for asynchronous processing and returns immediately with a request ID.

The email will be processed in the background, and you'll receive webhook events
for all delivery status updates (e.g. dropped, processed, delivered, hard-bounced).
These webhook events are identical to those sent for the synchronous /send endpoint.

Use this endpoint when you need to send emails without waiting for processing to complete.
This can improve your application's response time, especially when sending to multiple recipients.




## OpenAPI

````yaml /email-api/api-reference/openapi.yaml post /send-async
openapi: 3.0.0
info:
  contact:
    email: support@mailchannels.com
    name: MailChannels Corporation
  description: >
    This is the API reference for Email API. Here, you'll find more detailed
    information on every endpoint, including parameters, response formats, and
    error codes.
  title: Email API
  version: 1.4.0
servers:
  - url: https://api.mailchannels.net/tx/v1
security: []
tags:
  - name: Send
  - name: DKIM
  - name: Metrics
  - name: Sub-accounts
  - name: Suppression
  - name: Webhooks
  - name: Usage
  - name: Custom Tracking
paths:
  /send-async:
    post:
      tags:
        - Send
      summary: Send an Email Asynchronously
      description: >
        Queues an email message for asynchronous processing and returns
        immediately with a request ID.


        The email will be processed in the background, and you'll receive
        webhook events

        for all delivery status updates (e.g. dropped, processed, delivered,
        hard-bounced).

        These webhook events are identical to those sent for the synchronous
        /send endpoint.


        Use this endpoint when you need to send emails without waiting for
        processing to complete.

        This can improve your application's response time, especially when
        sending to multiple recipients.
      parameters:
        - in: header
          name: X-Api-Key
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MailSendBody'
        required: true
      responses:
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AsyncSendResponse'
          description: Request accepted and queued for processing
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Bad Request
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: User does not have access to this feature
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: >
            Payload too large - The total message size should not exceed 30MB.

            This includes the message itself, headers, and the combined size of
            any attachments.
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Internal Server Error
      x-codeSamples:
        - label: Node.js
          lang: javascript
          source: >-
            import { MailChannels } from "mailchannels-sdk";


            const { MAILCHANNELS_API_KEY, FROM_EMAIL, TO_EMAIL } = process.env;

            if (!MAILCHANNELS_API_KEY) throw new Error("Set MAILCHANNELS_API_KEY
            before running");

            if (!FROM_EMAIL) throw new Error("Set FROM_EMAIL (must be on a
            Domain-Lockdown-authorized domain)");

            if (!TO_EMAIL) throw new Error("Set TO_EMAIL");


            const mailchannels = new MailChannels(MAILCHANNELS_API_KEY);


            const { data, error } = await mailchannels.emails.sendAsync({
              from: { email: FROM_EMAIL, name: "Your Name" },
              to: { email: TO_EMAIL, name: "Recipient" },
              subject: "Hello from MailChannels",
              text: "This message was queued for async delivery. Status updates will arrive via webhook.",
            });


            if (error) {
              console.error("Send failed:", error);
              process.exit(1);
            }

            console.log(data);
        - label: Python
          lang: python
          source: >-
            import os

            import sys


            import mailchannels


            if not os.environ.get("MAILCHANNELS_API_KEY"):
                sys.exit("Set MAILCHANNELS_API_KEY before running")

            from_email = os.environ.get("FROM_EMAIL")

            to_email = os.environ.get("TO_EMAIL")

            if not from_email:
                sys.exit("Set FROM_EMAIL (must be on a Domain-Lockdown-authorized domain)")
            if not to_email:
                sys.exit("Set TO_EMAIL")

            # Emails.queue posts to /tx/v1/send-async. Delivery events are
            reported via webhooks.

            response = mailchannels.Emails.queue(
                {
                    "from": {"email": from_email, "name": "Your Name"},
                    "to": [{"email": to_email, "name": "Recipient"}],
                    "subject": "Hello from MailChannels",
                    "text": "This message was queued for async delivery. Status updates will arrive via webhook.",
                }
            )


            print(response)
        - label: PHP
          lang: php
          source: >-
            <?php


            require_once __DIR__ . '/vendor/autoload.php';


            use MailChannels\Client;


            $api_key    = getenv('MAILCHANNELS_API_KEY') or exit("Error:
            MAILCHANNELS_API_KEY is not set\n");

            $from_email = getenv('FROM_EMAIL') or exit("Error: FROM_EMAIL is not
            set\n");

            $to_email   = getenv('TO_EMAIL') or exit("Error: TO_EMAIL is not
            set\n");


            $client = new Client(apiKey: $api_key);


            // emails->queue posts to /tx/v1/send-async. Delivery events are
            reported via webhooks.

            $response = $client->emails->queue([
                'from'    => ['email' => $from_email, 'name' => 'Your Name'],
                'to'      => ['email' => $to_email, 'name' => 'Recipient'],
                'subject' => 'Hello from MailChannels',
                'text'    => 'This message was queued for async delivery. Status updates will arrive via webhook.',
            ]);


            print_r($response->toArray());
components:
  schemas:
    MailSendBody:
      properties:
        attachments:
          items:
            $ref: '#/components/schemas/Attachment'
          maxItems: 1000
          type: array
        campaign_id:
          description: >
            The campaign identifier. If specified, this ID will be included in
            all relevant webhooks. It can be up to 48 UTF-8 characters long and
            must not contain spaces.
          type: string
        content:
          items:
            $ref: '#/components/schemas/ContentItem'
          type: array
        dkim_domain:
          description: |
            If set, you must also provide the matching dkim_selector.
          type: string
        dkim_private_key:
          description: >
            Encoded in Base64.

            If set, you must also provide the matching dkim_domain and
            dkim_selector.
          type: string
        dkim_selector:
          description: >
            If set without a matching dkim_domain, the domain will be taken from
            the `from` email address.
          type: string
        envelope_from:
          $ref: '#/components/schemas/EmailAddress'
          description: >
            Optional envelope sender address. If not set, the envelope sender
            defaults to the from.email field.

            Can be overridden per-personalization.

            Only the email portion is used; the name field is ignored.
        from:
          $ref: '#/components/schemas/EmailAddress'
        headers:
          additionalProperties:
            type: string
          description: >
            A JSON object containing key-value pairs, where both keys (header
            names) and values must be strings.

            These pairs represent custom headers to be substituted. Please note
            the following restrictions and behavior:

            - Reserved headers: The following headers cannot be modified:
              - Authentication-Results
              - BCC
              - CC
              - Content-Transfer-Encoding
              - Content-Type
              - DKIM-Signature
              - From
              - Message-ID
              - Received
              - Reply-To
              - Subject
              - To
            - Header precedence: If a header is defined in both the
            personalizations object and the root headers,

            the value from personalizations will be used.

            - Case sensitivity: Headers are treated as case-insensitive. If
            multiple headers differ only by case,

            only one will be used, with no guarantee of which one.
          type: object
        personalizations:
          items:
            $ref: '#/components/schemas/Personalization'
          maxItems: 1000
          type: array
        reply_to:
          $ref: '#/components/schemas/EmailAddress'
        subject:
          type: string
        tracking_settings:
          description: >
            Settings to adjust open and click tracking for the message. Please
            note that

            enabling tracking for your messages requires a subscription that
            supports open

            and click tracking.
          properties:
            click_tracking:
              properties:
                custom_domain_name:
                  description: >
                    The name of a configured active click tracking domain. When
                    specified, click

                    tracking links will use this domain instead of the default
                    MailChannels domain.

                    The domain must be registered in your account and have an
                    active status.
                  maxLength: 64
                  pattern: ^[a-z0-9-]+$
                  type: string
                enable:
                  default: false
                  description: >
                    Setting to enable or disable click tracking for the message.

                    This feature allows you to track when a recipient clicks a
                    link in your email.
                  type: boolean
              type: object
            open_tracking:
              properties:
                custom_domain_name:
                  description: >
                    The name of a configured active open tracking domain. When
                    specified, the open

                    tracking pixel will use this domain instead of the default
                    MailChannels domain.

                    The domain must be registered in your account and have an
                    active status.
                  maxLength: 64
                  pattern: ^[a-z0-9-]+$
                  type: string
                enable:
                  default: false
                  description: >
                    Setting to enable or disable open tracking for the message.

                    This feature allows you to track when a recipient opens your
                    email.

                    Please note that some email clients may not support open
                    tracking.
                  type: boolean
              type: object
          type: object
        transactional:
          default: true
          description: >
            Mark these messages as transactional or non-transactional.

            In order for a message to be marked as non-transactional,

            it must have exactly one recipient per personalization,

            and it must be DKIM signed. 400 Bad Request will be returned

            if there are more than one recipient in any personalization for

            non-transactional messages.

            If a message is marked as non-transactional, it changes the sending
            process as follows:
              * List-Unsubscribe and List-Unsubscribe-Post headers will be added, unless you supply your own List-Unsubscribe header, in which case yours is used and neither is added.
          nullable: true
          type: boolean
        unsubscribe_settings:
          description: |
            Settings to customize the unsubscribe experience for the message.
          properties:
            custom_domain_name:
              description: >
                The name of a configured active unsubscribe tracking domain.
                When specified,

                unsubscribe links will use this domain instead of the default
                MailChannels domain.

                The domain must be registered in your account and have an active
                status.
              maxLength: 64
              pattern: ^[a-z0-9-]+$
              type: string
          type: object
      required:
        - personalizations
        - from
        - subject
        - content
      type: object
    AsyncSendResponse:
      properties:
        queued_at:
          description: |
            ISO 8601 timestamp when the request was queued for processing.
          format: date-time
          type: string
        request_id:
          description: |
            Unique identifier for tracking this async request.
            Will be included in all webhook events for this request.
          type: string
      required:
        - request_id
        - queued_at
      type: object
    ErrorResponse:
      properties:
        errors:
          description: >
            This is an array error objects that provide machine and human
            readable descriptions of the errors.
          items:
            type: string
          type: array
      type: object
    Attachment:
      properties:
        content:
          description: the attachment data, encoded in base64
          type: string
        filename:
          description: the name of the attachment file
          type: string
        type:
          description: the MIME type of the attachment
          type: string
      required:
        - content
        - filename
      type: object
    ContentItem:
      properties:
        template_type:
          description: The template type of the content
          enum:
            - mustache
          type: string
        type:
          description: The mime type of the content you are including in your email
          type: string
        value:
          description: >-
            The actual content of the specified mime type that you are including
            in the message
          type: string
      required:
        - type
        - value
      type: object
    EmailAddress:
      properties:
        email:
          type: string
        name:
          description: Display name in raw text, e.g. John Doe, 张三
          type: string
      required:
        - email
      type: object
    Personalization:
      properties:
        bcc:
          items:
            $ref: '#/components/schemas/EmailAddress'
          maxItems: 1000
          type: array
        cc:
          items:
            $ref: '#/components/schemas/EmailAddress'
          maxItems: 1000
          type: array
        dkim_domain:
          description: |
            If set, you must also provide the matching dkim_selector.
          type: string
        dkim_private_key:
          description: >
            Encoded in Base64.

            If set, you must also provide the matching dkim_domain and
            dkim_selector.
          type: string
        dkim_selector:
          description: >
            If set without a matching dkim_domain, the domain will be taken from
            the `from` email address.
          type: string
        dynamic_template_data:
          description: >
            A JSON object containing key-value pairs of variables to set for
            template rendering.

            Keys must be strings, and values can be one of the following types:

            * string

            * boolean

            * number

            * list, whose values are all of permitted types

            * map, whose keys must be strings, and whose values are all of
            permitted types
          type: object
        envelope_from:
          $ref: '#/components/schemas/EmailAddress'
          description: >
            Optional envelope sender address. If set, overrides the root-level
            envelope_from and from.email for this personalization.

            Only the email portion is used; the name field is ignored.
        from:
          $ref: '#/components/schemas/EmailAddress'
        headers:
          additionalProperties:
            type: string
          description: >
            A JSON object containing key-value pairs, where both keys (header
            names) and values must be strings.

            These pairs represent custom headers to be substituted. Please note
            the following restrictions and behavior:

            - Reserved headers: The following headers cannot be modified:
              - Authentication-Results
              - BCC
              - CC
              - Content-Transfer-Encoding
              - Content-Type
              - DKIM-Signature
              - From
              - Message-ID
              - Received
              - Reply-To
              - Subject
              - To
            - Header precedence: If a header is defined in both the
            personalizations object and the root headers,

            the value from personalizations will be used.

            - Case sensitivity: Headers are treated as case-insensitive. If
            multiple headers differ only by case,

            only one will be used, with no guarantee of which one.
          type: object
        reply_to:
          $ref: '#/components/schemas/EmailAddress'
        subject:
          type: string
        to:
          items:
            $ref: '#/components/schemas/EmailAddress'
          maxItems: 1000
          minItems: 1
          type: array
      required:
        - to

````