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

# Send message batch

> Accept up to 50 messages. All identity/template permissions and content-mode shapes are checked before enqueueing; denial rejects the entire request. Sending restrictions, quota, suppression, rendering and storage failures are returned per entry, in input order. queued means accepted, not delivered. Use one Idempotency-Key for the entire batch; retry rejected entries separately with a new key.

<Info>
  Requires the IAM action **`email:SendMessage`**. See [EMAIL permissions](/email/permissions) for the full list, what each one covers, and an example policy.
</Info>


## OpenAPI

````yaml /api-reference/specs/email.yaml post /v1/sent-messages/batch
openapi: 3.0.3
info:
  title: Basaltic Email API
  version: 1.0.0
  description: >
    Regional API for sending and receiving email, identities and DNS records,
    templates, configuration sets, IP pools, recipient rules, message content
    and attachments.


    Identities must be verified separately in every region. Create an identity,
    publish its dns_records, then request verification. Only verified identities
    can send or enable receiving.


    Request references accept a UUID, an account-unique name or a CRN of the
    expected resource type. Names are immutable. Malformed references or the
    wrong resource type/region return 400; missing or foreign-account references
    return 404. Resource paths use UUIDs. List filters are exact, account-scoped
    and applied before pagination; missing or foreign references return empty
    results.


    Sent and received message content expires after 30 days. Attachment objects
    follow their bucket lifecycle independently. Use Telemetry for aggregate
    metrics and the diagnostic endpoints for individual events and DMARC report
    records.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://email.{region}.basaltic.sh
    description: Regional API endpoint
    variables:
      region:
        default: sa-saopaulo-1
        description: Region code
security:
  - BearerAuth: []
tags:
  - name: Email
    description: Customer-facing email sending (regional).
paths:
  /v1/sent-messages/batch:
    post:
      tags:
        - Email
      summary: Send message batch
      description: >-
        Accept up to 50 messages. All identity/template permissions and
        content-mode shapes are checked before enqueueing; denial rejects the
        entire request. Sending restrictions, quota, suppression, rendering and
        storage failures are returned per entry, in input order. queued means
        accepted, not delivered. Use one Idempotency-Key for the entire batch;
        retry rejected entries separately with a new key.
      operationId: sendMessageBatch
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchSendRequest'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchSendResponse'
        '400':
          description: Invalid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Permission denied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Conflicting state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Quota or rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Dependency unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    BatchSendRequest:
      type: object
      required:
        - messages
      properties:
        messages:
          type: array
          minItems: 1
          maxItems: 50
          items:
            $ref: '#/components/schemas/SendMessageRequest'
    BatchSendResponse:
      type: object
      required:
        - results
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/BatchSendResult'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: Error code identifying the type of error
              example: INVALID_INPUT
            message:
              type: string
              description: Human-readable error message
              example: Invalid request parameters
            params:
              type: object
              additionalProperties: true
              description: >-
                Optional non-sensitive values for interpolation of localized
                errors, keyed by error code. Never present for server errors.
              example:
                instances: 2
                pools: 0
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
    SendMessageRequest:
      type: object
      required:
        - identity
        - from
        - to
        - content
      properties:
        attachments_bucket:
          type: string
          description: >-
            Bucket UUID, CRN or name for attachments embedded in raw MIME.
            Objects are written under email/{identity_id}/sent/{message_id}/.
            Separate attachments entries reference existing bucket objects.
        attachments:
          type: array
          description: >-
            Bucket objects to attach. GetObject permission is required; version
            and checksum are pinned at acceptance.
          items:
            $ref: '#/components/schemas/AttachmentInput'
        identity:
          type: string
          description: UUID, CRN or account-unique name.
        from:
          type: string
        to:
          type: array
          items:
            type: string
          minItems: 1
        subject:
          type: string
          description: >-
            Subject for text/HTML content. For raw or template content, the
            subject is supplied by that content.
        configuration_set:
          type: string
          description: UUID, CRN or account-unique name.
        content:
          $ref: '#/components/schemas/SendContent'
    BatchSendResult:
      type: object
      required:
        - index
        - status
      properties:
        index:
          type: integer
        status:
          type: string
          enum:
            - queued
            - rejected
        message:
          $ref: '#/components/schemas/ResourceRef'
        error:
          $ref: '#/components/schemas/error'
    AttachmentInput:
      type: object
      required:
        - bucket
        - key
        - name
      properties:
        bucket:
          type: string
          description: Same-account, same-region bucket name, UUID or CRN.
        key:
          type: string
          minLength: 1
        version_id:
          type: string
          description: Optional opaque Storage object version token.
        name:
          type: string
          minLength: 1
          description: Attachment filename.
        content_type:
          type: string
          description: MIME type; defaults to the object content type.
    SendContent:
      type: object
      properties:
        text:
          type: string
        html:
          type: string
        raw:
          type: string
          description: >-
            Complete RFC 5322 message. Its From header must belong to the
            authorized identity domain.
        template:
          type: string
          description: >-
            Template UUID, CRN or name; requires email:SendTemplatedMessage on
            that template.
        template_data:
          type: object
          additionalProperties:
            type: string
      description: >-
        Exactly one content mode: text and/or html; raw; or template with
        optional template_data. Text is never guessed to be HTML.
      oneOf:
        - anyOf:
            - required:
                - text
            - required:
                - html
          not:
            anyOf:
              - required:
                  - raw
              - required:
                  - template
        - required:
            - raw
          not:
            anyOf:
              - required:
                  - text
              - required:
                  - html
              - required:
                  - template
        - required:
            - template
          not:
            anyOf:
              - required:
                  - text
              - required:
                  - html
              - required:
                  - raw
    ResourceRef:
      type: object
      required:
        - id
        - crn
      properties:
        id:
          type: string
          format: uuid
          example: 288aa1e9-bbf5-5584-bce9-6a688f06d8a1
        crn:
          type: string
          example: crn:catalog::platform:country/288aa1e9-bbf5-5584-bce9-6a688f06d8a1
        name:
          type: string
          description: >-
            Display label at response time — the resource's name where it has
            one, otherwise its human label (an invoice number, an account
            display name). Absent when the target is gone. Not a lookup key.
          example: Brazil
    error:
      type: object
      required:
        - code
        - message
        - request_id
      properties:
        code:
          type: string
          description: Error code identifying the type of error
          example: INVALID_INPUT
        message:
          type: string
          description: Human-readable error message
          example: Invalid request parameters
        params:
          type: object
          additionalProperties: true
          description: >-
            Optional non-sensitive values for interpolation of localized errors,
            keyed by error code. Never present for server errors.
          example:
            instances: 2
            pools: 0
        request_id:
          type: string
          format: uuid
          description: Request ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An OAuth 2.0 bearer token, sent as `Authorization: Bearer <token>`.
        This is the recommended way to authenticate.

        Get one by exchanging a service account's access key pair at
        `POST /v1/oauth/token` with `grant_type=client_credentials`. It is the
        standard client-credentials grant, so any OAuth-aware library will
        obtain and refresh it for you.

        ```
        curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
          https://iam.basaltic.sh/v1/oauth/token
        ```

        Tokens last an hour by default. The same access key pair is separately
        your AWS SigV4 credential for the S3-compatible object endpoint, which
        speaks nothing else.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.