---
title: "Inbound"
description: "Store a raw RFC 5322 message in your inboxes as if it had been received. Requires the inbound_raw permission; authentication results in the message are ignored."
canonical: "https://machinemail.dev/docs/reference/api/inbound"
---

# Inbound

> Store a raw RFC 5322 message in your inboxes as if it had been received. Requires the inbound_raw permission; authentication results in the message are ignored.

Source: https://machinemail.dev/docs/reference/api/inbound

| Method | Path           | Summary                                   |
| ------ | -------------- | ----------------------------------------- |
| `POST` | `/inbound/raw` | [Inject Raw Message](#inject-raw-message) |

## Inject Raw Message

```http
POST /inbound/raw
```

Stores a raw RFC 5322 message (the request body, any Content-Type, at most 40 MB) as if it had been received, once per recipient inbox in the credential’s scope. The recipient is `X-Recipient`, otherwise every To and Cc address.

Injected messages are marked `received_via: "raw"`. Their trust report never believes the authentication results they carry (headers and provider verdicts are ignored): authentication is `none`, so the trust level is at most `unknown`.

An unrestricted key (`*`) does not imply `inbound_raw`; it must be granted by name.

Injected mail counts toward plan limits like any other inbound mail, even when the trust layer marks it spam or quarantined (its content is yours). On the Free plan, a copy past the monthly or daily allowance (or past storage) is held: it is listed in `held`, not in `messages`, and delivered when the allowance resets or after an upgrade.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie.

#### Headers

| Field | Type | | Description |
| --- | --- | --- | --- |
| `X-Recipient` | `string` |  | Recipient address. Defaults to the To and Cc addresses of the message. |

#### Request body

Content type: `message/rfc822`. Required.

Type: `string (binary)`

#### Response

**201** Stored (or held) (`application/json`)

| Field | Type | | Description |
| --- | --- | --- | --- |
| `count` | `integer` | required | Number of messages stored (one per recipient inbox that accepted it). |
| `messages` | `Message[]` | required | The stored messages, marked received_via: "raw". |
| `errors` | `object[]` |  | Recipients that could not be delivered to, when there were several and at least one succeeded. |
| `held` | `object[]` |  | Recipients whose copy was held (not delivered yet) because the organization reached a Free plan limit: monthly, daily or storage, or queued behind mail already held. Held mail is delivered when the allowance resets or after an upgrade. |

Each item of `messages` is a [Message](/content/docs/reference/api/objects#message/index.html):

| Field | Type | | Description |
| --- | --- | --- | --- |
| `inbox_id` | `string` | required | ID of the inbox. |
| `thread_id` | `string` | required | ID of the thread. |
| `message_id` | `string` | required | ID of the message. |
| `labels` | `string[]` | required | Labels of the message. |
| `timestamp` | `string (date-time)` | required | Time at which the message was sent or received. |
| `from` | `string` | required | Address of the sender. In format username@domain.com or Display Name <username@domain.com>. |
| `to` | `string[]` | required | Addresses of the recipients. In format username@domain.com or Display Name <username@domain.com>. |
| `cc` | `string[]` |  | Addresses of the CC recipients. In format username@domain.com or Display Name <username@domain.com>. |
| `bcc` | `string[]` |  | Addresses of the BCC recipients. In format username@domain.com or Display Name <username@domain.com>. |
| `subject` | `string` |  | Subject of the message. |
| `preview` | `string` |  | Text preview of the message. |
| `attachments` | `Attachment[]` |  | Attachments of the message. |
| `in_reply_to` | `string` |  | ID of the message being replied to. |
| `references` | `string[]` |  | IDs of previous messages in the thread. |
| `headers` | `Record<string, string>` |  | Headers of the message. |
| `authentication_results` | `MessageAuthenticationResults` |  | SPF, DKIM and DMARC verdicts for a received message, each with the domain it is about, as recorded when the message reached MachineMail: by the receiving mail provider (for example Amazon SES), or by the Authentication-Results header of the server that delivered it to MachineMail. A mechanism that was not evaluated is absent. The whole field is absent on sent messages, on messages injected through POST /inbound/raw (their headers are not believed), when nothing was evaluated, and on messages received before the field was introduced. As in AgentMail, only verdicts that speak for the sender are kept. spf is present only when spf_domain is aligned with the sender (shares an organizational domain with the From domain, or with the Sender domain when From spans several domains): an unaligned SPF result is withheld whatever its value. dkim and dmarc are withheld when From spans more than one domain or could not be parsed. Unlike the trust report (trust.authentication), which collapses each result to the values MachineMail scores on and adds aligned, these are the uncollapsed results: permerror and temperror stay as they are. dkim_domain is the signing domain as written: compare it with the From domain before treating a DKIM pass as proof of the sender, and use trust.level (or the UNAUTHENTICATED label) to decide whether to act on the message. Do not reject mail on dmarc: fail alone: forwarding breaks it. |
| `size` | `integer` | required | Size of the message in bytes. |
| `updated_at` | `string (date-time)` | required | Time at which the message was last updated. |
| `created_at` | `string (date-time)` | required | Time at which the message was created. |
| `pod_id` | `string` | required | ID of the pod. |
| `direction` | "inbound" \| "outbound" | required | Whether the message was received or sent. |
| `delivery_status` | "sent" \| "delivered" \| "bounced" \| "complained" |  | Outbound only: last delivery state reported by the transport. |
| `trust_level` | "verified" \| "known" \| "unknown" \| "suspicious" \| "quarantined" |  | Inbound only: trust.level, for list badges. |
| `reply_to` | `string[]` |  | Reply-to addresses. In format username@domain.com or Display Name <username@domain.com>. |
| `text` | `string` |  | Plain text body. Untrusted: agents should read trust.content.text or extracted_text. |
| `html` | `string` |  | HTML body. Untrusted. |
| `extracted_text` | `string` |  | New text content, without quoted replies. |
| `extracted_html` | `string` |  | New HTML content, without quoted replies. |
| `received_via` | "raw" |  | raw when the message was injected with POST /inbound/raw (authentication not verified). |
| `held_at` | `string (date-time)` |  | When the message arrived, for inbound mail that was held because the organization reached a Free plan limit. created_at is then when it was delivered (released). |
| `trust` | `TrustReport` |  | Trust report of an inbound message. |

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `402`  | Free plan: this organization already holds as much undelivered mail as it may (limit_key: "held_messages", or "held_bytes" when the size cap binds: then limit and used are bytes); the message was not stored.                     |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](/content/docs/reference/errors/index.html).

#### Example

```bash title="Request"
curl -X POST "https://api.machinemail.dev/inbound/raw" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: message/rfc822" \
  --data-binary @body
```

```json title="Response 201"
{
  "count": 1,
  "messages": [
    {
      "inbox_id": "agent@machinemail.dev",
      "thread_id": "thd_01k6x3a1fz0000c9k5ns1x4e6g",
      "message_id": "msg_01k6x3a1g00000d0m6pt2y5f7h",
      "labels": ["UNREAD"],
      "timestamp": "2026-10-01T12:00:00.000Z",
      "from": "Support Agent <agent@machinemail.dev>",
      "to": ["customer@example.com"],
      "cc": ["team@example.com"],
      "bcc": ["audit@example.com"],
      "subject": "Order #1042",
      "preview": "Thanks for the quick reply.",
      "attachments": [
        {
          "attachment_id": "att_01k6x3h7qv0000m7v3xb9f2p4r",
          "filename": "invoice.pdf",
          "size": 2048,
          "content_type": "application/pdf",
          "content_disposition": "string",
          "content_id": "string"
        }
      ],
      "in_reply_to": "msg_01k6x3a1g00000d0m6pt2y5f7h",
      "references": ["string"],
      "headers": {
        "key": "value"
      },
      "authentication_results": {
        "spf": "pass",
        "dkim": "pass",
        "dmarc": "pass",
        "spf_domain": "string",
        "dkim_domain": "string",
        "dmarc_domain": "string",
        "arc_sealer": "string"
      },
      "size": 2048,
      "updated_at": "2026-10-01T12:00:00.000Z",
      "created_at": "2026-10-01T12:00:00.000Z",
      "pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
      "direction": "inbound",
      "delivery_status": "sent",
      "trust_level": "verified",
      "reply_to": ["agent@machinemail.dev"],
      "text": "Thanks for the quick reply.",
      "html": "<p>Thanks for the quick reply.</p>",
      "extracted_text": "Thanks for the quick reply.",
      "extracted_html": "<p>Thanks for the quick reply.</p>",
      "received_via": "raw",
      "held_at": "2026-10-01T12:00:00.000Z",
      "trust": {
        "level": "verified",
        "score": 0.8,
        "basis": "trusted_domain",
        "authentication": {
          "spf": "pass",
          "dkim": "pass",
          "dmarc": "pass",
          "aligned": false
        },
        "sender": {
          "address": "agent@machinemail.dev",
          "domain": "example.com",
          "prior_correspondence": false,
          "on_allow_list": false,
          "on_block_list": false,
          "free_mail_provider": false,
          "trusted_domain": {
            "id": "string",
            "domain": "example.com",
            "scope": "org"
          },
          "trusted_domain_shadowed_by": "block"
        },
        "content": {
          "text": "Thanks for the quick reply.",
          "html": "<p>Thanks for the quick reply.</p>",
          "segments": [{}],
          "hidden_text_found": false,
          "zero_width_found": false,
          "tracking_pixels": 1,
          "agent_instructions_detected": false,
          "warnings": ["string"]
        },
        "links": [
          {
            "href": "string",
            "text": "Thanks for the quick reply.",
            "final_url": "https://example.com",
            "domain": "example.com",
            "display_mismatch": false,
            "shortener": false,
            "suspicious": false,
            "reasons": []
          }
        ],
        "attachments": [
          {
            "attachment_id": "att_01k6x3h7qv0000m7v3xb9f2p4r",
            "filename": "invoice.pdf",
            "content_type": "application/pdf",
            "risk": "low",
            "reasons": [],
            "extracted_text": "Thanks for the quick reply."
          }
        ],
        "classification": {
          "is_spam": 0.8,
          "is_phishing": 0.8,
          "contains_instructions_to_agent": 0.8,
          "requests_credentials_or_payment": 0.8,
          "urgency": 0.8,
          "category": "transactional",
          "language": "string",
          "backend": "string",
          "input_hash": "string",
          "cached": false
        },
        "provider_verdicts": {
          "spam": "pass",
          "virus": "pass",
          "source": "string"
        },
        "reasons": ["string"],
        "computed_at": "2026-10-01T12:00:00.000Z"
      }
    }
  ],
  "errors": [
    {
      "recipient": "string",
      "message": "string"
    }
  ],
  "held": [
    {
      "recipient": "string",
      "reason": "monthly"
    }
  ]
}
```
