Mailactor
Messages

Send messages

Send email from your inbox and track the result.

Use the inbox send endpoint for agents and applications that need conversations. Mailactor supplies the sender identity and email threading headers.

Required scopes: mailbox:send to submit the message and delivery:read to track delivery.

Set MAILACTOR_API_URL and MAILACTOR_API_KEY as shown in quickstart. Examples below use illustrative IDs and values; use the values returned for your organization.

Send a new message

export SEND_KEY="send-$(uuidgen)"

curl --fail-with-body --silent --show-error \
  "$MAILACTOR_API_URL/v1/inboxes/$INBOX_ID/messages" \
  -H "x-api-key: $MAILACTOR_API_KEY" \
  -H "idempotency-key: $SEND_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":[{"email":"you@example.com"}],"subject":"Your research update","text":"The research is ready for your review."}'

Replace you@example.com with your intended recipient. Persist the key and request body together so a timeout can be retried safely.

Request: sendInboxMessage
{
  "to": [
    {
      "email": "you@example.com",
      "name": "Alex"
    }
  ],
  "subject": "Your research update",
  "text": "The research is ready for your review.",
  "html": "<p>The research is ready for your review.</p>",
  "replyTo": {
    "email": "research-agent@inbox.mailactor.com",
    "name": "Research Agent"
  },
  "metadata": {
    "taskId": "research-42"
  }
}
FieldRequiredShape
toYesArray of {email, name?} objects. At least one; use /v1/meplatformLimits.recipientsPerMessage for your live cap (schema maximum 1,000).
subjectYesString, 1–998 characters, not whitespace-only.
textOne of text / htmlPlain-text string.
htmlOne of text / htmlHTML string. Both body formats are allowed.
replyToNoOne {email, name?} object; directs normal email replies. Omit to receive replies at the inbox's sender address.
metadataNoUp to 20 string values, keys 1–100 characters, values at most 500 characters.

Every mailbox needs a valid email; optional name is 1–200 characters. Unknown fields are rejected. There are no outbound attachment, CC, or BCC fields. The sender is your inbox's returned address; you do not supply from. Treat outgoing HTML as application-authored content, and respect the live messageContentBytes limit.

Save the response identifiers

FieldUse
message.idIdentify the email in your mailbox.
message.threadIdRead this conversation and receive replies.
submission.idTrack outbound delivery.

A 202 response means accepted for asynchronous delivery. Poll the submission endpoint for the outcome. A mailbox message's delivery.status: "submitted" does not mean the recipient's server accepted it.

HTTP 202 example

The example above can return this complete envelope. replayed: false means a new operation; true means the same operation was recovered by its idempotency key. Status may already have advanced when you read a replay.

Response: sendInboxMessage 202
{
  "message": {
    "id": "msg_1123456789abcdef01234567",
    "inboxId": "inb_0123456789abcdef01234567",
    "threadId": "thr_0123456789abcdef01234567",
    "direction": "outbound",
    "internetMessageId": "<research-42@inbox.mailactor.com>",
    "inReplyTo": null,
    "references": [],
    "from": {
      "email": "research-agent@inbox.mailactor.com",
      "name": "Research Agent"
    },
    "to": [
      {
        "email": "you@example.com",
        "name": "Alex"
      }
    ],
    "subject": "Your research update",
    "text": "The research is ready for your review.",
    "html": "<p>The research is ready for your review.</p>",
    "replyTo": {
      "email": "research-agent@inbox.mailactor.com",
      "name": "Research Agent"
    },
    "metadata": {
      "taskId": "research-42"
    },
    "delivery": {
      "submissionId": "00000000-0000-4000-8000-000000000001",
      "status": "submitted",
      "failureCode": null
    },
    "createdAt": "2026-09-08T12:00:00.000Z",
    "updatedAt": "2026-09-08T12:00:00.000Z"
  },
  "submission": {
    "id": "00000000-0000-4000-8000-000000000001",
    "from": {
      "email": "research-agent@inbox.mailactor.com",
      "name": "Research Agent"
    },
    "recipients": [
      {
        "email": "you@example.com",
        "status": "pending",
        "response": null,
        "updatedAt": "2026-09-08T12:00:00.000Z"
      }
    ],
    "subject": "Your research update",
    "metadata": {
      "taskId": "research-42"
    },
    "status": "pending",
    "queueId": null,
    "response": null,
    "failureCode": null,
    "createdAt": "2026-09-08T12:00:00.000Z",
    "updatedAt": "2026-09-08T12:00:00.000Z"
  },
  "replayed": false
}

Retry safely

For an interrupted or retryable request, use the same idempotency key and semantic body. Do not create a new key merely because the first response was lost. A new key represents a new message and can send a duplicate.

If the retry deadline expires, retain the key and body and report acceptance as unknown. There is no lookup endpoint by idempotency key; matching a message by subject or content is not proof that it belongs to this operation.

Idempotency and safe retries

Choose the correct sending route

POST /v1/inboxes/{inboxId}/messages stores a mailbox message and creates the thread needed for normal inbox workflows.

POST /v1/send is a lower-level delivery endpoint for integrations supplying their own authorized From mailbox. It requires delivery:send and a verified sending domain. It does not create the inbox conversation for you. Never switch routes when retrying one logical send.

Full inbox send reference

On this page