objects.md


title: "Objects" description: "Every object the MachineMail API accepts or returns, field by field, with types and required fields. Endpoint pages link here for nested objects." canonical: "https://machinemail.dev/docs/reference/api/objects"

Objects

Every object the MachineMail API accepts or returns, field by field, with types and required fields. Endpoint pages link here for nested objects.

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

Endpoint pages link here for nested objects. Fields marked required are always present in responses and must be sent in requests.

AgentIdentityRequest

Field Type Description
type "anonymous" | "service_auth" | "identity_assertion" required Registration type.
name string Agent label (first 100 characters). Untrusted; shown as agent-described in the dashboard.
client_name string Alias of name.
login_hint string service_auth: email address of the user the agent acts for. Required for that type.
assertion_type string identity_assertion: urn:ietf:params:oauth:token-type:id-jag. Required for that type.
assertion string identity_assertion: the ID-JAG (signed JWT). Required for that type.

AgentIdentityResponse

Field Type Description
registration_id string required
agent_id string required Same value as registration_id.
registration_type "anonymous" | "service_auth" | "identity_assertion" required anonymous: no human yet; a sandbox inbox until a human claims it. service_auth: on behalf of a named user, who confirms first. identity_assertion: an ID-JAG from a trusted agent provider.
identity_assertion string Service-signed JWT to exchange at /oauth2/token. Absent for service_auth until the claim completes.
assertion_expires string (date-time)
scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] identity_assertion registrations: the granted scopes.
pre_claim_scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] anonymous registrations: scopes before a human claims the agent (its sandbox inbox only).
post_claim_scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] Scopes after the claim.
claim_url string Where to start the claim ceremony (/agent/identity/claim).
claim_token string Secret for /agent/identity/claim and the claim grant.
claim_token_expires string (date-time)
claim object service_auth registrations: the ceremony is already started.
inbox object anonymous registrations: the ephemeral sandbox inbox. There is no API key; authenticate with the access token from /oauth2/token.

AgentRegistration

An agent registration. Hashes and tokens are never included.

Field Type Description
agent_id string required ID of the registration (reg_...).
registration_id string required Same value as agent_id.
registration_type "anonymous" | "service_auth" | "identity_assertion" required anonymous: no human yet; a sandbox inbox until a human claims it. service_auth: on behalf of a named user, who confirms first. identity_assertion: an ID-JAG from a trusted agent provider.
status "pending_claim" | "claimed" | "revoked" required
name string Agent-described label. Untrusted.
client string Provider name for identity_assertion, otherwise agent (self-described) or anonymous agent.
organization_id string Organization the registration is bound to (after a claim, or right away for identity_assertion).
inbox_id string The sandbox inbox of an anonymous registration.
email string Verified email bound at claim or carried by the identity assertion.
issuer string Issuer of the identity assertion (identity_assertion).
agent_platform string agent_platform claim of the identity assertion.
created_at string (date-time) required When the agent registered.
claimed_at string (date-time) When a human claimed the registration.
revoked_at string (date-time) When the registration was revoked.
expires_at string (date-time) When an unclaimed registration expires.

ApiKeyPermissions

Permissions of the key, as { "<name>": true }. Only names set to true are granted; false is the same as leaving the name out. An omitted (or null) permission object means full access for the key scope, like {"*": true}; neither includes inbound_raw, which must be granted by name. A key can only be given permissions its creator has. Another name set to true (for example AgentMail’s calendar_*, app_* or account_update, which MachineMail does not support) is a 400.

Field Type Description
* boolean Every permission except inbound_raw. {"*": true, "inbound_raw": true} is full access plus raw injection.
inbox_read boolean Read inbox details.
inbox_create boolean Create new inboxes.
inbox_update boolean Update inbox settings.
inbox_delete boolean Delete inboxes.
thread_read boolean Read threads.
thread_delete boolean Delete threads.
message_read boolean Read messages.
message_reply boolean Reply and reply-all. message_send allows them too.
message_send boolean Send messages (and reply, reply-all, forward).
message_update boolean Update message labels. Also required to update threads.
message_delete boolean Delete messages.
label_spam_read boolean Access messages labeled spam.
label_blocked_read boolean Access messages labeled blocked.
label_unauthenticated_read boolean Access messages labeled unauthenticated.
label_trash_read boolean Access messages labeled trash.
draft_read boolean Read drafts.
draft_create boolean Create drafts.
draft_update boolean Update drafts.
draft_delete boolean Delete drafts.
draft_send boolean Send drafts.
webhook_read boolean Read webhook configurations.
webhook_create boolean Create webhooks.
webhook_update boolean Update webhooks.
webhook_delete boolean Delete webhooks.
domain_read boolean Read domain details.
domain_create boolean Create domains.
domain_update boolean Update domains.
domain_delete boolean Delete domains.
list_entry_read boolean Read list entries and suppressions.
list_entry_create boolean Create list entries and suppressions.
list_entry_delete boolean Delete list entries and suppressions.
trusted_domain_read boolean Read trusted domains and preview new ones.
trusted_domain_create boolean Add trusted domains. Organization API keys and the dashboard only: pod and inbox keys get 403 even with it.
trusted_domain_update boolean Change trusted domains. Organization API keys and the dashboard only, as for trusted_domain_create.
trusted_domain_delete boolean Remove trusted domains.
metrics_read boolean Read metrics and events.
api_key_read boolean Read API keys.
api_key_create boolean Create API keys.
api_key_update boolean Update API keys.
api_key_delete boolean Delete API keys.
pod_read boolean Read pods.
pod_create boolean Create pods.
pod_update boolean Update pods.
pod_delete boolean Delete pods.
inbound_raw boolean Inject raw mail with POST /inbound/raw. Never implied by an unrestricted key or *: it must be granted by name.

Attachment

Field Type Description
attachment_id string required ID of the attachment.
filename string Filename of the attachment.
size integer required Size of the attachment in bytes.
content_type string Content type of the attachment.
content_disposition string Content disposition of the attachment (inline or attachment).
content_id string Content ID of the attachment.

AttachmentResponse

Field Type Description
attachment_id string required ID of the attachment.
filename string Filename of the attachment.
size integer required Size of the attachment in bytes.
content_type string Content type of the attachment.
content_disposition string Content disposition of the attachment (inline or attachment).
content_id string Content ID of the attachment.
download_url string required URL of the attachment bytes. Depending on the storage backend: a signed storage URL, the API URL GET .../attachments/{attachment_id}/download (send your API key), or a data: URI.
expires_at string (date-time) required When download_url expires: one hour from the request unless the signed URL sets its own expiry.

AuthConfigResponse

How people sign in to MachineMail.

Field Type Description
workos boolean required Legacy alias of email_code, kept for older clients: sign in with an email code (POST /auth/email/start), a social provider (GET /auth/social/{provider}) or SSO.
email_code boolean required Email-code sign-in (POST /auth/email/start, then POST /auth/email/verify) is available.
providers ("google" | "github" | "apple" | "microsoft")[] required Social providers on offer (GET /auth/social/{provider}). Empty when none are offered.
magic_link boolean required Magic-link sign-in (POST /auth/magic-link) is available.
password boolean required The deprecated password endpoints are available.
authkit boolean required, deprecated Deprecated: always false. Kept for older clients; see email_code.
passkey boolean required Passkey sign-in (POST /auth/passkey/options, then POST /auth/passkey/verify) is offered: show “Sign in with a passkey” and passkey autofill on the email field.

AuthorizationServerMetadata

RFC 8414 Authorization Server Metadata (as the MCP authorization specification asks for it) plus the auth.md agent_auth block.

Field Type Description
resource string required The protected resource: / (the REST API and MCP), or / for a path-suffixed document. On the MCP server’s own host, the MCP server’s URL (https://mcp.machinemail.dev/mcp); on the issuer, /mcp is the legacy MCP alias.
authorization_servers string[] required
scopes_supported ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] required
bearer_methods_supported string[] required header.
issuer string required
authorization_endpoint string required /oauth2/authorize: authorization code grant with PKCE (S256).
token_endpoint string required
registration_endpoint string required /oauth2/register: Dynamic Client Registration (RFC 7591), public or confidential clients.
revocation_endpoint string required
device_authorization_endpoint string required /auth/cli/device/code: the device grant of the MachineMail CLI (client_id machinemail-cli only).
jwks_uri string required
service_documentation string required
grant_types_supported string[] required authorization_code, refresh_token, urn:ietf:params:oauth:grant-type:device_code, urn:ietf:params:oauth:grant-type:jwt-bearer, urn:workos:agent-auth:grant-type:claim.
response_types_supported string[] required code.
response_modes_supported string[] required query.
code_challenge_methods_supported string[] required S256.
token_endpoint_auth_methods_supported string[] required none (public clients: every URL client ID, and registrations without a secret), client_secret_post and client_secret_basic (registrations that asked for a secret). Every client uses PKCE.
revocation_endpoint_auth_methods_supported string[] required Same as token_endpoint_auth_methods_supported.
client_id_metadata_document_supported boolean required true: an https URL is accepted as client_id (OAuth Client ID Metadata Document).
authorization_response_iss_parameter_supported boolean required true: authorization responses carry iss (RFC 9207).
agent_auth object required

BatchGetMessagesRequest

Field Type Description
message_ids string[] required IDs of the messages to fetch. Only the first 100 distinct IDs are read.

BatchGetMessagesResponse

Field Type Description
limit integer required Number of IDs in the request.
count integer required Number of messages returned.
messages Message[] required Found messages, in request order. IDs not found in the inbox are omitted.

BatchUpdateMessagesRequest

Field Type Description
message_ids string[] required IDs of the messages to update. Only the first 100 distinct IDs are updated.
add_labels string | string[] Label or labels to add to every message.
remove_labels string | string[] Label or labels to remove from every message.

BatchUpdateMessagesResponse

Field Type Description
limit integer required Number of IDs in the request.
count integer required Number of messages updated.
updates UpdateMessageResponse[] required Updated messages with their new labels, in request order. IDs not found are omitted.

BearerApiKey

An API key presented as a bearer token in the Authorization header.

Field Type Description
type "bearer" required Always bearer: MachineMail has no public-key credentials.
api_key_id string required ID of the API key.
prefix string required First 12 characters of the key (mm_live_ and 4 more), safe to display.
name string required Name of the key.
pod_id string Pod the key is scoped to: it can only access resources in this pod.
inbox_id string Inbox the key is scoped to: it can only access this inbox.
permissions ApiKeyPermissions Permissions of the key, as { "": true }. Only names set to true are granted; false is the same as leaving the name out. An omitted (or null) permission object means full access for the key scope, like {"": true}; neither includes inbound_raw, which must be granted by name. A key can only be given permissions its creator has. Another name set to true (for example AgentMail’s calendar_, app_* or account_update, which MachineMail does not support) is a 400.
created_at string (date-time) required Time at which the key was created.
expires_at string (date-time) Time at which the key expires: requests with it then get 401. Absent when it does not expire.
organization_id string required ID of the organization.
used_at string (date-time) Time at which the key was last used.
revoked_at string (date-time) When the key was deleted (revoked). Revoked keys are not listed but can still be fetched by ID.
updated_at string (date-time) required Time at which the name, permissions or revocation last changed. Use does not change it.

Bounce

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.
timestamp string (date-time) required When it happened.
type string required Bounce type: Permanent or Transient (or the provider type).
sub_type string required Bounce sub-type, General when the provider gives none.
recipients Recipient[] required Bounced recipients. Permanent bounces are added to the suppression list.

ClaimBlock

RFC 8628-shaped claim ceremony block.

Field Type Description
user_code string required 6-digit code the human enters in the dashboard.
verification_uri string required https://machinemail.dev/claim?claim_attempt_token=cat_...: the page to send the human to.
expires_in integer required Seconds until user_code expires.
interval integer required Minimum seconds between /oauth2/token polls.

ClaimCompleteRequest

Field Type Description
user_code string required The 6-digit code the agent shows; spaces and dashes are ignored.
claim_attempt_token string The cat_... token from verification_uri; when given, it must belong to the same attempt as user_code.

ClaimCompleteResponse

The claimed registration plus the moved inbox.

ClaimPreviewResponse

An agent registration plus the claim details.

ClaimStartRequest

Send claim_token (and optionally email), or agent_id with Bearer proof.

Field Type Description
claim_token string Protocol form: the claim_token from registration.
email string Binds the claim to this human. For service_auth and identity_assertion it must match the bound email.
agent_id string Alternative to claim_token; needs the registration’s access token or identity assertion as Authorization: Bearer.
registration_id string Alias of agent_id.

ClaimStartResponse

The claim_attempt block and the flat user_code, verification_uri, expires_in and interval carry the same values.

Field Type Description
registration_id string required
agent_id string required
claim_attempt_id string required
status "initiated" required
expires_at string (date-time) required When this attempt expires.
claim_attempt ClaimBlock required RFC 8628-shaped claim ceremony block.
user_code string required 6-digit code the human enters in the dashboard.
verification_uri string required https://machinemail.dev/claim?claim_attempt_token=cat_...: the page to send the human to.
expires_in integer required Seconds until user_code expires.
interval integer required Minimum seconds between /oauth2/token polls.

CliDeviceApproveRequest

Field Type Description
user_code string required The code the CLI printed (XXXX-XXXX); case, spaces and dashes are ignored.
organization_id string The organization the key is for, as the page showed it: it must be the one the session is signed in to (409 conflict otherwise, for example after another tab switched organizations). To create the key in another organization the person belongs to, switch the session to it first (POST /auth/organizations/switch). Default: the session’s organization.

CliDeviceAuthorization

A pending CLI sign-in, as the approval page shows it. Never includes the device code.

Field Type Description
user_code string required The code, formatted XXXX-XXXX.
device_id string required Opaque ID of this sign-in (cld_...), not a secret: the device_id of the session.cli.device stream events that report it approved, denied or redeemed.
client_id string required Always machinemail-cli.
client_name string | null required What the CLI says it is. Self-reported.
hostname string | null required The machine the CLI says it runs on. Self-reported.
key_name string required Name of the key approval creates: CLI on .
permissions string[] required Permissions of that key: ["*"] (every permission except inbound_raw).
created_at string (date-time) required When the CLI asked for the code.
expires_at string (date-time) required When the code expires.

CliDeviceCodeRequest

Field Type Description
client_id string required Always machinemail-cli.
client_name string Shown to the human on the approval page, for example MachineMail CLI 0.4.0. At most 100 characters. (max length 100)
hostname string The machine the CLI runs on. Names the key (CLI on ) and is shown on the approval page. At most 253 characters. (max length 253)

CliDeviceCodeResponse

RFC 8628 device authorization response.

Field Type Description
device_code string required Secret the CLI polls the token endpoint with. Never show it.
user_code string required Code the human checks on the approval page: 8 letters as XXXX-XXXX (consonants only, no look-alikes).
verification_uri string required https://machinemail.dev/cli: where the human approves.
verification_uri_complete string required verification_uri with ?code=, for opening in a browser.
expires_in integer required Seconds until both codes expire (600).
interval integer required Minimum seconds between polls of the token endpoint (5).

CliDeviceDecision

Field Type Description
status "approved" | "denied" required
key_name string required Name of the key the CLI receives (approved) or would have received (denied).

CliDeviceDecisionRequest

Field Type Description
user_code string required The code the CLI printed (XXXX-XXXX); case, spaces and dashes are ignored.

CliDeviceTokenRequest

Field Type Description
grant_type string required urn:ietf:params:oauth:grant-type:device_code.
device_code string required The device_code from the device authorization response.
client_id string required Always machinemail-cli.

CliDeviceTokenResponse

An organization API key with every permission except inbound_raw, minted for the approving user.

Field Type Description
access_token string required The new API key (mm_live_...). Returned once; send it as Authorization: Bearer.
token_type "Bearer" required
api_key_id string required ID of the key, for DELETE /v0/api-keys/{api_key_id} on logout.
key_name string required Name of the key: CLI on .
organization Organization required The organization the key belongs to.
user User required The person who approved the sign-in.

ClientRegistrationRequest

RFC 7591 client metadata. Unknown members are ignored.

Field Type Description
redirect_uris string[] required Where the authorization response may be sent: https URLs, http loopback URLs (http://127.0.0.1, http://[::1] or http://localhost; any port is accepted at authorization time, RFC 8252), or a private-use scheme of a native app (cursor://...). No fragments. At most 10. (min items 1, max items 10)
client_name string Shown on the consent page, marked as unverified. At most 200 characters. (max length 200)
client_uri string Home page of the client; shown on the consent page when it is https. (max length 2000)
logo_uri string Logo shown on the consent page when it is https. (max length 2000)
token_endpoint_auth_method string none (the default: a public client, PKCE only), client_secret_post or client_secret_basic (a confidential client: the response carries a client_secret, and the token endpoint accepts it either way). Any other value is replaced with none in the response (RFC 7591 section 3.2.1).
grant_types string[] authorization_code and refresh_token (the default). Must include authorization_code (invalid_client_metadata otherwise); other values are dropped from the registration.
response_types string[] code (the default). Other values: invalid_client_metadata.
scope string Space-separated Scope values the client may ask for. Default: every scope. (max length 2000)
application_type "native" | "web" native or web (OpenID Connect Dynamic Client Registration; required by MCP 2026-07-28). Default web.
software_id string Identifier of the client software. Stored, not verified. (max length 200)
software_version string Version of the client software. Stored, not verified. (max length 100)

ClientRegistrationResponse

RFC 7591 client information response. A public client has no client_secret.

Field Type Description
client_id string required The new client identifier (oac_...).
client_id_issued_at integer required Seconds since the epoch.
client_name string
client_uri string
logo_uri string
redirect_uris string[] required
grant_types string[] required
response_types string[] required
token_endpoint_auth_method "none" | "client_secret_post" | "client_secret_basic" required As requested when supported, otherwise none.
client_secret string Confidential clients only (client_secret_post, client_secret_basic): shown once, stored only as a hash. Keep it secret.
client_secret_expires_at integer With client_secret: 0, the secret does not expire.
application_type "native" | "web" required
scope string
software_id string
software_version string

Complaint

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.
timestamp string (date-time) required When it happened.
type string required Complaint type, complaint when the provider gives none.
sub_type string required Complaint sub-type, abuse when the provider gives none.
recipients Recipient[] required Complaining recipients, as {address, status} objects (AgentMail documents plain strings). They are added to the suppression list.

CreateApiKeyResponse

Field Type Description
api_key_id string required ID of the API key.
prefix string required First 12 characters of the key (mm_live_ and 4 more), safe to display.
name string required Name of the key.
pod_id string Pod the key is scoped to: it can only access resources in this pod.
inbox_id string Inbox the key is scoped to: it can only access this inbox.
permissions ApiKeyPermissions Permissions of the key, as { "": true }. Only names set to true are granted; false is the same as leaving the name out. An omitted (or null) permission object means full access for the key scope, like {"": true}; neither includes inbound_raw, which must be granted by name. A key can only be given permissions its creator has. Another name set to true (for example AgentMail’s calendar_, app_* or account_update, which MachineMail does not support) is a 400.
created_at string (date-time) required Time at which the key was created.
expires_at string (date-time) Time at which the key expires: requests with it then get 401. Absent when it does not expire.
api_key string required The key itself (mm_live_ and 32 characters). Returned once; only a hash is stored.

CreateBearerApiKeyRequest

The route sets the scope: /v0/api-keys makes an organization key, /v0/pods/{pod_id}/api-keys a pod key, /v0/inboxes/{inbox_id}/api-keys an inbox key.

Field Type Description
name string Name of the key. Default API key.
permissions object | null Permissions of the new key. Omitted or null: full access for the key scope (inbound_raw excepted).
expires_at string (date-time) | null When the key stops working, as an RFC 3339 timestamp at least 5 minutes from now (400 otherwise). A date alone or a time without a zone is read as UTC. Omit it or send null for no expiry (a key created with an expiring API key gets that key’s expiry instead). A key created with another API key cannot outlive it: a later time is a 403. An inherited expiry can be under 5 minutes away. It cannot be changed later; create a new key instead.

CreateDomainRequest

Field Type Description
domain string required The domain name, for example example.com. Cannot be the shared domain or a domain another organization registered.
feedback_enabled boolean Stored and returned; has no effect. Default false.
inbound_enabled boolean Receive email for this domain. Default true. false makes it send-only (the inbound MX record is not required).
client_id string Idempotency key: a create with a client_id already used in the organization returns that domain with 200, or 409 when that domain is outside the pod of the API key or route.
pod_id string Pod to create the domain in. Defaults to the credential pod or the organization default pod. A pod-scoped credential can only name its own pod.
catch_all boolean Create an inbox for any address at the domain that receives mail. Default false.
catch_all_ttl_seconds integer | null Make inboxes created by catch-all ephemeral with this TTL. null or absent: permanent.

CreateDraftRequest

Field Type Description
labels string[] Labels of the draft.
reply_to string | string[] Reply-to addresses: one address or a list.
to string | string[] Recipient addresses: one address or a list.
cc string | string[] CC addresses: one address or a list.
bcc string | string[] BCC addresses: one address or a list.
subject string Subject.
text string Plain text body.
html string HTML body.
attachments SendAttachment[] Attachments, sent with the draft. Each needs content or url; a url is fetched when the draft is sent.
in_reply_to string ID of a message in this inbox to reply to: the sent message gets its In-Reply-To and References headers.
send_at string (date-time) | null Schedule the draft: it is sent automatically at this time (send_status: scheduled). null or absent: not scheduled.
client_id string Idempotency key: a create with a client_id already used in the organization returns that draft with 200, or 409 when that draft is outside the pod or inbox of the API key or route.

CreatedTrustedDomain

The entry, with any warnings about mail that stays blocked.

Field Type Description
trusted_domain_id string required ID of the entry (td_...).
entry_type "domain" | "email" required domain: every address at the domain (and its subdomains with include_subdomains). email: exactly one address.
domain string required The domain, or for entry_type: "email" the address, lowercased, with the domain in its ASCII (punycode) form.
domain_unicode string required The same, with the domain in its Unicode form. Equal to domain for ASCII names.
include_subdomains boolean required Also trust mail signed by subdomains (billing.example.com for example.com). Always false for addresses.
scope "org" | "pod" | "inbox" required Where an entry applies: the whole organization, one pod, or one inbox.
pod_id string | null required The pod, for pod- and inbox-scoped entries.
inbox_id string | null required The inbox, for inbox-scoped entries.
reason string | null required Why it was added, for people reading the list. Never included in a message’s trust report.
expires_at string (date-time) | null required When the entry stops applying. null: never.
created_by object | null required Who added the entry.
match_count integer required Messages this entry has marked trusted.
last_matched_at string (date-time) | null required When this entry last marked a message trusted. null: never.
created_at string (date-time) required When the entry was added.
updated_at string (date-time) required When the entry last changed.
warnings Warning[] required Conflicts with block entries or allow-only scopes. Empty when there are none.

CreateInboxRequest

Field Type Description
username string Local part of the address: a-z, 0-9 and . _ + -, 1 to 64 characters. Randomly generated if omitted. On the shared domain, a username equal to another organization's slug is reserved for that organization (409).
domain string Domain of the address: a domain verified by this organization. Defaults to the shared domain.
display_name string Display name: Display Name username@domain.com.
client_id string Idempotency key: a create with a client_id already used in the organization returns that inbox with 200, or 409 when that inbox is outside the pod of the API key or route.
status "active" | "paused" Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata Record<string, string | number | boolean> Custom key-value pairs attached to the inbox.
pod_id string Pod to create the inbox in. Defaults to the credential pod or the organization default pod.
ephemeral boolean true without ttl_seconds creates an ephemeral inbox with a one hour TTL (3600 seconds).
ttl_seconds integer | null Creates an ephemeral inbox that expires ttl_seconds after creation, extended by each inbound message.
import_source "agentmail" Marks an inbox copied from another provider by an importer (machinemail import agentmail sets agentmail). The only effect: its inbox.created event is not delivered to webhooks or MCP subscribers, so they are not notified about an inbox that already existed elsewhere. The event is still recorded (GET /v0/events, the event stream), marked as an import in its payload, so the event log shows every import. Everything else about the create is unchanged.

CreateInvitationRequest

Field Type Description
email string required Address to invite.
role "owner" | "admin" | "member" Role on joining. Default member. Only owners can invite owners.

CreateListEntryRequest

Field Type Description
entry string required Email address or domain to add. (min length 1)
reason string Reason for adding the entry.

CreatePodRequest

Field Type Description
name string Name of the pod. Default Untitled pod.
client_id string Idempotency key: a create with a client_id already used in the organization returns that pod with 200.

CreateSessionOrganizationRequest

Field Type Description
name string required Name of the new organization.

CreateSuppressionRequest

Field Type Description
email string required Address to suppress.
detail string Note stored as detail.
reason string deprecated Old name of detail (it is stored as detail; the suppression reason is always manual). Ignored when detail is set.

CreateTrustedDomainRequest

Field Type Description
domain string required A domain (example.com) or an exact address (invoices@example.com). Unicode names are accepted and stored in ASCII (punycode) form. (min length 1, max length 320)
include_subdomains boolean Also trust mail signed by subdomains. Default false. Not allowed for an address.
reason string Why you trust it, for people reading the list. Never included in a message’s trust report. (max length 500)
expires_at string (date-time) When the entry stops applying. Must be in the future. Omit for never.
confirm boolean Required (true) for platforms where anyone can write the content (github.com, google.com, slack.com and similar, or one under the domain with include_subdomains) and for one address on a group or marketplace relay (team@googlegroups.com): without it the answer is 422 confirmation_required.
client_id string Idempotency key: a create with a client_id already used in the organization returns that entry (200).

CreateWebhookRequest

Field Type Description
url string required Endpoint URL: a public http(s) URL (private and loopback addresses are rejected, and re-checked before every delivery).
event_types ("message.received" | "message.received.spam" | "message.received.quarantined" | "message.received.unauthenticated" | "message.received.blocked" | "message.sent" | "message.delivered" | "message.bounced" | "message.complained" | "message.rejected" | "domain.verified" | "domain.updated" | "inbox.created" | "inbox.expired" | "draft.sent" | "webhook.test" | "trusted_domain.created" | "trusted_domain.updated" | "trusted_domain.deleted")[] Event types the webhook receives. Omit it or send an empty array to receive every event type except domain.updated and trusted_domain.*, which are sent only when listed.
client_id string Idempotency key: a create with a client_id already used in the organization returns that webhook with 200, or 409 when that webhook is outside the pod or inbox of the API key or route.
inbox_ids string[] Only deliver events of these inboxes.
pod_ids string[] Only deliver events of these pods.
headers Record<string, string> Custom HTTP headers sent with every delivery to this webhook (every attempt, retry, replay and test event), alongside the X-MachineMail-* headers, for example {"Authorization": "Bearer "} for an endpoint that requires one. Values are write-only: they are stored encrypted and no response returns them; reads list the names (header_names). The headers are not part of the signed payload: X-MachineMail-Signature covers the body only. At most 10 headers. Names are HTTP tokens of up to 64 characters, compared without regard to case; values are printable ASCII (no line breaks or control characters) of up to 4096 characters, with surrounding spaces removed, and names plus values total at most 8192 bytes. Reserved names are refused with 400: Host, Content-Length, Content-Type, Content-Encoding, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, Expect, User-Agent, Accept-Encoding, and every name starting with Proxy-, Sec-, X-MachineMail-, Svix- or Webhook-. Authorization and Cookie are allowed.

DeleteOrganizationRequest

Field Type Description
code string required The 6-digit code from the email.

DeleteOrganizationResponse

The organization is deleted.

Field Type Description
ok true required
organization_id string required ID of the deleted organization.

Delivery

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.
timestamp string (date-time) required When it happened.
recipients string[] required Delivered recipients.

Domain

Field Type Description
pod_id string required ID of the pod the domain belongs to.
domain_id string required ID of the domain.
domain string required The domain name (for example example.com), lowercased.
feedback_enabled boolean required Stored as given. MachineMail does not send bounce and complaint notifications to inboxes; use the message.bounced and message.complained events.
inbound_enabled boolean required Receive email for this domain. false makes it send-only: the inbound MX record is not required.
subdomains_enabled boolean required Always false: inboxes on subdomains are not supported.
tracking_enabled boolean required Always false: open tracking is not supported.
client_id string Client ID given at creation (idempotency key).
updated_at string (date-time) required Time at which the domain was last updated.
created_at string (date-time) required Time at which the domain was created.
status "NOT_STARTED" | "PENDING" | "INVALID" | "FAILED" | "VERIFYING" | "VERIFIED" required NOT_STARTED until the first verify, then VERIFIED when every required record is valid, INVALID when a required record has the wrong value, otherwise PENDING. For domains whose email provider reports its own verdict (Amazon SES): VERIFYING while every required record checks out but the provider has not confirmed them yet, and FAILED when the provider gave up (reason says why).
reason string Why the domain is not verified yet: what to do next, or which records are missing or invalid. Absent once VERIFIED.
records VerificationRecord[] required DNS records to publish.
organization_id string required ID of the organization.
catch_all boolean required Mail to any address at the domain without an inbox creates one (created_by: catch_all).
catch_all_ttl_seconds integer TTL of inboxes created by catch-all; absent means they are permanent.
nameservers string[] Authoritative nameservers, detected on create and verify.
dns_provider "cloudflare" | "route53" | "google" | "vercel" | "namecheap" | "godaddy" | "digitalocean" | "hetzner" | "porkbun" | "other" DNS host the nameservers belong to.
dns_provider_url string Link to the DNS host console.
domain_connect object One-click DNS setup (Domain Connect), from the last discovery. See Get Domain Connect Setup.
verified_at string (date-time) When the domain became VERIFIED.
last_checked_at string (date-time) When the DNS records were last checked.

DomainConnect

Field Type Description
supported boolean required The zone DNS provider supports Domain Connect and has the MachineMail template.
provider_name string Display name of the DNS provider.
apply_url string Signed link that opens the provider with the outstanding records prefilled. Absent when nothing is left to add.
provider_id string Domain Connect provider ID.
url_sync_ux string Base URL of the provider synchronous flow.
width integer Suggested popup width, in pixels.
height integer Suggested popup height, in pixels.
reason "no_domain_connect" | "provider_error" | "no_sync_flow" | "template_not_supported" | "records_not_templatable" | "already_configured" | "not_configured" Why one-click setup is not available, or already_configured when nothing is left to add.
checked_at string (date-time) required When discovery last ran.

DomainItem

Draft

Field Type Description
inbox_id string required ID of the inbox.
draft_id string required ID of the draft.
labels string[] required Labels of the draft. The sent message gets them.
to string[] Recipient addresses.
cc string[] CC addresses.
bcc string[] BCC addresses.
subject string Subject of the draft.
preview string Text preview of the draft.
attachments Attachment[] Attachments of the draft. size is 0 for attachments given by url until the draft is sent (the URL is fetched then).
in_reply_to string ID of the message being replied to.
send_status "scheduled" | "sending" | "failed" scheduled while waiting for send_at, sending while a sender holds it, failed when a scheduled send failed (it is not retried). Absent on drafts without send_at.
send_at string (date-time) Time at which the draft is sent automatically.
updated_at string (date-time) required Time at which the draft was last updated.
client_id string Client ID given at creation (idempotency key).
reply_to string[] Reply-to addresses.
text string Plain text body.
html string HTML body.
references string[] Message IDs the draft references (set from in_reply_to).
created_at string (date-time) required Time at which the draft was created.
pod_id string required ID of the pod.

DraftItem

EmailCodesRequest

Field Type Description
enabled boolean required false turns email sign-in codes off; true back on.

EmailCodesResponse

Field Type Description
email_codes boolean required Email sign-in codes work for this account now.

EmailCodeStartRequest

Field Type Description
email string Address to send the code to. Optional with invitation_token (the code goes to the invited address).
next string Same-origin path to land on after sign-in, for example /cli?code=ABCD-EFGH. Anything else is ignored. Default /app.
invitation_token string An invitation token (from /invite/{token}): signing in accepts the invitation.

EmailCodeStartResponse

Field Type Description
ok true required
redirect_to string Set when the address’s domain signs in with SSO: send the browser here (the organization’s identity provider). Otherwise a code was emailed: show the code screen.

EmailCodeVerifyRequest

Field Type Description
code string required The 6-digit code from the email. Spaces and dashes are ignored.

Event

An event in the replayable log. Webhooks, the SSE stream and the WebSocket deliver the event envelope instead (type: "event" with the data keys also at the top level).

Field Type Description
event_id string required ID of the event (evt_...). Sorts by creation time.
event_type "message.received" | "message.received.spam" | "message.received.quarantined" | "message.received.unauthenticated" | "message.received.blocked" | "message.sent" | "message.delivered" | "message.bounced" | "message.complained" | "message.rejected" | "domain.verified" | "domain.updated" | "inbox.created" | "inbox.expired" | "draft.sent" | "webhook.test" | "trusted_domain.created" | "trusted_domain.updated" | "trusted_domain.deleted" | "registration.created" | "token.issued" | "agent.claimed" | "agent.revoked" | "member.invited" | "member.role_changed" | "member.removed" required Type of event: an events_EventType, or an audit event for agent registrations and members (registration.created, token.issued, agent.claimed, agent.revoked, member.invited, member.role_changed, member.removed), which is logged but never delivered to webhooks or streams.
organization_id string required ID of the organization.
pod_id string ID of the pod. Absent for organization-level events.
inbox_id string ID of the inbox. Absent for events without an inbox (for example domain.verified).
data Record<string, unknown> required Event payload, as delivered to webhooks: message.* events carry message and thread, delivery events their send, delivery, bounce, complaint or reject object, inbox.* the inbox, domain.verified and domain.updated the domain, trusted_domain.* the trusted_domain.
timestamp string (date-time) required When the event happened (same as created_at).
created_at string (date-time) required When the event was stored.

FirstKeyResponse

Field Type Description
api_key OneTimeApiKey required An API key with its plaintext secret, returned once.

HealthResponse

Field Type Description
status "ok" required

Identity

Identity and scope of the credential.

Field Type Description
scope_type "organization" | "pod" | "inbox" required The scope tier the credential is bound to.
scope_id string required ID of the most specific scope: inbox_id for an inbox credential, pod_id for a pod credential, otherwise organization_id.
organization_id string required ID of the organization.
pod_id string ID of the pod the credential is scoped to. Present when scope_type is pod, and for inbox credentials created under a pod.
inbox_id string ID of the inbox the credential is scoped to. Present when scope_type is inbox.
api_key_id string ID of the API key used. Absent for dashboard sessions and agent access tokens.
api_key_expires_at string (date-time) When the API key used expires. Absent when it does not expire, and for other credentials.
user object The signed-in user, for a dashboard session.

InboundRawResponse

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.

Inbox

Field Type Description
pod_id string required ID of the pod the inbox belongs to.
inbox_id string required ID of the inbox: its email address, as in AgentMail (inbox_id == email).
email string required Email address of the inbox.
display_name string Display name: Display Name username@domain.com.
client_id string Client ID given at creation (idempotency key).
status "active" | "paused" required Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata Record<string, string | number | boolean> Custom key-value pairs attached to the inbox.
updated_at string (date-time) required Time at which the inbox was last updated.
created_at string (date-time) required Time at which the inbox was created.
organization_id string required ID of the organization.
ephemeral boolean required Whether the inbox expires (see ttl_seconds).
ttl_seconds integer TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_at string (date-time) When an ephemeral inbox and its mail are deleted.
created_by "api" | "catch_all" | "dashboard" | "agent" required What created the inbox: the API, a catch-all domain, the dashboard or an agent registration.

InboxAvailability

Field Type Description
available boolean required
email string required The address that was checked (lowercased).
reason "invalid_username" | "domain_not_found" | "taken" Why the address is not available.
message string Human-readable reason.

Invitation

An invitation to join the organization.

Field Type Description
invitation_id string required ID of the invitation.
organization_id string required ID of the organization the invitee joins.
email string required Address the invitation was sent to. Only this address can accept it.
role "owner" | "admin" | "member" required Role in the organization. Owners and admins invite, change roles and remove members; only owners grant or remove the owner role, and an organization always keeps one owner.
state "pending" | "accepted" | "expired" | "revoked" required State of the invitation.
invited_by_user_id string ID of the member who sent it, when known.
expires_at string (date-time) required When the invitation stops working (7 days after it was sent).
created_at string (date-time) required When the invitation was sent.

InvitationPreviewResponse

What an invitation link is for, before signing in.

Field Type Description
organization_name string required The organization the invitation is to.
email string required The invited address, masked (a••@example.com).
state "pending" | "accepted" | "expired" | "revoked" required Only a pending invitation can be accepted.
expires_at string (date-time) required When the invitation expires.

JsonRpcError

JSON-RPC 2.0 error response.

Field Type Description
jsonrpc "2.0" required
error object required
id string | number | null required

JsonWebKeySet

RFC 7517 JWK Set.

Field Type Description
keys Record<string, unknown>[] required

ListAgentRegistrationsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
agent_registrations AgentRegistration[] required Newest first unless ascending is set.

ListApiKeysResponse

Field Type Description
count integer required Number of items returned.
limit integer required Page size used.
next_page_token string Page token for pagination. Absent on the last page.
api_keys BearerApiKey[] required Keys in the route scope that are not revoked, ordered by created_at, newest first unless ascending is set.

ListDeliveriesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
deliveries WebhookDelivery[] required Ordered by created_at, newest first unless ascending is set.

ListDomainsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
domains DomainItem[] required Ordered by created_at, newest first unless ascending is set.

ListDraftsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
drafts DraftItem[] required Ordered by created_at, newest first unless ascending is set.

ListEntry

An allow or block list entry. The route sets the list: /v0/lists is the organization list, /v0/pods/{pod_id}/lists the pod list, /v0/inboxes/{inbox_id}/lists the inbox list.

Field Type Description
entry string required Email address or domain (lowercased).
organization_id string required ID of the organization.
pod_id string ID of the pod, for pod-scoped entries.
inbox_id string ID of the inbox, for inbox-scoped entries.
reason string Reason given when the entry was added.
direction "send" | "receive" | "reply" required receive: who may send to you (inbound mail from a blocked sender is labeled BLOCKED). send: who you may send to (a blocked recipient is a 403). reply entries are stored and listed but not applied to any mail yet.
list_type "allow" | "block" required block refuses matching addresses. allow makes the list exclusive: once it has an entry, only matching addresses pass.
entry_type "email" | "domain" required Whether the entry is an email address or a domain.
read_only boolean required Always false: every entry can be deleted through the API.
created_at string (date-time) required Time at which the entry was created.

ListEventsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
events Event[] required Newest first; oldest first when after is set or ascending is true.

ListInboxesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
inboxes Inbox[] required Ordered by created_at, newest first unless ascending is set.

ListInvitationsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
invitations Invitation[] required Pending invitations, newest first.

ListListEntriesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
entries ListEntry[] required Ordered by entry, ascending unless ascending is false.

ListMembersResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
members Member[] required Oldest first unless ascending=false.

ListMessagesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
messages MessageItem[] required Ordered by timestamp, newest first unless ascending is set.

ListOAuthGrantsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
oauth_grants OAuthGrant[] required Newest first unless ascending is set.

ListPasskeysResponse

Field Type Description
passkeys Passkey[] required The person’s passkeys, oldest first.
email_codes boolean required Email sign-in codes work for this account. false once turned off (with at least one passkey).
step_up object required Confirmation before sensitive changes.
prompt boolean required Offer to create a passkey (no passkey yet, and the offer was not snoozed or declined).

ListPodsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
pods Pod[] required Ordered by created_at, newest first unless ascending is set. A pod credential sees only its pod.

ListSessionOrganizationsResponse

Field Type Description
organizations MembershipOrganization[] required Every organization the person belongs to, by name.

ListSuppressionsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
suppressions Suppression[] required Newest first unless ascending is set.

ListThreadsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
threads ThreadItem[] required Ordered by timestamp, newest first unless ascending is set.
truncated true Present when q matched more than 500 messages: only the threads of the newest 500 matching messages were considered.

ListTrustedDomainsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
trusted_domains TrustedDomain[] required Entries stored at exactly this level (organization, pod or inbox), newest first unless ascending is set.

ListWebhooksResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
webhooks Webhook[] required Ordered by created_at, newest first unless ascending is set.

LoginRequest

Field Type Description
email string required
password string required

MagicLinkRequest

Field Type Description
email string required Address to send the sign-in link to.
org_name string Organization name, used only when this is the address’s first sign-in.
next string Same-origin path to land on after sign-in, for example /claim?user_code=123456. Anything else is ignored. Default /app.
organization_name string Alias of org_name.
organizationName string deprecated Alias of org_name.

MagicLinkResponse

Field Type Description
ok true required

McpDescription

How to connect to the remote MCP server.

Field Type Description
name string required
description string required What the server is for, in one line.
icons object[] required The MachineMail mark, for clients and registries that show an icon.
version string required
transport "streamable-http" required
url string required The canonical MCP endpoint, https://mcp.machinemail.dev/mcp. https://machinemail.dev/mcp also works (legacy alias).
authentication object required
docs string required

Member

A person in the organization, with their role there and how they sign in.

Field Type Description
user_id string required ID of the user.
email string required Email address the user signs in with.
name string | null Display name, when set.
organization_id string required ID of the organization this record is about: the session’s active organization, or the organization listed.
role "owner" | "admin" | "member" required Role in the organization. Owners and admins invite, change roles and remove members; only owners grant or remove the owner role, and an organization always keeps one owner.
created_at string (date-time) required When the user was created.
sign_in_methods ("email" | "password" | "google" | "github" | "apple" | "microsoft" | "sso" | "passkey")[] required Every method the member has used to sign in to this organization, in the order first used. Empty until their first sign-in after this was recorded.
last_sign_in_method ("email" | "password" | "google" | "github" | "apple" | "microsoft" | "sso" | "passkey" | null) | null required How the member last signed in to this organization. null until their first sign-in after this was recorded.

MembershipOrganization

An organization the signed-in person belongs to.

Field Type Description
organization_id string required ID of the organization.
name string required Name of the organization.
slug string required URL-safe name of the organization. Fixed when the organization is created; it never changes.
role "owner" | "admin" | "member" required Role in the organization. Owners and admins invite, change roles and remove members; only owners grant or remove the owner role, and an organization always keeps one owner.
current boolean required The session is signed in to this organization.

Message

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.

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.

Field Type Description
spf "pass" | "fail" | "none" | "neutral" | "softfail" | "temperror" | "permerror" Result of one authentication mechanism, in the vocabulary of the Authentication-Results header (RFC 8601). none: there was nothing to evaluate (no SPF record for the envelope sender domain, no DKIM signature, or no DMARC record for the From domain). temperror: the check could not complete, for example a DNS timeout.
dkim "pass" | "fail" | "none" | "neutral" | "softfail" | "temperror" | "permerror" Result of one authentication mechanism, in the vocabulary of the Authentication-Results header (RFC 8601). none: there was nothing to evaluate (no SPF record for the envelope sender domain, no DKIM signature, or no DMARC record for the From domain). temperror: the check could not complete, for example a DNS timeout.
dmarc "pass" | "fail" | "none" | "neutral" | "softfail" | "temperror" | "permerror" Result of one authentication mechanism, in the vocabulary of the Authentication-Results header (RFC 8601). none: there was nothing to evaluate (no SPF record for the envelope sender domain, no DKIM signature, or no DMARC record for the From domain). temperror: the check could not complete, for example a DNS timeout.
spf_domain string Envelope sender (MAIL FROM) domain the spf verdict is about (smtp.mailfrom, or the HELO name when the envelope sender was empty).
dkim_domain string Signing domain (d=) of the signature the dkim verdict is about: for pass, a signature that passed, preferring one aligned with the From domain. Present only when dkim is pass or fail. It is the domain as signed: compare it with the From domain before relying on it.
dmarc_domain string From domain the dmarc verdict is about (header.from).
arc_sealer string Domain of the forwarder whose ARC seal the verdicts were read from (for example google.com): they then describe the message as that forwarder received it. Present only on forwarded mail, and only beside at least one verdict. MachineMail does not validate ARC chains, so it reads verdicts from ARC only when its trust layer is set to believe any results header; by default it believes only its own receiving server and does not send this key.

MessageItem

A message without its bodies, as in lists.

MetricBucket

Field Type Description
timestamp string (date-time) required Start of the bucket.
count integer required Number of events in the bucket.

OAuthApproveRequest

Field Type Description
request_id string required
pod_id string Limit the grant to one pod of the organization. Default: the whole organization.
inbox_id string Limit the grant to one inbox (and its pod).
organization_id string The organization the grant is for, as the consent page showed it: it must be the one the session is signed in to (409 conflict otherwise, for example after another tab switched organizations). To connect the app to another organization the person belongs to, switch the session to it first (POST /auth/organizations/switch). Default: the session’s organization.

OAuthAuthorizationRequest

A pending authorization request, as the consent page shows it.

Field Type Description
request_id string required
client OAuthClientInfo required
redirect_uri string required Where the response goes.
redirect_host string required Host (or scheme, for an app link) of redirect_uri, for the human to check.
redirect_loopback boolean required The response goes to a program on this computer (http://127.0.0.1, localhost).
resource string required What the token will be good for: the MCP server (https://mcp.machinemail.dev/mcp, or the legacy /mcp) or / (the REST API and MCP).
scopes ScopeDescription[] required What the client asked for.
created_at string (date-time) required
expires_at string (date-time) required When the request expires (10 minutes after it was made).

OAuthClientInfo

Field Type Description
client_id string required
client_name string | null required Self-reported by the client.
client_uri string | null required Self-reported; https only.
logo_uri string | null required Self-reported; https only.
registration "dynamic" | "metadata_document" required dynamic: registered at /oauth2/register (name and logo unverified). metadata_document: client_id is the URL of its metadata document, so its host is verified.
host string | null required metadata_document: the host that serves the document (for example claude.ai).

OAuthDecision

Field Type Description
status "approved" | "denied" required
redirect_to string required Send the browser here: redirect_uri with code (or error=access_denied), state and iss.

OAuthDenyRequest

Field Type Description
request_id string required

OAuthError

OAuth / auth.md error body (RFC 6749 section 5.2, RFC 7591 section 3.2.2). The /agent/* and /oauth2/* endpoints use this shape instead of the API error envelope.

Field Type Description
error string required Error code: invalid_request, invalid_grant, invalid_client, invalid_target, invalid_scope, invalid_client_metadata, invalid_redirect_uri, unsupported_grant_type, unsupported_response_type, access_denied, authorization_pending, slow_down, expired_token, interaction_required, login_required, invalid_claim_token, claimed_or_in_flight, claim_expired, rate_limited, anonymous_not_enabled, service_auth_not_enabled, identity_assertion_not_enabled, invalid_issuer, invalid_signature, invalid_audience, expired, replay_detected, invalid_client_id, missing_verified_email.
error_description string required
message string required Same text as error_description.
registration_id string interaction_required only.
agent_id string interaction_required only.
registration_type "anonymous" | "service_auth" | "identity_assertion" interaction_required only.
claim_url string interaction_required only.
claim_token string interaction_required only.
claim_token_expires string (date-time) interaction_required only.
post_claim_scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] interaction_required only.
claim object interaction_required only.
max_age integer login_required only: the maximum auth_time age in seconds.

OAuthGrant

An app a person connected with OAuth. Revoking it ends its access and refresh tokens at once.

Field Type Description
grant_id string required ID of the grant (oag_...).
client_id string required
client_name string | null required Self-reported by the client at registration.
client_uri string | null required
logo_uri string | null required
registration "dynamic" | "metadata_document" required
user_id string required Who approved it.
user_email string | null required
scopes ("inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write")[] required
resource string required Audience of its access tokens.
pod_id string | null required Set when the grant is limited to one pod.
inbox_id string | null required Set when the grant is limited to one inbox.
created_at string (date-time) required
last_used_at string (date-time) | null required Last token refresh or API call (updated at most once a minute).
expires_at string (date-time) required When the current refresh token expires unless it is used (30 days after the last refresh).

OkResponse

Acknowledgement.

Field Type Description
ok true required

OneTimeApiKey

An API key with its plaintext secret, returned once.

Field Type Description
api_key_id string required ID of the API key.
api_key string required Plaintext secret (mm_live_...). Shown once.
prefix string required First characters of the key, shown in listings.
name string required Name of the key.
created_at string (date-time) required When the key was created.

Organization

The organization of the credential. plan and GET /v0/organizations/usage report plan allowances; inboxes are unlimited (no inbox_limit) and there are no billing fields.

Field Type Description
organization_id string required ID of the organization.
name string required Name of the organization.
slug string required URL-safe name of the organization, chosen from its name when it is created. It never changes, not even when the organization is renamed. {slug}@ on the shared domain is reserved for this organization: no other organization can create that inbox.
plan "free" | "pro" | "team" | "scale" required Plan of the organization.
inbox_count integer required Number of inboxes in the credential scope.
domain_count integer required Number of domains in the organization.
domain_limit integer Custom domains included in the plan. The Free plan cannot add more; paid plans can, and each extra domain is billed. Always present on GET /v0/organizations and PATCH /v0/organizations.
usage object Usage. Always present on GET /v0/organizations and PATCH /v0/organizations.
shared_domain string Domain every organization can create inboxes on, used when an inbox is created without domain. Always present on GET /v0/organizations and PATCH /v0/organizations.
undo_send boolean required Undo send in the dashboard: when true (the default), a message sent from the MachineMail dashboard waits 5 seconds before it goes out, so it can be undone. Only the dashboard reads it: the API, the MCP server and the CLI always send at once.
default_inbox_id string | null required The default inbox of the organization (its inbox_id). A new organization gets {slug}@ on the shared domain, named after the organization, as its default inbox; when that address cannot be used (a reserved name), it starts without one. The dashboard lists the default inbox first. Change it with PATCH /v0/organizations. null when there is none: it was cleared, its inbox was deleted, or (for a pod or inbox credential) it is outside the credential scope.
updated_at string (date-time) required Time at which the organization was last updated.
created_at string (date-time) required Time at which the organization was created.

OrganizationDeletionStarted

A confirmation code was emailed to you.

Field Type Description
email string required Where the code was sent: your own address, partly hidden.
expires_at string (date-time) required When the code stops working (10 minutes after it was sent).

Passkey

A passkey the signed-in person can sign in with.

Field Type Description
passkey_id string required ID of the passkey (pk_…).
name string required Name shown in Settings (named after its password manager or device when added; up to 64 characters).
created_at string (date-time) required When the passkey was added.
last_used_at string (date-time) | null required When it last signed in or confirmed a change.
backed_up boolean required Synced by its password manager to the person’s other devices.
device_type "singleDevice" | "multiDevice" multiDevice: a synced passkey. singleDevice: bound to one device or security key.

PasskeyCredentialRequest

Field Type Description
credential Record<string, unknown> required The browser’s AuthenticationResponseJSON.

PasskeyOptionsResponse

Field Type Description
options Record<string, unknown> required PublicKeyCredentialRequestOptionsJSON: pass to navigator.credentials.get().

PasskeyPromptRequest

Field Type Description
action "not_now" | "never" required not_now: ask again in 14 days. never: don’t ask again.

PasskeyRegistrationOptionsResponse

Field Type Description
options Record<string, unknown> required PublicKeyCredentialCreationOptionsJSON: pass to navigator.credentials.create().

PasskeySignInOptionsRequest

Field Type Description
next string Same-origin path to land on after sign-in. Anything else is ignored. Default /app.
invitation_token string An invitation token (from /invite/{token}): signing in accepts the invitation.

PendingOrganizationRequest

Field Type Description
organization_id string required One of the organizations from GET /auth/pending.

PendingSignInResponse

The sign-in in progress in this browser.

Field Type Description
step "code" | "organization" | "verify_email" required code: waiting for the emailed sign-in code. organization: pick an organization. verify_email: enter the code that verifies the email.
email string The address signing in, when known.
organizations object[] For organization: the organizations to pick from.
invitation boolean required Signing in accepts an invitation.

PendingVerifyRequest

Field Type Description
code string required The 6-digit code from the email. Spaces and dashes are ignored.

PlanLimits

The allowances that apply to the organization.

Field Type Description
messages_per_month integer | null required Inbound messages and outbound recipients together per calendar month (UTC). null: no combined cap (paid plans).
messages_per_day integer | null required The same, per UTC day. null: no daily cap.
inbound_per_month integer | null required Inbound messages included per month on paid plans (more is billed as overage). null on Free.
outbound_per_month integer | null required Outbound recipients included per month on paid plans (more is billed as overage). null on Free.
storage_bytes integer required Storage included, in bytes (1 GB = 1,000,000,000 bytes).
custom_domains integer required Custom domains included.
seats integer | null required Members (including pending invitations). null: unlimited.
overage boolean required true: usage past an allowance is billed, never blocked. false (Free): inbound past it is held and sending is refused until the reset.

PlanUsage

Plan allowances and usage of the organization in the current period.

Field Type Description
plan "free" | "pro" | "team" | "scale" required Plan of the organization: free, pro, team or scale.
period object required
limits PlanLimits required The allowances that apply to the organization.
usage object required
held object required
enforcement "enforce" | "shadow" | "off" | "exempt" required enforce: limits apply. shadow and off: limits are not applied right now (usage is still counted). exempt: this organization has its own limits (unclaimed agent sandbox).

Pod

Field Type Description
pod_id string required ID of the pod.
organization_id string required ID of the organization.
name string required Name of the pod.
is_default boolean required Whether this is the default pod, where inboxes go when no pod is given. It cannot be deleted.
client_id string Client ID given at creation (idempotency key).
updated_at string (date-time) required Time at which the pod was last updated.
created_at string (date-time) required Time at which the pod was created.

PreviewTrustedDomainRequest

Field Type Description
domain string required A domain (example.com) or an exact address (invoices@example.com). Unicode names are accepted and stored in ASCII (punycode) form. (min length 1, max length 320)
include_subdomains boolean As for create.

PreviewTrustedDomainResponse

What a create would do, without saving anything.

Field Type Description
domain string | null required The entry as it would be stored (ASCII form). null when it is not a domain or address.
domain_unicode string | null required The same in Unicode form.
entry_type object required
allowed boolean required Whether a create would be accepted (with confirm: true when confirmation_required), plan limit aside.
refusal ("free_mail" | "privacy_relay" | "shared_platform" | "public_suffix" | "disposable" | "invalid" | "confusable_idn" | null) | null required Why it cannot be trusted. null when it can.
message string | null required The refusal or confirmation, in one sentence. null when there is neither.
confirmation_required boolean required A platform where anyone can write the content, or a relay address: a create needs confirm: true.
warnings Warning[] required Conflicts with block entries or allow-only scopes, as a create would report them.
would_release object | null required Not computed yet: always null.
suggestions string[] | null required Narrower entries to consider (an exact address). Not computed yet: always null.

ProtectedResourceMetadata

RFC 9728 OAuth Protected Resource Metadata.

RatePoint

Field Type Description
timestamp string (date-time) required End of the window the point covers; the window is the window seconds before it.
rate number Bounced (or complained) messages divided by messages sent over the window, as a fraction (0.05 is 5%). Absent when nothing was sent in the window.
sent integer required Messages sent in the window.

ReadyResponse

Field Type Description
status "ready" | "unavailable" required ready when storage answers; the HTTP status is then 200, otherwise 503.
checks object required The checks behind status.

Recipient

Field Type Description
address string required Recipient address.
status string required bounced or complained.

RegisterPasskeyRequest

Field Type Description
credential Record<string, unknown> required The browser’s RegistrationResponseJSON.
name string Name for the passkey (up to 64 characters). Default: its password manager or device, or “Passkey”.

Reject

Field Type Description
inbox_id string required ID of the inbox.
thread_id null required Always null: nothing was stored.
message_id null required Always null: nothing was stored.
timestamp string (date-time) required When it happened.
reason "inbox_paused" | "plan_limit" | "plan_limit_expired" required Why the message was rejected. inbox_paused: the inbox is paused. plan_limit (MachineMail): the organization reached a Free plan limit and already holds as much mail as it may. plan_limit_expired (MachineMail): held mail was not released in time and was deleted.
from string required Sender of the rejected message.
subject string Subject of the rejected message.

RemovePasskeyResponse

Field Type Description
ok true required
sessions_ended integer required Sessions the passkey had signed in that were signed out.
signed_out boolean required This session was one of them: sign in again.

RenamePasskeyRequest

Field Type Description
name string required New name, 1 to 64 characters.

ReplyAllMessageRequest

Field Type Description
labels string | string[] Labels of the message. SENT is always added.
reply_to string | string[] Reply-to address or addresses.
text string Plain text body.
html string HTML body.
attachments SendAttachment[] Attachments to include.
headers Record<string, string> Headers to include. In-Reply-To and References also thread the message.
to string | string[] More recipients, added to the sender and recipients of the original.
cc string | string[] More CC recipients, added to the CC recipients of the original.
bcc string | string[] BCC recipient address or addresses.
subject string Subject of the reply. Defaults to the original subject with Re: in front.

ReplyToMessageRequest

Field Type Description
labels string | string[] Labels of the message. SENT is always added.
reply_to string | string[] Reply-to address or addresses.
to string | string[] Recipient address or addresses. Defaults to the sender of the original (its reply-to addresses if any); for an outbound original, its recipients.
cc string | string[] CC recipient address or addresses.
bcc string | string[] BCC recipient address or addresses.
reply_all boolean true replies to all recipients of the original, as Reply All Message does; to and cc are then added to them.
text string Plain text body.
html string HTML body.
attachments SendAttachment[] Attachments to include.
headers Record<string, string> Headers to include. In-Reply-To and References also thread the message.
subject string Subject of the reply. Defaults to the original subject with Re: in front.

RevokeOtherSessionsResponse

Field Type Description
ok true required
ended integer required Other sessions signed out.

RevokeRequest

Field Type Description
token string required An access token, a refresh token or an identity assertion.
token_type_hint string access_token, refresh_token or identity_assertion. A refresh token revokes its whole grant; an identity assertion its whole registration. Other values are ignored.
client_id string Refresh and access tokens of an app: when given, must be the client the token was issued to, or nothing is revoked.
client_secret string A confidential client authenticates as at the token endpoint (client_secret_post, or HTTP Basic).

ScopeDescription

Field Type Description
scope "inboxes.read" | "inboxes.write" | "messages.read" | "messages.send" | "messages.write" | "webhooks.read" | "webhooks.write" | "domains.read" | "domains.write" | "lists.read" | "lists.write" | "metrics.read" | "pods.read" | "pods.write" | "api_keys.read" | "api_keys.write" required OAuth scope. Each grants API key permissions: inboxes.* (inbox_*), messages.read (message, thread and label reads), messages.send (send, reply, drafts), messages.write (update and delete messages and threads), webhooks., domains., lists.* (allow/block lists and suppressions), pods., api_keys., metrics.read (metrics and the event log).
description string required

SearchInboxesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
inboxes Inbox[] required Matching inboxes, newest first.
truncated true Present when the organization has more than 500 inboxes in scope: only the newest 500 were searched.

SearchMessagesResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
messages MessageItem[] required Matching messages, newest first unless ascending is set.

SearchThreadsResponse

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
threads ThreadItem[] required Matching threads, ordered by timestamp, newest first unless ascending is set.
truncated true Present when q matched more than 500 messages: only the threads of the newest 500 matching messages were considered.

Send

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.
timestamp string (date-time) required When it happened.
recipients string[] required Every recipient (to, cc and bcc).

SendAttachment

Provide either content or url for each attachment.

Field Type Description
filename string Filename of the attachment. Defaults to the last segment of url.
content_type string Content type of the attachment. Defaults to the Content-Type of the url response.
content_disposition "inline" | "attachment" Content disposition of the attachment.
content_id string Content ID, for inline images referenced as cid: in the HTML body.
content string Base64 encoded content of the attachment.
url string URL the API downloads the attachment from: public http(s) only, no redirects, at most 10 MB, 20 second timeout.

SendMessageRequest

Field Type Description
labels string | string[] Labels of the message. SENT is always added.
reply_to string | string[] Reply-to address or addresses.
to string | string[] Recipient address or addresses.
cc string | string[] CC recipient address or addresses.
bcc string | string[] BCC recipient address or addresses.
subject string Subject of the message.
text string Plain text body.
html string HTML body.
attachments SendAttachment[] Attachments to include.
headers Record<string, string> Headers to include. In-Reply-To and References also thread the message.

SendMessageResponse

Field Type Description
message_id string required ID of the message.
thread_id string required ID of the thread.
timestamp string (date-time) required When the message was sent.

SessionResponse

The signed-in user and their organization.

Field Type Description
user User required A person who signs in to the dashboard.
organization Organization required The organization of the credential. plan and GET /v0/organizations/usage report plan allowances; inboxes are unlimited (no inbox_limit) and there are no billing fields.

SetError

RFC 8935 SET delivery error.

Field Type Description
err string required invalid_request, invalid_issuer, invalid_key or invalid_audience.
description string required

SignInStepResponse

The result of a sign-in step.

Field Type Description
ok true required
signed_in boolean required true: the mm_session cookie is set. false: another step comes first (organization picker, email verification, SSO).
redirect_to string required Where to send the browser next, built by the server: next (with welcome=1 after a first sign-in), /login/organization, /login/verify, an identity provider, or /login?error=.

SignupRequest

Field Type Description
email string required
password string required At least 8 characters.
name string Display name of the user.
org_name string Organization name.
organization_name string Alias of org_name.
organizationName string deprecated Alias of org_name.

SignupResponse

The new user, their organization and the first organization API key (shown once).

Field Type Description
user User required A person who signs in to the dashboard.
organization Organization required The organization of the credential. plan and GET /v0/organizations/usage report plan allowances; inboxes are unlimited (no inbox_limit) and there are no billing fields.
api_key OneTimeApiKey required An API key with its plaintext secret, returned once.

StartOrganizationDeletionRequest

Field Type Description
confirm_name string required The name of the organization, exactly as it is shown (case and spaces included).

StepUpEmailResponse

Field Type Description
ok true required
email string required Where the code went, masked.
expires_at string (date-time) required When the code expires (10 minutes).

StepUpEmailVerifyRequest

Field Type Description
code string required The 6-digit code from the email. Spaces and dashes are ignored.

StepUpResponse

Field Type Description
ok true required
recent_until string (date-time) required Until when sensitive changes need no further confirmation.

Suppression

An address MachineMail will not send to. Suppressions apply to the whole organization.

Field Type Description
email string required The suppressed address (lowercased).
organization_id string required ID of the organization.
reason "bounce" | "complaint" | "manual" required bounce: a permanent bounce. complaint: the recipient reported spam; only MachineMail support can remove it. manual: added with POST /v0/suppressions.
detail string Free text: the bounce diagnostic, or the note given when the address was added manually.
source_message_id string Message whose bounce or complaint caused the suppression.
created_at string (date-time) required When the address was suppressed.

SwitchOrganizationRequest

Field Type Description
organization_id string required ID of an organization the person belongs to.

Thread

Field Type Description
inbox_id string required ID of the inbox.
thread_id string required ID of the thread.
labels string[] required Labels of the thread: the union of the labels of its messages.
timestamp string (date-time) required Timestamp of the last sent or received message.
received_timestamp string (date-time) Timestamp of the last received message.
sent_timestamp string (date-time) Timestamp of the last sent message.
senders string[] required Senders in the thread. In format username@domain.com.
recipients string[] required Recipients (to and cc) in the thread. In format username@domain.com.
subject string Subject of the thread.
preview string Text preview of the last message in the thread.
attachments Attachment[] Attachments in the thread.
last_message_id string required ID of the last message in the thread.
message_count integer required Number of messages in the thread.
size integer required Size of the thread in bytes.
updated_at string (date-time) required Time at which the thread was last updated.
created_at string (date-time) required Time at which the thread was created.
pod_id string required ID of the pod.
count integer required Number of messages in this page.
limit integer Maximum number of messages requested for this page.
next_page_token string Token for the next, older page of messages. Absent when this page completes the thread.
messages Message[] required Messages in this page, oldest first. The first page has the newest messages; follow next_page_token for older ones.

ThreadItem

TokenRequest

Field Type Description
grant_type string required authorization_code (with PKCE) and refresh_token for apps and MCP clients; urn:ietf:params:oauth:grant-type:device_code for mm login; urn:ietf:params:oauth:grant-type:jwt-bearer (RFC 7523) exchanges an assertion; urn:workos:agent-auth:grant-type:claim polls with a claim_token. Other values: unsupported_grant_type.
code string authorization_code: the code from the authorization response. Single use; expires after 2 minutes.
redirect_uri string authorization_code: the redirect_uri of the authorization request, when it had one.
code_verifier string authorization_code: the PKCE code verifier (43 to 128 characters).
refresh_token string refresh_token: the current refresh token. Each use returns a new one; presenting a replaced one within 60 seconds of its replacement returns the current one, later it revokes the whole grant.
scope string refresh_token, optional: narrow the new access token to these scopes of the grant.
device_code string device_code: the device_code from /auth/cli/device/code.
assertion string jwt-bearer grant: the identity_assertion.
client_id string authorization_code and refresh_token: the client the code or token was issued to (invalid_grant otherwise); may instead come from an HTTP Basic Authorization header (client_secret_basic), or be left out (taken from the code or token). device_code: required. jwt-bearer, optional: the registration id.
client_secret string Confidential clients using client_secret_post (registered with a secret). Alternatively send Authorization: Basic base64(urlencode(client_id):urlencode(client_secret)) (client_secret_basic), not both. A missing or wrong secret: 401 invalid_client. Public clients need none; one they send is ignored.
resource string RFC 8707. authorization_code and refresh_token: must be the resource of the authorization request (invalid_target otherwise). jwt-bearer, optional audience pin: must be /.
claim_token string Claim grant: the claim_token from registration.

TokenResponse

auth.md grants issue no refresh_token (exchange the identity_assertion again); the authorization code and refresh grants do.

Field Type Description
access_token string required JWT (at+jwt) to send as Authorization: Bearer. Tokens from the authorization code grant are audience-bound: aud the MCP server (https://mcp.machinemail.dev/mcp, or the legacy /mcp) works on the MCP endpoint only (either URL), / on /v0 and the MCP endpoint. auth.md tokens work on both.
token_type "Bearer" required
expires_in integer required Lifetime of the access token in seconds.
scope string required Space-separated Scope values.
refresh_token string authorization_code and refresh_token grants: the new refresh token (rotated on every use).
identity_assertion string Claim grant only: the post-claim identity assertion.
assertion_expires string (date-time)

TrustedDomain

A trusted domain or address.

TrustReport

Trust report of an inbound message. Message content is untrusted: feed content.text to an LLM rather than the message text or html.

Field Type Description
level "verified" | "known" | "unknown" | "suspicious" | "quarantined" required Overall verdict, safest first. quarantined messages are labelled QUARANTINE and hidden from lists unless asked for.
score number required 0 to 1, higher is safer. Ranks messages within a level. (minimum 0, maximum 1)
basis "trusted_domain" trusted_domain: the sender is a trusted domain of the organization, pod or inbox (sender.trusted_domain) and the message carries that domain's own DKIM signature. It is verified, or known when it contains instructions to an AI agent, a phishing signal or malware (content.warnings), and never suspicious or quarantined. Agents get its text and attachments, except attachments the virus scan flags. Absent otherwise.
authentication object required
sender object required
content object required
links object[] required
attachments object[] required
classification object required
provider_verdicts object Spam and virus scans by the receiving mail provider. Only on messages it scanned.
reasons string[] required Human-readable reasons for the verdict.
computed_at string (date-time) required When the report was computed.

UpdateApiKeyRequest

Fields you omit are unchanged. permissions replaces the permission object in full. Scope and expiry cannot be changed.

Field Type Description
name string New name. A blank name is ignored.
permissions object New permissions; replaces the permission object in full.

UpdateDomainRequest

Field Type Description
feedback_enabled boolean Stored and returned; has no effect.
inbound_enabled boolean Receive email for this domain. false makes the inbound MX record optional and re-evaluates the status.
catch_all boolean Create an inbox for any address at the domain that receives mail.
catch_all_ttl_seconds integer | null TTL of inboxes created by catch-all from now on. null makes them permanent.

UpdateDraftRequest

Field Type Description
reply_to string | string[] | null Reply-to addresses. null clears them.
to string | string[] | null Recipient addresses. null clears them.
cc string | string[] | null CC addresses. null clears them.
bcc string | string[] | null BCC addresses. null clears them.
subject string | null Subject. null clears it.
text string | null Plain text body. null clears it.
html string | null HTML body. null clears it.
add_attachments SendAttachment[] Attachments to add. Each needs content or url.
remove_attachments string[] IDs of attachments to remove. Unknown IDs are ignored.
add_labels string[] Labels to add.
remove_labels string[] Labels to remove (applied after add_labels).
send_at string (date-time) | null Schedule (or reschedule) the draft. null unschedules it.

UpdateInboxRequest

Field Type Description
display_name string Display name: Display Name username@domain.com.
status "active" | "paused" Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata (Record<string, string | number | boolean | null>) | null Merged into the existing metadata: keys you send are added or overwritten, keys set to null are removed, other keys are kept. null clears all metadata.
ttl_seconds integer | null Make the inbox ephemeral with this TTL (expires_at restarts from now), or null to make it permanent.
ephemeral boolean false makes the inbox permanent (same as ttl_seconds: null). true alone has no effect; send ttl_seconds.

UpdateMemberRequest

Field Type Description
role "owner" | "admin" | "member" required Role in the organization. Owners and admins invite, change roles and remove members; only owners grant or remove the owner role, and an organization always keeps one owner.

UpdateMessageRequest

Field Type Description
add_labels string | string[] Label or labels to add.
remove_labels string | string[] Label or labels to remove.

UpdateMessageResponse

Field Type Description
message_id string required ID of the message.
labels string[] required Labels of the message after the update.

UpdateOrganizationRequest

Field Type Description
name string New name. Must not be blank.
slug string Immutable: the slug is fixed when the organization is created. Only the current value is accepted (a client echoing the organization back); any other value is a 400.
undo_send boolean Undo send in the dashboard: when true (the default), a message sent from the MachineMail dashboard waits 5 seconds before it goes out, so it can be undone. Only the dashboard reads it: the API, the MCP server and the CLI always send at once.
default_inbox_id string | null Make this inbox (an inbox_id of the organization) the default inbox, or null to have none. An unknown inbox is a 404.

UpdatePodRequest

Field Type Description
name string New name. Must not be blank.

UpdateThreadRequest

Field Type Description
add_labels string | string[] Label or labels to add to every message in the thread.
remove_labels string | string[] Label or labels to remove from every message in the thread. Applied after add_labels.

UpdateTrustedDomainRequest

Field Type Description
include_subdomains boolean Also trust mail signed by subdomains. Not allowed for an address.
confirm boolean Required (true) to turn on include_subdomains when a platform where anyone can write the content lies under the domain: without it the answer is 422 confirmation_required.
reason string | null New reason; null clears it. (max length 500)
expires_at string (date-time) | null New expiry, in the future; null removes it.

UpdateWebhookHeadersRequest

Sets, replaces or removes custom delivery headers; the headers you do not name are unchanged. Give at least one of headers (each name is added, or replaces the value of the header of that name in any case) or remove_headers. A name cannot be both set and removed in one request.

Field Type Description
headers Record<string, string> Custom HTTP headers sent with every delivery to this webhook (every attempt, retry, replay and test event), alongside the X-MachineMail-* headers, for example {"Authorization": "Bearer "} for an endpoint that requires one. Values are write-only: they are stored encrypted and no response returns them; reads list the names (header_names). The headers are not part of the signed payload: X-MachineMail-Signature covers the body only. At most 10 headers. Names are HTTP tokens of up to 64 characters, compared without regard to case; values are printable ASCII (no line breaks or control characters) of up to 4096 characters, with surrounding spaces removed, and names plus values total at most 8192 bytes. Reserved names are refused with 400: Host, Content-Length, Content-Type, Content-Encoding, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, Expect, User-Agent, Accept-Encoding, and every name starting with Proxy-, Sec-, X-MachineMail-, Svix- or Webhook-. Authorization and Cookie are allowed.
remove_headers string[] Names of custom headers to remove (any case). Names that are not set are ignored.

UpdateWebhookRequest

Field Type Description
event_types ("message.received" | "message.received.spam" | "message.received.quarantined" | "message.received.unauthenticated" | "message.received.blocked" | "message.sent" | "message.delivered" | "message.bounced" | "message.complained" | "message.rejected" | "domain.verified" | "domain.updated" | "inbox.created" | "inbox.expired" | "draft.sent" | "webhook.test" | "trusted_domain.created" | "trusted_domain.updated" | "trusted_domain.deleted")[] Replaces the subscribed event types in full (not a merge). An empty array subscribes to every event type except domain.updated and trusted_domain.*, which are sent only when listed. Omit it to keep the types.
enabled boolean false disables the webhook: no new deliveries are queued (deliveries already queued are still attempted). true enables it again. Events that occurred while it was disabled are not delivered later.
add_inbox_ids string[] Inboxes to add to inbox_ids.
remove_inbox_ids string[] Inboxes to remove from inbox_ids.
add_pod_ids string[] Pods to add to pod_ids.
remove_pod_ids string[] Pods to remove from pod_ids.
url string New endpoint URL: a public http(s) URL.
headers Record<string, string> | null Replaces the custom delivery headers in full (not a merge): the webhook then sends exactly these. null or {} removes them all; omit it to keep them. To change one header and keep the others, use PATCH /v0/webhooks/{webhook_id}/headers. Values are write-only. At most 10 headers. Names are HTTP tokens of up to 64 characters, compared without regard to case; values are printable ASCII (no line breaks or control characters) of up to 4096 characters, with surrounding spaces removed, and names plus values total at most 8192 bytes. Reserved names are refused with 400: Host, Content-Length, Content-Type, Content-Encoding, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, Expect, User-Agent, Accept-Encoding, and every name starting with Proxy-, Sec-, X-MachineMail-, Svix- or Webhook-. Authorization and Cookie are allowed.

UsagePoint

Field Type Description
timestamp string (date-time) required Time of the value (end).
value integer required Value of the usage metric now.

User

A person who signs in to the dashboard.

VerificationRecord

Field Type Description
type "TXT" | "CNAME" | "MX" required
name string required Name (host) of the record.
value string required Value of the record.
status "MISSING" | "INVALID" | "VALID" required MISSING: not published yet. INVALID: published with the wrong value.
priority integer Priority of an MX record.
reason string Why an INVALID record is invalid: Found: .
purpose "inbound" | "spf" | "dkim" | "dmarc" | "provider" required What the record is for. provider records come from the sending provider.
required boolean required Whether the record must be valid for the domain to verify. The inbound MX record is not required when inbound_enabled is false.

Warning

A conflict that does not stop the entry from being saved, but means some of its mail is still blocked.

Field Type Description
code "shadowed_by_block" | "shadowed_by_allow_only" required shadowed_by_block: a receive/block list entry matches some or all of the mail this entry trusts, and a block always wins over trust. shadowed_by_allow_only: the scope is allow-only (it has receive/allow entries) and none of them allows this sender, so the mail is still BLOCKED.
scope "org" | "pod" | "inbox" required Where an entry applies: the whole organization, one pod, or one inbox.
pod_id string The pod of the list, for pod and inbox scopes.
inbox_id string The inbox of the list, for the inbox scope.
entry object shadowed_by_block only: the block entry. Left out for credentials without list_entry_read.
message string required What the warning means, in one sentence.

Webhook

Field Type Description
webhook_id string required ID of the webhook.
url string required URL of the webhook endpoint.
event_types ("message.received" | "message.received.spam" | "message.received.quarantined" | "message.received.unauthenticated" | "message.received.blocked" | "message.sent" | "message.delivered" | "message.bounced" | "message.complained" | "message.rejected" | "domain.verified" | "domain.updated" | "inbox.created" | "inbox.expired" | "draft.sent" | "webhook.test" | "trusted_domain.created" | "trusted_domain.updated" | "trusted_domain.deleted")[] required Event types the webhook receives. Empty: every event type except domain.updated and trusted_domain.*, which are sent only when listed.
pod_ids string[] Only events of these pods. Absent: every pod in scope.
inbox_ids string[] Only events of these inboxes. Absent: every inbox in scope.
pod_id string Set when the webhook was created with a pod-scoped credential (or under /v0/pods/{pod_id}): it never receives events outside that pod.
inbox_id string Set when the webhook was created with an inbox-scoped credential (or under /v0/inboxes/{inbox_id}): it only receives events of that inbox.
secret string required Signing secret (whsec_...) for X-MachineMail-Signature. Returned on every read.
enabled boolean required Whether new events are delivered. Webhooks are never disabled automatically.
updated_at string (date-time) required Time at which the webhook was last updated.
created_at string (date-time) required Time at which the webhook was created.
client_id string Client ID given at creation (idempotency key).
status "active" | "disabled" required active or disabled; mirrors enabled.
header_names string[] required Names of the custom delivery headers (headers), as they were set; empty when there are none. Values are write-only and never returned.
headers_updated_at string (date-time) When the custom headers were last set or changed. Absent when they never were.

WebhookDelivery

Field Type Description
delivery_id string required ID of the delivery (X-MachineMail-Delivery-Id).
webhook_id string required ID of the webhook.
event_id string required ID of the event (X-MachineMail-Event-Id).
event_type "message.received" | "message.received.spam" | "message.received.quarantined" | "message.received.unauthenticated" | "message.received.blocked" | "message.sent" | "message.delivered" | "message.bounced" | "message.complained" | "message.rejected" | "domain.verified" | "domain.updated" | "inbox.created" | "inbox.expired" | "draft.sent" | "webhook.test" | "trusted_domain.created" | "trusted_domain.updated" | "trusted_domain.deleted" required Type of event. AgentMail has no message.received.quarantined, domain.updated, inbox.created, inbox.expired, draft.sent or webhook.test; MachineMail does not emit message.opened or calendar.event.. domain.updated is sent whenever a DNS check changes the domain status or a record status (the change to VERIFIED also sends domain.verified). trusted_domain.created, .updated and .deleted (MachineMail) record changes to trusted domains. Webhooks and WebSocket subscriptions receive domain.updated and the trusted_domain. types only when their event_types list them, while the SSE stream and the event log always include them.
attempt integer required Number of attempts so far.
status "pending" | "delivered" | "failed" required pending until a 2xx response (delivered), or failed when retries stop (5 days after the event) or the webhook or event was deleted.
response_status integer HTTP status of the last attempt.
response_body string First 1024 bytes of the last response body.
next_attempt_at string (date-time) When the next attempt is due, while pending.
last_error string Error of the last failed attempt (HTTP 500, a network error).
delivered_at string (date-time) When the delivery succeeded.
created_at string (date-time) required When the delivery was queued.
updated_at string (date-time) required Last change to the delivery.

WebhookHeaderNamesResponse

Field Type Description
header_names string[] required Names of the custom delivery headers of this webhook, as they were set. Values are never returned.
headers_updated_at string (date-time) When the custom headers were last set or changed. Absent when they never were.