Hoppa till innehållet

Send up to 100 messages

POST/v1/email/batch

TypeScript sendora.email.sendBatch(messages)

Python sendora.email.send_batch(messages)

Key sk_… a server key

Accepts an array of messages and answers one result per message, in order: accepted with its id, or refused with the same error the single send would give. The Idempotency-Key is required. A retry under the same key sends nothing twice: every item accepted before is answered again with replayed set, and only the items that failed are attempted again.

Parameters

  • idempotency-keyin headerstringrequired

    Any text of 1 to 255 printable characters that identifies this batch; the same key with a different item is refused for that item.

Request body

  • fromone of 2required

    The sender. Its domain must be a verified sending domain of the server.

    1. string (email)
      • emailstring (email)required
      • namestring (at least 1, at most 200 characters) or null

        A display name of up to 200 characters.

  • streamIdstring (uuid)

    The stream of this server the message goes on; the default transactional stream when absent.

  • toarray of one of 2, at least 1required

    Recipients; at most 50 across to, cc and bcc.

    1. string (email)
      • emailstring (email)required
      • namestring (at least 1, at most 200 characters) or null

        A display name of up to 200 characters.

  • ccarray of one of 2

    Copied recipients, shown in the message.

    1. string (email)
      • emailstring (email)required
      • namestring (at least 1, at most 200 characters) or null

        A display name of up to 200 characters.

  • bccarray of one of 2

    Blind-copied recipients.

    1. string (email)
      • emailstring (email)required
      • namestring (at least 1, at most 200 characters) or null

        A display name of up to 200 characters.

  • subjectstring (at least 1, at most 998 characters)required

    The subject line.

  • textstring (at least 1 character)

    The plain-text part. At least one of text and html is required.

  • htmlstring (at least 1 character)

    The HTML part.

  • headersmap of string to stringdefault {}

    Custom headers by name, at most 20. Sendora writes these itself, so a message may not set them: From, Sender, To, Cc, Bcc, Subject, Date, Message-ID, MIME-Version, Return-Path, Received, Delivered-To, DKIM-Signature, DomainKey-Signature, Authentication-Results, Received-SPF, and any name that starts with Content-, Resent-, ARC- or X-Kumo.

  • attachmentsarray of object, at most 20

    At most 20. A message with its attachments encoded may be at most 10 MB.

    • namestringrequired
    • contentstring (base64)required
    • contentTypestring
    • contentIdstring or null
  • tagstring or null

    A label of up to 100 characters, returned with the message and its events.

  • metadatamap of string to stringdefault {}

    Up to 20 key-value pairs of your own, returned with the message and its events.

[
  {
    "from": {
      "email": "no-reply@example.se",
      "name": "Example AB"
    },
    "to": [
      "anna@example.com"
    ],
    "subject": "Your invoice for September",
    "text": "Hi Anna, your invoice is attached.",
    "attachments": [
      {
        "name": "invoice.pdf",
        "content": "JVBERi0xLjcK",
        "contentType": "application/pdf"
      }
    ],
    "tag": "invoice",
    "metadata": {
      "invoiceId": "2026-0912"
    }
  }
]

Responses

200Every message answered on its own; the batch as a whole never fails halfway.

  • resultsarray of one of 18required

    One result per message, in request order.

    1. The message was accepted for delivery.

      • messageIdstring (uuid)required

        The id the message log, the events and the webhooks refer to.

      • status"accepted"required
      • submittedAtstring (date-time)required

        When the message was accepted.

      • testbooleanrequired

        True when the server is a test server: the message goes through everything but delivery, and nobody receives it.

      • indexintegerrequired

        The position of the message in the request.

      • replayedbooleanrequired

        True when an earlier request under the same key already sent this item.

    A refusal carries message, index, status and error, one of these codes, with the fields the code adds:

    CodeMeaningAdds
    invalid_requestThe message does not match what a send takes.issues (path, message)
    from_domain_not_verifiedThe From domain is not a verified sending domain of this server.
    stream_not_foundThe streamId names no stream of this server.
    stream_archivedThe stream is archived and takes no new messages.
    stream_pausedSendora has paused the stream after complaints; it takes no messages until support has resumed it.
    stream_not_sendableAn inbound stream receives mail; it takes no messages and has no suppression list. Name a transactional or broadcast stream.
    unsubscribe_placeholder_missingA message on a broadcast stream must carry {{ unsubscribe_url }} in every part it has.
    list_unsubscribe_reservedOn a broadcast stream Sendora writes the List-Unsubscribe pair itself, so a message may not carry one.
    recipient_suppressedOne or more recipients are on the suppression list of the stream.streamId, suppressed (address, reason)
    test_address_on_live_serverAddresses at simulator.sendora.se act out an outcome on a test server; a live server never sends to them.addresses
    idempotency_key_mismatchThe Idempotency-Key was already used for a different request.
    rate_limitedMore was sent within a minute than the limit allows.scope, limit, retryAfter
    monthly_cap_reachedThe monthly cap of the account, the server or the test servers is used up.scope, cap, used, resetsAt
    sending_disabledSending is disabled for everyone for the moment; retry after the seconds in Retry-After.
    account_pausedThe account is paused by Sendora.
    account_not_activeThe account is closed, or not yet approved for a live server's sends or an inbound stream.
    payment_requiredThe account has no active subscription.

Example

{
  "results": [
    {
      "index": 0,
      "messageId": "5f432ffd-c005-499b-aa3a-5b8a088ea20e",
      "status": "accepted",
      "submittedAt": "2026-09-15T12:00:00.000Z",
      "test": false,
      "replayed": false
    }
  ]
}

Errors

Every error answers error, the code, and message, a sentence for a person. A code that adds fields is shown in full below the table.

CodeStatusMeaning
invalid_request400The body, the query or a header does not match what the route takes.
idempotency_key_required400Batch sends need an Idempotency-Key header.
unauthorized401The key is missing, malformed or revoked.
payment_required402The account has no active subscription.
wrong_token_kind403The key is of the other kind: a server key (sk_) where an account key (ak_) is needed, or the reverse. The message names the kind the operation takes.
account_paused403The account is paused by Sendora.
account_not_active403The account is closed, or not yet approved for a live server's sends or an inbound stream.
request_too_large413The body exceeds 10 MB.
sending_disabled503Sending is disabled for everyone for the moment; retry after the seconds in Retry-After.
  • Retry-Afterheader on 503integer

    Seconds to wait before trying again.

invalid_request

  • issuesarray of object

    One entry per invalid field; absent when a header is wrong.

    • pathstringrequired

      The field, dotted, such as to.0.email; empty when the whole body is wrong.

    • messagestringrequired

Example

{
  "error": "invalid_request",
  "message": "The request is invalid: to.0: Invalid email address",
  "issues": [
    {
      "path": "to.0",
      "message": "Invalid email address"
    }
  ]
}