Skip to content
AgentMail
AgentMail
Core tasks

Receive email

List the messages an inbox received, read full bodies, download attachments, and choose what your agent sees.

If you don’t have an API key yet, follow the Quickstart first.

List all messages in an inbox

You can start receiving emails right after you have created an inbox. Results include sent and received mail alike, newest first.

Each entry is a summary: who sent it, who got it, the subject, its labels, and a preview of the body. That is usually enough for your agent to triage without fetching anything else. When your agent needs a whole conversation, fetch threads instead of stitching messages together. One call returns the full exchange in order.

inbox_id is the only required input. The optional parameters filter and page the results, full list below the code.

agentmail inboxes:messages list \
  --inbox-id "example@agentmail.to"
ParamTypeWhat it means
limitintegerNumber of messages per page.
page_tokenstringWhere to resume. Pass the next_page_token from the previous page.
labelsstring[]Only messages that carry every label you list, for example unread.
before, afterRFC 3339 timestampBound the results by time, like 2026-08-24T00:00:00Z.
ascendingbooleanOldest first instead of newest first.
from, to, subjectstring[]Match against the sender, any recipient (to, cc, or bcc), or the subject. Repeatable, and every value must match.
include_spam, include_blocked, include_unauthenticated, include_trashbooleanAlso return messages those labels normally hide. See Choose which messages you list.

The from, to, and subject filters match whole words and word prefixes, not fragments in the middle of a word: subject=metrics finds “Weekly metrics report”, subject=etrics finds nothing.

count is the number of messages in the current page. When more remain, the response includes a next_page_token. The labels on each entry tell you which direction the message went:

  • received arrived from outside
  • sent went out from this inbox
Sample response
{
  "count": 1,
  "messages": [
    {
      "inbox_id": "example@agentmail.to",
      "thread_id": "7c00cf26-ab80-4e20-a8a6-0285223b385d",
      "message_id": "<010001a034352488-0023daba-a7dd-4ce7-a8b8-b4eec4905809-000000@email.amazonses.com>",
      "labels": ["received", "unread"],
      "timestamp": "2026-08-24T14:38:13Z",
      "from": "You <you@example.com>",
      "to": ["example@agentmail.to"],
      "subject": "Weekly metrics report",
      "preview": "Hi, this week's numbers are attached. Let me know if anything looks off.",
      "attachments": [
        {
          "attachment_id": "079de291-1800-4156-8f6a-3ee90fd701eb",
          "filename": "weekly-metrics.csv",
          "size": 38,
          "content_type": "text/csv",
          "content_disposition": "attachment"
        }
      ],
      "size": 5103,
      "created_at": "2026-08-24T14:38:14Z",
      "updated_at": "2026-08-24T14:38:14Z"
    }
  ]
}

You will use message_id for everything that follows on this page: reading the message in full, downloading its attachments, and replying. attachments[].attachment_id is the other half of the download call, and thread_id groups the message with the rest of its conversation.

Read one message in full

The preview is the first 200 characters of the plain-text body, with no formatting.

To act on a message, get it by its inbox_id and message_id; the response is the full summary plus the complete body.

agentmail inboxes:messages get \
  --inbox-id "example@agentmail.to" \
  --message-id "<message_id>"

A message_id contains <, >, and @, so URL-encode it when you build the API path by hand. The CLI and SDKs encode it for you.

The response carries the body in up to four fields:

  • text is the plain-text body as the sender’s client produced it, quoted history from earlier messages included.
  • html is the rich version of the same content.
  • extracted_text and extracted_html hold only the new content, with the quoted history and signatures stripped out. Each describes one message; no field holds a quote-stripped rendition of a whole thread.

For replies, read extracted_text first so your agent sees what the sender just wrote instead of the whole conversation replayed. Fall back to text, then html. Some clients, Gmail and Outlook forwards in particular, send HTML with no plain-text part, and then text and preview are absent. When the reply’s markup, links, or formatting are the input to your workflow, prefer extracted_html first instead, with a fallback that matches how your application handles HTML.

Sample response
{
  "inbox_id": "example@agentmail.to",
  "thread_id": "7c00cf26-ab80-4e20-a8a6-0285223b385d",
  "message_id": "<010001a0343cff6a-cb637a47-c313-4245-82ac-2638d40395dc-000000@email.amazonses.com>",
  "labels": ["received", "unread"],
  "timestamp": "2026-08-24T14:46:47Z",
  "from": "You <you@example.com>",
  "to": ["example@agentmail.to"],
  "subject": "Re: Weekly metrics report",
  "in_reply_to": "<010001a0343c5b99-1ea2468f-46cd-405b-b01f-a0a98b750af3-000000@email.amazonses.com>",
  "text": "Yes, all five refunds for week 35 are confirmed final.\n\nOn Mon, Aug 24, 2026 at 2:46 PM UTC example@agentmail.to wrote:\n\n> Thanks. Is the week 35 refund count final?",
  "extracted_text": "Yes, all five refunds for week 35 are confirmed final."
}

To answer this message, pass its message_id to the reply call, from the same inbox_id that received it. in_reply_to and references hold the ids of earlier messages in the chain, useful when you need to know which message this one answers.

Download an attachment from a message

The message object carries only attachment metadata. To read a file, get the attachment by id: you need the inbox_id, the message_id, and the attachment_id from the message’s attachments array.

agentmail inboxes:messages get-attachment \
  --inbox-id "example@agentmail.to" \
  --message-id "<message_id>" \
  --attachment-id "<attachment_id>"

# then fetch the file
curl -o weekly-metrics.csv "<download_url from the response>"

The call returns links, not bytes:

  • download_url serves the original file. Fetch it with any HTTP client, no Authorization header needed.
  • When AgentMail can pull text out of the file (PDFs, Word documents, spreadsheets), text_url serves that text as a plain file, ready to hand to a model without any parsing on your side. The extraction runs on AgentExtract, the same AgentMail engine that produces a message’s extracted_text.

Both links stop working at expires_at, one hour after the call. The ids stay valid, so get the attachment again whenever you need fresh links.

Sample response
{
  "attachment_id": "079de291-1800-4156-8f6a-3ee90fd701eb",
  "filename": "weekly-metrics.csv",
  "size": 38,
  "content_type": "text/csv",
  "content_disposition": "attachment",
  "download_url": "https://cdn.agentmail.to/attachments/079de291-1800-4156-8f6a-3ee90fd701eb?Expires=1787586009&Key-Pair-Id=KEP2XXZ8TNG4T&Signature=<signature>",
  "text_url": "https://cdn.agentmail.to/extracted/079de291-1800-4156-8f6a-3ee90fd701eb?Expires=1787586009&Key-Pair-Id=KEP2XXZ8TNG4T&Signature=<signature>",
  "expires_at": "2026-08-24T15:40:09Z"
}

Choose which messages you list

AgentMail labels every message when it arrives, and the listing uses those labels to keep your agent’s view clean. Filter with labels to pick out the mail you care about. The usual pattern is polling for unread:

agentmail inboxes:messages list \
  --inbox-id "example@agentmail.to" \
  --label unread

Each system label tells you how a message arrived:

LabelMeaning for inbound mailListed by default
receivedArrived from outside. Messages the inbox sent carry sent instead.Yes
unreadNot handled yet. Every received message starts with it.Yes
spamFailed spam screening on arrival.Only with include_spam
blockedThe sender is barred by your inbound rules.Only with include_blocked
unauthenticatedCould not be verified as coming from its claimed sender (usually, the sender has no SPF, DKIM, or DMARC set up).Only with include_unauthenticated
trashMoved to trash. You add this label yourself with the update call below.Only with include_trash

What gets rejected before delivery, the ARC fallback that keeps forwarded Gmail and Outlook mail working, and the API-key permissions behind the include flags are all covered in how inbound mail is classified.

Once your agent has handled a message, mark it so the next unread poll skips it:

agentmail inboxes:messages update \
  --inbox-id "example@agentmail.to" \
  --message-id "<message_id>" \
  --remove-labels unread

The update returns the message’s new label state:

Sample response
{
  "message_id": "<010001a034352488-0023daba-a7dd-4ce7-a8b8-b4eec4905809-000000@email.amazonses.com>",
  "labels": ["received"]
}

Remove unread only after the work is done. If your agent crashes mid-task, the message stays in the next poll instead of getting lost.

Next Steps

Was this page helpful?Suggest editsRaise issue