Skip to content
My Beast
Developer docsMenu

Mail · API reference

Emails

Send an email, then look it up to see what happened to it. Emails and their events are kept for your plan's log retention (see Plans and limits).

Endpoints

https://services.my-beast.com/mail/api/email/v1

The email object

An email you sent, with a status for every recipient.

Fields

  • idstring

    Unique ID, starting with em_.

  • fromstring

    The sender, as you sent it.

  • toarray of strings

    Recipients, as you sent them. Always an array.

  • ccarray of strings

    Copy recipients. Empty if there were none.

  • bccarray of strings

    Blind copy recipients. Empty if there were none.

  • reply_toarray of strings

    Reply-to addresses. Empty if there were none.

  • subjectstring

    The subject line.

  • statusstring

    queued, sent, delivered, bounced, complained or failed. A summary of the recipients' statuses: see Email statuses.

  • recipientsarray of objects

    Every address the email went to (to, cc and bcc), each once.

    • emailstring

      The address, without a display name.

    • statusstring

      This recipient's status.

  • tagsarray of objects

    The tags you sent. Empty if there were none.

    • namestring

      The tag's name.

    • valuestring

      The tag's value.

  • created_atstring

    When we accepted the email (ISO 8601, UTC).

  • eventsarray of objects

    What happened, oldest first. Only returned by Retrieve an email.

    • typestring

      sent, delivered, bounced, complained or failed. Each type happens at most once per recipient.

    • recipientstring

      The address this event is about.

    • reasonstring or null

      On failed events: suppressed or expired. Otherwise null.

    • messagestring or null

      On bounced and failed events: a short explanation, often the receiving server's reply. Meant for people, so don't parse it. Otherwise null.

    • created_atstring

      When it happened (ISO 8601, UTC).

Example
{
  "id": "em_01JA2Q8ZK4T9W6",
  "from": "Acme <hello@acme.com>",
  "to": ["customer@example.com"],
  "cc": [],
  "bcc": [],
  "reply_to": ["support@acme.com"],
  "subject": "Your order has shipped",
  "status": "delivered",
  "recipients": [{ "email": "customer@example.com", "status": "delivered" }],
  "tags": [{ "name": "category", "value": "shipping" }],
  "created_at": "2026-10-09T09:14:03Z",
  "events": [
    {
      "type": "sent",
      "recipient": "customer@example.com",
      "reason": null,
      "message": null,
      "created_at": "2026-10-09T09:14:04Z"
    },
    {
      "type": "delivered",
      "recipient": "customer@example.com",
      "reason": null,
      "message": null,
      "created_at": "2026-10-09T09:14:06Z"
    }
  ]
}

Email statuses

Every recipient of an email has one of these statuses:

StatusMeaning
queuedWe've accepted the email and it's waiting to be sent.
sentWe're delivering it to the recipient's mail server. If that server asks us to try later, we keep trying for up to 24 hours.
deliveredThe recipient's mail server accepted it. We can't see whether it was filed in the inbox or as spam. It can still change to bounced or complained.
bouncedThe recipient's mail server refused it permanently, or the address or its domain doesn't exist. The address is added to your suppression list.
complainedThe recipient marked it as spam. Only some mailbox providers report this. The address is added to your suppression list.
failedWe didn't deliver it: the address was on your suppression list (reason suppressed), or the recipient's server kept asking us to try later for 24 hours (reason expired).

With one recipient, the email's status is that recipient's status.

With several, it summarises them. While any recipient has no result yet, it's sent if at least one of those is sent, otherwise queued.

Once every recipient has a result, it's delivered if all were delivered. If not, it's the first of complained, bounced and failed that any recipient has.

A failed event has a reason:

ReasonMeaning
suppressedThe address is on your suppression list, so we didn't send to it.
expiredThe recipient's mail server kept asking us to try later, and 24 hours passed.

Send an email

POST/emails

Accepts an email for sending and returns its ID straight away. Follow what happens next with Retrieve an email or webhooks.

  • to, cc and bcc together can hold up to 50 different addresses. An address listed more than once gets the email once.
  • The whole email, counting html, text and the decoded attachments, can be up to 10 MB.
  • Each recipient counts as one email of your plan's monthly allowance. If the recipients don't all fit in what's left this month, nothing is sent.
  • Recipients on your suppression list are skipped and don't count towards the allowance. They get a failed event with reason suppressed.
  • With a test key the request is checked exactly the same way, and the email is then kept in the test inbox instead of being sent: no verified domain is needed, nothing leaves, nothing counts towards the allowance, and no webhook is sent.

Headers

  • Idempotency-Keystringoptional

    Up to 255 characters, such as a UUID. Retrying with the same key within 24 hours returns the first response instead of sending again. See Idempotency.

Body

  • fromstringrequired

    The sender: an address, or a name and address like Acme <hello@acme.com>. Any address at one of your verified sending domains.

  • tostring or array of stringsrequired

    One or more recipients. Each is an address, or a name and address.

  • ccstring or array of stringsoptional

    Copy recipients.

  • bccstring or array of stringsoptional

    Blind copy recipients. Other recipients don't see them.

  • reply_tostring or array of stringsoptional

    Where replies go, up to 5 addresses.

  • subjectstringrequired

    The subject line, up to 500 characters.

  • htmlstringoptional

    The HTML body. Send html, text or both.

  • textstringoptional

    The plain-text body. We send exactly what you provide and don't make one body from the other.

  • headersobjectoptional

    Extra headers, as name and value strings, such as List-Unsubscribe. Up to 50. Names use letters, digits and hyphens; values can't contain line breaks. You can't set From, Sender, To, Cc, Bcc, Reply-To, Subject, Date, Message-ID, Return-Path, MIME-Version, Content-Type, Content-Transfer-Encoding, DKIM-Signature.

  • tagsarray of objectsoptional

    Up to 10 labels of your own. They come back on the email and in webhook events. Names and values use letters, digits, _ and -, up to 256 characters each. Names must be different from each other.

    • namestringrequired

      The tag's name.

    • valuestringrequired

      The tag's value.

  • attachmentsarray of objectsoptional

    Files to attach.

    • filenamestringrequired

      The name the recipient sees, up to 255 characters.

    • contentstringrequired

      The file's content, base64-encoded.

    • content_typestringoptional

      The MIME type, such as application/pdf. Default application/octet-stream.

Response

200 OK. The email's id, and its status, which is always queued here.

Errors

  • 403domain_not_verifiedThe from domain isn't verified on your plan.
  • 409idempotency_conflictThe Idempotency-Key was used with a different body, or is still in use.
  • 422validation_errorA field is missing or invalid, or a limit above is exceeded.
  • 429monthly_limit_reachedThe recipients don't fit in this month's remaining allowance.

Any endpoint can also return the common errors.

Request

curl -X POST https://services.my-beast.com/mail/api/email/v1/emails \
  -H "Authorization: Bearer $MYBEAST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4f1c2b7e-9d3a-4e8b-a6f0-2c5d8e1b7a93" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "to": ["customer@example.com"],
    "reply_to": "support@acme.com",
    "subject": "Your order has shipped",
    "html": "<p>Your order is on its way.</p>",
    "text": "Your order is on its way.",
    "tags": [{ "name": "category", "value": "shipping" }],
    "attachments": [
      {
        "filename": "receipt.txt",
        "content": "VGhhbmsgeW91IGZvciB5b3VyIG9yZGVyLg==",
        "content_type": "text/plain"
      }
    ]
  }'

Response

200 OK
{
  "id": "em_01JA2Q8ZK4T9W6",
  "status": "queued"
}

Retrieve an email

GET/emails/{id}

Returns an email with its recipients and events. The bodies, headers and attachments aren't returned. With a test key, an email in its test inbox.

Path parameters

  • idstringrequired

    The email's ID.

Response

200 OK. The email object, with events.

Errors

  • 404not_foundNo email has this ID, or it's older than your plan's log retention.

Any endpoint can also return the common errors.

Request

curl https://services.my-beast.com/mail/api/email/v1/emails/em_01JA2Q8ZK4T9W6 \
  -H "Authorization: Bearer $MYBEAST_API_KEY"

Response

200 OK
{
  "id": "em_01JA2Q8ZK4T9W6",
  "from": "Acme <hello@acme.com>",
  "to": ["customer@example.com"],
  "cc": [],
  "bcc": [],
  "reply_to": ["support@acme.com"],
  "subject": "Your order has shipped",
  "status": "delivered",
  "recipients": [{ "email": "customer@example.com", "status": "delivered" }],
  "tags": [{ "name": "category", "value": "shipping" }],
  "created_at": "2026-10-09T09:14:03Z",
  "events": [
    {
      "type": "sent",
      "recipient": "customer@example.com",
      "reason": null,
      "message": null,
      "created_at": "2026-10-09T09:14:04Z"
    },
    {
      "type": "delivered",
      "recipient": "customer@example.com",
      "reason": null,
      "message": null,
      "created_at": "2026-10-09T09:14:06Z"
    }
  ]
}

List emails

GET/emails

Returns your emails, newest first, as far back as your plan's log retention. With a test key, the emails in its test inbox.

Query parameters

  • limitintegeroptional

    How many to return, from 1 to 100. Default 20.

  • afterstringoptional

    The ID of the last email on the previous page. Leave it out for the first page. See Pagination.

Response

200 OK. A page of email objects, without events.

Errors

  • 422validation_errorlimit is out of range, or after isn't an email in this list.

Any endpoint can also return the common errors.

Request

curl "https://services.my-beast.com/mail/api/email/v1/emails?limit=20" \
  -H "Authorization: Bearer $MYBEAST_API_KEY"

Response

200 OK
{
  "data": [
    {
      "id": "em_01JA2Q8ZK4T9W6",
      "from": "Acme <hello@acme.com>",
      "to": ["customer@example.com"],
      "cc": [],
      "bcc": [],
      "reply_to": ["support@acme.com"],
      "subject": "Your order has shipped",
      "status": "delivered",
      "recipients": [{ "email": "customer@example.com", "status": "delivered" }],
      "tags": [{ "name": "category", "value": "shipping" }],
      "created_at": "2026-10-09T09:14:03Z"
    }
  ],
  "has_more": true
}