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

# Send email

> Sends a transactional email immediately or at a scheduled time. Provide the HTML or plain-text body inline. The `from` address must belong to a verified sending domain in the project.

`to` accepts email addresses or a single audience id — a topic (`top_<ulid>`) or segment (`seg_<ulid>`). Multiple direct addresses without `cc` or `bcc` fan out to one message per address, and the response reports the first accepted message plus a `messages` entry per recipient. Each fan-out message has its own delivery status, tracking, and unsubscribe links. If multiple `to` addresses are combined with `cc` or `bcc`, SES receives one shared message and its status is aggregate. An audience must be the only recipient and cannot be combined with `cc` or `bcc`, and at most 50 recipients fan out per request — the fan-out is paced to the project's per-second send limit.

Emails are delivered through Amazon SES. Delivery events are available through webhooks and the email timeline endpoint.

### Requirements

- **Permission:** `emails:send`.
- **Safe retries:** place `idempotencyKey` in the JSON body; Apollo Signal does not use an idempotency header.
- **HTTP rate limit:** 300 requests per 60 seconds per API key.



## OpenAPI

````yaml /signal/api-reference/openapi.json post /v1/emails
openapi: 3.1.0
info:
  title: Apollo Signal API
  version: 1.0.0
  description: >-
    Public REST API for transactional email, contacts, audiences, webhooks,
    metrics, projects, and sending domains.
servers:
  - url: https://api.signal.apollodeploy.com
    description: Production
security: []
tags:
  - name: Emails
    description: Send, inspect, cancel, validate, and stream transactional email activity.
  - name: Metrics
    description: Read project, topic, message, and deliverability analytics.
  - name: Suppressions
    description: Manage addresses that Apollo Signal must not send to.
  - name: Segments
    description: Create dynamic contact groups and inspect their membership.
  - name: Topics
    description: Manage subscription topics and topic membership.
  - name: Contact properties
    description: Define the custom fields available on project contacts.
  - name: Contacts
    description: >-
      Manage contacts, audience membership, images, activity, and engagement
      data.
  - name: Webhooks
    description: Manage webhook endpoints, deliveries, tests, and replays.
  - name: API key usage
    description: Inspect API key metadata and request usage without exposing raw keys.
  - name: Projects
    description: Inspect projects and project-scoped email logs.
  - name: Sending domains
    description: >-
      Register, verify, inspect, and remove sending domains and BIMI
      configuration.
paths:
  /v1/emails:
    post:
      tags:
        - Emails
      summary: Send email
      description: >-
        Sends a transactional email immediately or at a scheduled time. Provide
        the HTML or plain-text body inline. The `from` address must belong to a
        verified sending domain in the project.


        `to` accepts email addresses or a single audience id — a topic
        (`top_<ulid>`) or segment (`seg_<ulid>`). Multiple direct addresses
        without `cc` or `bcc` fan out to one message per address, and the
        response reports the first accepted message plus a `messages` entry per
        recipient. Each fan-out message has its own delivery status, tracking,
        and unsubscribe links. If multiple `to` addresses are combined with `cc`
        or `bcc`, SES receives one shared message and its status is aggregate.
        An audience must be the only recipient and cannot be combined with `cc`
        or `bcc`, and at most 50 recipients fan out per request — the fan-out is
        paced to the project's per-second send limit.


        Emails are delivered through Amazon SES. Delivery events are available
        through webhooks and the email timeline endpoint.


        ### Requirements


        - **Permission:** `emails:send`.

        - **Safe retries:** place `idempotencyKey` in the JSON body; Apollo
        Signal does not use an idempotency header.

        - **HTTP rate limit:** 300 requests per 60 seconds per API key.
      operationId: sendEmail
      parameters: []
      requestBody:
        description: >-
          Email message including sender, recipients (addresses or a topic /
          segment id), subject, body content, and optional scheduling and
          tracking configuration.
        content:
          application/json:
            schema:
              $ref: >-
                #/components/schemas/com.apollodeploy.signal.feature.email.api.model.SendEmailRequest
        required: true
      responses:
        '201':
          description: >-
            Email accepted for delivery. The `id` can be used to retrieve status
            or cancel. For a recipient fan-out, `messages` lists one entry per
            recipient message; each entry can be tracked independently.
          headers: {}
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.signal.feature.email.api.model.SendEmailResponse
        '400':
          description: >-
            Validation error — missing required fields, invalid address format,
            body not provided, or an audience combined with other recipients,
            `cc`, or `bcc`.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
        '401':
          description: Missing or invalid API key.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
        '403':
          description: >-
            The credential lacks the required permission or cannot access this
            project.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
        '413':
          description: >-
            The referenced topic or segment has more than the 50-recipient limit
            for one send request.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
        '422':
          description: >-
            The `from` domain is not verified, the project is suspended, or the
            referenced topic/segment has no recipients that could be sent to.
          headers: {}
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
        '429':
          description: >-
            The endpoint rate limit was exceeded. Wait for the `Retry-After`
            interval before retrying.
          headers:
            Retry-After:
              description: Whole seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
          content:
            application/problem+json:
              schema:
                $ref: >-
                  #/components/schemas/com.apollodeploy.commons.core.error.ApiProblem
      deprecated: false
      security:
        - bearerAuth: []
      x-codeSamples:
        - lang: TypeScript
          label: TypeScript
          source: >-
            import { createApolloSignalApiClient } from
            "@apollo-deploy/signal-sdk";


            const signal = createApolloSignalApiClient({ apiKey: "ap_signal_..."
            });


            const result = await signal.emails.sendEmail(/* params */);


            console.log(result);
        - lang: Python
          label: Python
          source: |-
            from apollo_signal import SignalClient

            signal = SignalClient(api_key="ap_signal_...")

            result = signal.emails.sendEmail(# params)

            print(result)
        - lang: Go
          label: Go
          source: >-
            import signal "github.com/apollo-deploy/signal-sdk-go"


            client := signal.NewClient("ap_signal_...")


            result, err := client.Emails.SendEmail(context.Background() /*
            params */)

            if err != nil {
                log.Fatal(err)
            }

            fmt.Println(result)
        - lang: Java
          label: Java
          source: |-
            import com.apollodeploy.signal.SignalClient;

            SignalClient signal = new SignalClient("ap_signal_...");

            var result = signal.emails().sendEmail(/* params */);
            System.out.println(result);
        - lang: Kotlin
          label: Kotlin
          source: |-
            import com.apollodeploy.signal.SignalClient

            val signal = SignalClient("ap_signal_...")

            val result = signal.emails.sendEmail(/* params */)
            println(result)
        - lang: Ruby
          label: Ruby
          source: |-
            require "apollo_signal"

            signal = ApolloSignal::Client.new(api_key: "ap_signal_...")

            result = signal.emails.sendEmail(# params)
            puts result
        - lang: PHP
          label: PHP
          source: |-
            use ApolloSignal\SignalClient;

            $signal = new SignalClient("ap_signal_...");

            $result = $signal->emails->sendEmail(/* params */);
            var_dump($result);
        - lang: Rust
          label: Rust
          source: |-
            use apollo_signal::SignalClient;

            let signal = SignalClient::new("ap_signal_...");

            let result = signal.emails.sendEmail(/* params */).await?;
            println!("{:?}", result);
        - lang: C#
          label: .NET
          source: |-
            using ApolloSignal;

            var signal = new SignalClient("ap_signal_...");

            var result = await signal.Emails.SendEmailAsync(/* params */);
            Console.WriteLine(result);
components:
  schemas:
    com.apollodeploy.signal.feature.email.api.model.SendEmailRequest:
      type: object
      properties:
        attachments:
          type: array
          items:
            $ref: >-
              #/components/schemas/com.apollodeploy.signal.feature.email.api.model.AttachmentRequest
          title: List<AttachmentRequest>
          description: >-
            Base64-encoded attachments. The decoded total must fit the
            configured attachment limit, and the message may contain at most 500
            MIME parts including bodies.
        bcc:
          type: array
          items:
            type: string
            title: String
          title: List<String>
          description: >-
            Blind-carbon-copy recipient addresses. These count toward the
            project's per-message recipient limit.
        cc:
          type: array
          items:
            type: string
            title: String
          title: List<String>
          description: >-
            Carbon-copy recipient addresses. These count toward the project's
            per-message recipient limit.
        deliveryWindow:
          $ref: >-
            #/components/schemas/com.apollodeploy.signal.feature.email.api.model.DeliveryWindowRequest
          description: >-
            Allowed time window for an `optimal` non-transactional send.
            Required when optimization may delay the message.
        from:
          type: string
          title: String
          description: >-
            Sender address. Its domain must be verified in the authenticated
            project.
        html:
          type: string
          title: String
          description: HTML body. Supply `html`, `text`, or both.
        idempotencyKey:
          type: string
          title: String
          description: >-
            Project-scoped key that returns the original send result when the
            request is retried.
        metadata:
          type: object
          additionalProperties:
            type: string
            title: String
          title: Map<String,String>
          description: Caller-defined string metadata associated with the send.
        replyTo:
          type: string
          title: String
          description: Address that receives replies instead of the sender address.
        scheduledAt:
          type: string
          title: String
          description: >-
            ISO 8601 send time or `optimal`. Explicit times must be 30 seconds
            to 30 days in the future; omit to send immediately.
        sendTimeCategory:
          type: string
          title: String
          description: >-
            Delivery category. `transactional` messages are never delayed by
            optimal-time scheduling. Defaults to `transactional`.
          enum:
            - transactional
            - marketing
            - notification
            - digest
          default: transactional
        subject:
          type: string
          title: String
          description: Email subject. The request is rejected when this field is omitted.
        tags:
          type: object
          additionalProperties:
            type: string
            title: String
          title: Map<String,String>
          description: Caller-defined string labels used to categorize the email.
        testMode:
          type: boolean
          title: Boolean
          description: >-
            Exercises the send flow without delivering to real recipients.
            Defaults to `false`.
          default: false
        text:
          type: string
          title: String
          description: Plain-text body. Supply `html`, `text`, or both.
        to:
          type: array
          items:
            type: string
            title: String
          title: List<String>
          description: >-
            Recipient addresses, or one topic (`top_…`) or segment (`seg_…`)
            identifier. A single string is accepted. Audience sends are capped
            at 50 resolved recipients and cannot include `cc` or `bcc`.
        trackingSettings:
          $ref: >-
            #/components/schemas/com.apollodeploy.signal.feature.email.api.model.TrackingSettingsRequest
          description: Per-message overrides for the project's tracking settings.
      required:
        - from
        - to
        - subject
      title: SendEmailRequest
      description: >-
        Email content and delivery options. `from`, `to`, and `subject` are
        required, and at least one of `html` or `text` must be supplied.
    com.apollodeploy.signal.feature.email.api.model.SendEmailResponse:
      type: object
      properties:
        audienceId:
          type: string
          title: String
        createdAt:
          type: string
          title: String
        id:
          type: string
          title: String
        messageId:
          type: string
          title: String
        messages:
          type: array
          items:
            $ref: >-
              #/components/schemas/com.apollodeploy.signal.feature.email.api.model.BatchSendItemResponse
          title: List<BatchSendItemResponse>
        scheduledAt:
          type: string
          title: String
        status:
          type: string
          title: String
      required:
        - createdAt
        - id
        - status
      title: SendEmailResponse
    com.apollodeploy.commons.core.error.ApiProblem:
      type: object
      properties:
        code:
          type: string
          title: ErrorCode
        detail:
          type: string
          title: String
        errors:
          type: array
          items:
            $ref: >-
              #/components/schemas/com.apollodeploy.commons.core.error.FieldProblem
          title: List<FieldProblem>
        instance:
          type: string
          title: ProblemInstance
        requestId:
          type: string
          title: String
        status:
          type: integer
          format: int32
          title: Int
        title:
          type: string
          title: String
        type:
          type: string
          title: ProblemType
      required:
        - code
        - status
        - title
        - type
      title: ApiProblem
    com.apollodeploy.signal.feature.email.api.model.AttachmentRequest:
      type: object
      properties:
        content:
          type: string
          title: String
          description: Valid base64-encoded file content.
        contentId:
          type: string
          title: String
          description: >-
            Optional Content-ID used to reference an inline attachment from
            HTML.
        contentType:
          type: string
          title: String
          description: Non-empty MIME type for the attachment.
        disposition:
          type: string
          title: String
          description: 'MIME disposition: `attachment` (default) or `inline`.'
          enum:
            - attachment
            - inline
          default: attachment
        filename:
          type: string
          title: String
          description: File name without path separators or control characters.
      required:
        - filename
        - content
        - contentType
      title: AttachmentRequest
      description: One MIME attachment encoded inside the JSON request.
    com.apollodeploy.signal.feature.email.api.model.DeliveryWindowRequest:
      type: object
      properties:
        end:
          type: string
          title: String
          description: Inclusive ISO 8601 end of the delivery window.
          format: date-time
        start:
          type: string
          title: String
          description: Inclusive ISO 8601 start of the delivery window.
          format: date-time
      required:
        - end
        - start
      title: DeliveryWindowRequest
      description: ISO 8601 bounds used by optimal-time scheduling.
    com.apollodeploy.signal.feature.email.api.model.TrackingSettingsRequest:
      type: object
      properties:
        clickTracking:
          type: boolean
          title: Boolean
          description: Enable or disable tracked-link rewriting for this message.
        openTracking:
          type: boolean
          title: Boolean
          description: Enable or disable open-pixel tracking for this message.
        readEngagement:
          type: boolean
          title: Boolean
          description: Enable or disable read-engagement tracking for this message.
        unsubscribeTracking:
          type: boolean
          title: Boolean
          description: Enable or disable unsubscribe-link handling for this message.
      title: TrackingSettingsRequest
      description: >-
        Optional tracking overrides for one message; omitted fields inherit
        project settings.
    com.apollodeploy.signal.feature.email.api.model.BatchSendItemResponse:
      type: object
      properties:
        createdAt:
          type: string
          title: String
        error:
          type: string
          title: String
        id:
          type: string
          title: String
        index:
          type: integer
          format: int32
          title: Int
        messageId:
          type: string
          title: String
        scheduledAt:
          type: string
          title: String
        status:
          type: string
          title: String
      required:
        - index
      title: BatchSendItemResponse
    com.apollodeploy.commons.core.error.FieldProblem:
      type: object
      properties:
        detail:
          type: string
          title: String
        pointer:
          type: string
          title: String
      required:
        - detail
        - pointer
      title: FieldProblem
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Project-bound Apollo Signal API key. Keys begin with `ap_signal_` and
        must carry the permission shown on the operation.

````