Skip to content
Skip to main content

How Agent Account mailboxes work

Every Agent Account has a real mailbox with a real address — something like [email protected] or [email protected]. It sends outbound mail, receives inbound mail, maintains folders, and has its own deliverability reputation. To anyone interacting with it over SMTP, it’s indistinguishable from a human-operated mailbox.

This page walks through what actually happens when an Agent Account sends a message, what happens when mail arrives, and how the mailbox surface maps onto Nylas’s existing Email API. If you’re looking for the complete endpoint list, see Supported endpoints.

When you provision an Agent Account, Nylas creates a hosted mailbox on one of your registered domains and returns a grant_id. That grant ID is the only identifier you need — the existing Messages, Threads, Folders, Drafts, and Attachments endpoints all work against /v3/grants/{grant_id}/... the same way they do for any other grant.

Every mailbox comes with:

  • A primary email address on a domain you’ve verified, or on a Nylas-provided *.nylas.email trial domain.
  • Six system folders provisioned automatically: inbox, sent, drafts, trash, junk, and archive. You can create custom folders alongside them with POST /folders. System folder names are reserved.
  • A thread index built from standard RFC 5322 headers so replies group into conversations. See Email threading for agents for the full treatment.
  • An optional app_password on the grant for IMAP and SMTP submission, so end users can connect Outlook or Apple Mail alongside the API. See Mail client access.

Inbound and outbound mail use the same Nylas-hosted infrastructure whether you drive the mailbox through the API, through IMAP/SMTP, or through both at once. Anything sent via IMAP/SMTP appears as a message in the API; anything sent via the API appears in the Sent folder in the mail client.

An inbound message goes through this lifecycle:

  1. The remote sender delivers to Nylas over SMTP. The sending server looks up the MX record for the Agent Account’s domain and opens an SMTP connection to Nylas’s inbound infrastructure.
  2. Nylas runs policy checks. If the grant has a policy attached, any rules that match inbound conditions run here — block rejects the message at the SMTP layer, mark_as_spam routes it to junk, assign_to_folder routes it to a named folder, and so on. Rule evaluations are logged for audit.
  3. The message is stored and delivered to a folder. Default destination is inbox; rules or the sender’s address can route it elsewhere.
  4. The webhook fires. Any subscription matching message.created on the grant receives a payload identical in shape to message.created for any other provider. If the body exceeds ~1 MB, the trigger name becomes message.created.truncated and the body is omitted — fetch the full message with GET /messages/{id} in that case.
  5. The thread is indexed. Nylas reads In-Reply-To and References headers to attach the message to an existing thread, or creates a new thread if it’s a conversation starter. The webhook payload’s thread_id is the key your agent uses to reconstruct conversation state.

Inbound attachments count against the limits set by your plan and the grant’s policy — limit_attachment_size_limit, limit_attachment_count_limit, and limit_attachment_allowed_types control what’s accepted. Messages that exceed these caps are rejected at the policy stage before message.created fires.

If you’d rather poll than subscribe to webhooks, GET /messages with received_after works fine for batch workflows. Webhooks are preferred for near-real-time agent loops because delivery typically lands within seconds of the SMTP handoff.

Outbound from the API uses POST /v3/grants/{grant_id}/messages/send. The body is JSON, or multipart for attachments, and takes the same shape as sending from any other grant — to, cc, bcc, subject, body, and optional reply_to_message_id, tracking_options, and custom_headers.

curl --request POST \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/messages/send" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"to": [{ "email": "[email protected]" }],
"subject": "Following up on your demo request",
"body": "Hi Alice, thanks for your interest..."
}'

A few things to know about how sends work:

  • Send happens from the Agent Account’s address. Nylas stamps the From header with the grant’s primary address. Agent Accounts can’t spoof other identities.
  • Threading is automatic on replies. Pass reply_to_message_id and Nylas populates Message-ID, In-Reply-To, and References so the reply threads in every recipient’s mail client. Details in Email threading for agents.
  • Policy rules can block or rewrite outbound. If the grant’s policy has rules with outbound.type or recipient matchers, they run before the message hits SMTP. See Policies, Rules, and Lists.
  • Send quota is tracked per account. The default soft limit is 100 messages per account per day; paid plans go higher. Sends over the limit return an error on the API call.
  • Attachments are capped by standard email sizes. Messages over the recipient server’s size limit (typically ~25 MB) will be rejected by the remote MX.

After Nylas hands the message to the recipient’s server, deliverability signals come back as webhooks:

TriggerWhen it fires
message.send_successThe recipient server accepted the message.
message.send_failedThe send failed before the message reached the recipient — typically a policy block, deliverability gate, or spam complaint from the recipient.
message.bounce_detectedHard or soft bounce returned by the remote server.

Because Nylas owns the SMTP path end-to-end for Agent Accounts, these triggers give you send-side visibility on every outbound message. Sender reputation is shared across every Agent Account on a given domain, so treat outbound hygiene as a domain-level concern. See Domain warming when you’re rolling out a new custom domain at scale.

Drafts are supported with full CRUD at /v3/grants/{grant_id}/drafts. Create one, update it, then POST to /drafts/{draft_id} to send — the send action on an existing draft behaves the same as POST /messages/send. This is useful for human-in-the-loop flows where an agent proposes a reply and a reviewer approves it before delivery.

Replies group into conversations using the standard Message-ID, In-Reply-To, and References headers. Every message.created webhook payload includes a thread_id — fetch the thread to reconstruct what’s been said before your agent decides how to respond:

curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<GRANT_ID>/threads/<THREAD_ID>" \
--header "Authorization: Bearer <NYLAS_API_KEY>"

To send a reply that threads correctly, pass reply_to_message_id on POST /messages/send. Nylas sets the threading headers on the outbound message automatically.

For the full protocol-level explanation and the state-mapping pattern for multi-turn conversations, see Email threading for agents.

  • Fetch the thread before responding. An agent that drafts replies needs the full thread history to avoid repeating itself or contradicting earlier messages. Don’t reply off the single-message payload from the webhook alone.
  • Inbound filtering is cheaper than reacting to noise. Use rules to drop obvious spam, loops, and mailer-daemon replies before message.created fires. It keeps the agent from reacting to auto-replies.
  • Mail clients see the same mailbox as the API. Anything sent via IMAP/SMTP appears in the Messages API; anything sent via the API appears in the Sent folder in the mail client. There’s no separation between protocol traffic and API traffic.
  • Native message tracking isn’t available on API sends. message.opened and message.link_clicked aren’t emitted for messages sent directly through POST /messages/send on an Agent Account. Deliverability is tracked through the send and bounce triggers above.