{"openapi":"3.1.0","info":{"title":"MachineMail API","version":"0.1.0","summary":"Email for AI agents. Wire-compatible with AgentMail.","description":"MachineMail gives every AI agent its own inbox and makes sure nothing in it can hijack the agent. The `/v0` API is wire-compatible with AgentMail: snake_case fields, `limit`/`page_token`/`next_page_token` pagination, and the same paths and resource shapes. MachineMail adds trust reports, pods, catch-all and ephemeral inboxes, delivery replay and event streaming; fields and operations AgentMail does not have are marked `x-machinemail: true`.\n\nEach operation lists the API key permission it requires in `x-permission` (any one of the listed permissions is enough). Errors on `/v0` are `{\"error\": {\"type\", \"message\", \"param\"?}}` with the HTTP status of `type`.\n\nSee https://machinemail.dev/docs/reference/agentmail-compatibility for the operation-by-operation comparison with AgentMail.","contact":{"name":"MachineMail","url":"https://machinemail.dev"}},"servers":[{"url":"https://api.machinemail.dev","description":"Production"}],"security":[{"Bearer":[]},{"SessionCookie":[]}],"tags":[{"name":"Inboxes","description":"Inboxes. `inbox_id` is the email address."},{"name":"Messages","description":"Send, receive, search and manage messages."},{"name":"Threads","description":"Conversation threads."},{"name":"Drafts","description":"Drafts (unsent messages a person can send or delete) and scheduled sends (`send_at`)."},{"name":"Trust","description":"Trust reports for inbound messages."},{"name":"Domains","description":"Custom domains, DNS records, catch-all."},{"name":"Webhooks","description":"Webhook endpoints, deliveries and replay."},{"name":"Webhook Events","description":"Payloads delivered to your webhook URL."},{"name":"Lists","description":"Allow and block lists for the organization, a pod or an inbox. A non-empty allow list is allow-only: one `receive/allow` entry blocks mail from every sender not on it."},{"name":"Trusted Domains","description":"Domains and addresses the organization, a pod or an inbox trusts: mail they genuinely sign is never quarantined or withheld from agents. Trust never beats a block entry or opens an allow-only scope."},{"name":"Suppressions","description":"Addresses we will not send to."},{"name":"Events","description":"Replayable event log and live streams."},{"name":"Metrics","description":"Counts and rates."},{"name":"Export","description":"Inbox export."},{"name":"Organization","description":"The authenticated organization."},{"name":"Auth","description":"The credential making the request: its organization, pod, inbox and permissions."},{"name":"Pods","description":"Pods group inboxes, domains and webhooks."},{"name":"API Keys","description":"Organization, pod and inbox scoped keys."},{"name":"Inbound","description":"Raw message injection: store an RFC 5322 message as if it had been received."},{"name":"Health","description":"Liveness and readiness."},{"name":"OpenAPI","description":"This document."},{"name":"Agent Auth","description":"The MachineMail authorization server: OAuth sign-in for apps and MCP clients (authorization code with PKCE, client registration) and the auth.md protocol for agent onboarding."},{"name":"Agent Registrations","description":"Agent registrations bound to the organization."},{"name":"Connected Apps","description":"Apps and MCP clients connected with OAuth."},{"name":"MCP","description":"Remote MCP server (Streamable HTTP) and its description document."},{"name":"CLI Auth","description":"Signing the CLI in with the browser (RFC 8628 device authorization grant)."},{"name":"Dashboard Auth","description":"Cookie sessions for the dashboard."}],"paths":{"/.well-known/jwks.json":{"get":{"operationId":"agentAuth_jwks","tags":["Agent Auth"],"summary":"JSON Web Key Set","description":"The service’s public signing key (RFC 7517). Verifies the identity assertions and access tokens this service issues.","security":[],"x-machinemail":true,"responses":{"200":{"description":"JWKS","headers":{"Cache-Control":{"description":"`public, max-age=600`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonWebKeySet"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/.well-known/mcp.json":{"get":{"operationId":"mcp_wellKnown","servers":[{"url":"https://mcp.machinemail.dev","description":"MCP server; `https://machinemail.dev/mcp` is a legacy alias"}],"tags":["MCP"],"summary":"MCP Server Description","description":"Same document as a plain `GET /mcp`.","security":[],"x-machinemail":true,"responses":{"200":{"description":"How to connect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDescription"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"agentAuth_authorizationServer","tags":["Agent Auth"],"summary":"OAuth Authorization Server Metadata","description":"RFC 8414 plus the auth.md `agent_auth` block. `identity_types_supported` lists the registration types MachineMail accepts.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadata"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"agentAuth_protectedResource","tags":["Agent Auth"],"summary":"OAuth Protected Resource Metadata","description":"RFC 9728. Referenced by the `WWW-Authenticate` header on `401` responses from `/v0` and `/mcp`. On the MCP host (`mcp.machinemail.dev`) it describes the MCP server there, the same as the path-suffixed form.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/.well-known/oauth-protected-resource/{path}":{"get":{"operationId":"agentAuth_protectedResourcePath","tags":["Agent Auth"],"summary":"OAuth Protected Resource Metadata (Path-Suffixed)","description":"RFC 9728 metadata for a resource at a path, for example `/.well-known/oauth-protected-resource/mcp`. `resource` is `<issuer>/<path>`; everything else is the same as the root document. `path` may contain slashes. On the MCP host (`https://mcp.machinemail.dev/mcp`) only `mcp` is served and `resource` is that URL; `authorization_servers` still names the issuer.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"Resource path after the well-known name; may contain slashes (`mcp`, `v0/inboxes`).","name":"path","in":"path"}],"responses":{"200":{"description":"The metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/agent/event/notify":{"post":{"operationId":"agentAuth_eventNotify","tags":["Agent Auth"],"summary":"Receive Security Event Token","description":"RFC 8935 push delivery from a trusted agent provider. The body is a signed SET (`typ: secevent+jwt`) with `aud` equal to the issuer, a unique `jti`, and an `events` claim containing `https://schemas.workos.com/events/agent/auth/identity/assertion/revoked`. Every registration for that `(iss, sub)` is revoked.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/secevent+jwt":{"schema":{"type":"string","description":"Compact JWS."}}}},"responses":{"202":{"description":"Accepted (empty body)"},"400":{"description":"SET rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/agent/identity":{"post":{"operationId":"agentAuth_identity","tags":["Agent Auth"],"summary":"Register Agent Identity","description":"Dispatches on `type` (auth.md). No API key is ever returned.\n\n`anonymous` returns a pre-claim `identity_assertion` and the sandbox `inbox` (one ephemeral inbox on the shared domain); exchange the assertion at `/oauth2/token` for an access token.\n\n`service_auth` withholds the assertion and returns a `claim` block until the named user (`login_hint`) confirms.\n\n`identity_assertion` verifies an ID-JAG from a trusted provider. When the verified email belongs to an existing user it answers `401 interaction_required` with a `claim_token` and `claim` block; when `auth_time` is too old, `401 login_required` with `max_age`. Both set `WWW-Authenticate: AgentAuth error=\"...\"`.\n\nRegistration is rate limited per requester (an IPv4 address, or an IPv6 /64) and overall: `429 rate_limited` with `Retry-After`. `anonymous` and `service_auth` share a cap per requester of at most 1 per rolling hour and 3 per rolling 24 hours (an IPv6 /48, all its /64s together, at most 10 per rolling 24 hours), and a platform-wide cap of about 100 per rolling hour and 1000 per rolling 24 hours. `anonymous` is also refused while about 500 unclaimed sandbox inboxes are live (`Sandbox capacity is full right now`); a claimed or expired registration frees its place.\n\nRegistrations from a network that was blocked for abuse are refused with `403 registration_blocked` (no `Retry-After`: retrying does not help).\n\n`identity_assertion` with a verified email that matches no account creates a new organization; when that email is a disposable email address it is refused with `403 disposable_email_not_allowed` (`param` `email`): MachineMail doesn’t accept disposable addresses for new accounts.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIdentityRequest"}}}},"responses":{"200":{"description":"Registered","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIdentityResponse"}}}},"400":{"description":"OAuth error: `invalid_request` (including a body that fails validation), `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`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"OAuth error `interaction_required` or `login_required`.","headers":{"WWW-Authenticate":{"description":"`AgentAuth error=\"interaction_required\", ...` or `AgentAuth error=\"login_required\", max_age=\"...\", ...`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"403":{"description":"OAuth error `registration_blocked`: registration is not available from this network. Or `disposable_email_not_allowed`: an identity_assertion would create a new organization for a disposable email address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"OAuth error `rate_limited`.","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/agent/identity/claim":{"post":{"operationId":"agentAuth_claim","tags":["Agent Auth"],"summary":"Start Claim Ceremony","description":"Called by the agent. Protocol form: `{claim_token, email?}`. Alternative: `{agent_id}` (or `registration_id`) with the registration’s access token or identity assertion as `Authorization: Bearer`.\n\nReturns a 6-digit `user_code` and a `verification_uri` to show the human, who completes the claim in the dashboard (`POST /auth/claim`). The agent then polls `/oauth2/token` with the claim grant. Calling it again starts a fresh attempt.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimStartRequest"}}}},"responses":{"200":{"description":"Claim attempt started","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimStartResponse"}}}},"400":{"description":"OAuth error `invalid_request`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"OAuth error `invalid_claim_token`: `agent_id` without a valid access token or identity assertion as Bearer.","headers":{"WWW-Authenticate":{"description":"`Bearer error=\"invalid_token\"`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"404":{"description":"OAuth error `invalid_claim_token`: unknown or revoked registration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"409":{"description":"OAuth error `claimed_or_in_flight`: already claimed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"410":{"description":"OAuth error `claim_expired`: the registration expired before it was claimed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth.md":{"get":{"operationId":"agentAuth_authMd","tags":["Agent Auth"],"summary":"Agent Onboarding Document","description":"Markdown instructions for agents (auth.md protocol): how to register, claim and authenticate. Lists the registration types MachineMail accepts.","security":[],"x-machinemail":true,"responses":{"200":{"description":"auth.md","headers":{"Cache-Control":{"description":"`public, max-age=300`","schema":{"type":"string"}}},"content":{"text/markdown":{"schema":{"type":"string"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/authkit":{"get":{"operationId":"session_authkit","tags":["Dashboard Auth"],"summary":"Legacy Sign-In Redirect (Deprecated)","description":"Deprecated: an old sign-in entry point, kept so existing links work. Redirects to the sign-in page, `/login` (keeping a same-origin `next`).","deprecated":true,"security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"Same-origin path to land on after sign-in. Default `/app`.","name":"next","in":"query"}],"responses":{"302":{"description":"To `/login`.","headers":{"Location":{"description":"Where to go next.","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/callback":{"get":{"operationId":"session_callback","tags":["Dashboard Auth"],"summary":"Sign-in Callback","description":"Where the browser returns after a social or SSO sign-in. Checks `state` against the browser’s cookie, exchanges the code, links the sign-in to the MachineMail account with the same verified email (or creates one), syncs their organizations, sets the `mm_session` cookie and redirects to `next`. A person with no organization gets one, with a first API key (`welcome=1`, `GET /auth/first-key`).\n\nWhen the sign-in needs one more step, the browser goes to our own screens with a `mm_signin` cookie: `/login/organization` (pick an organization) or `/login/verify` (verify the email with a code), or on to the organization’s SSO connection.\n\nFailures redirect to `/login?error=signin_failed` (the sign-in was refused or failed), `access_denied` (cancelled at the provider), `unverified` (an unverified email matching an existing account), `linked` (the account is already linked to a different sign-in identity), `mfa` (the sign-in asked for multi-factor authentication, which MachineMail does not support), `methods` (the organization does not allow this sign-in method), `address_not_allowed` (a new account for an address that receives mail through MachineMail: sign up with an address outside MachineMail), `disposable_address` (a new account for a disposable email address: sign up with an address you’ll keep receiving mail at), `mailbox_has_account` (a new account for a mailbox that already has one, such as a Gmail address with dots moved or a `+` alias: `account` carries the existing account’s masked address to sign in with, and `invited=1` that an organization brought the person in) or `codes_paused` (too many codes for the address recently: a verification code was not sent; try later). A callback without `state` (one this browser did not start) never signs anyone in: it goes to `/login`, or to `/invite/{token}` when it carries an invitation token.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"Authorization code from the sign-in.","name":"code","in":"query"},{"schema":{"type":"string"},"required":false,"description":"The `state` sent with the authorization request.","name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Error code, when sign-in failed.","name":"error","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Error description, when sign-in failed.","name":"error_description","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Invitation token, on a sign-in started from an invitation email.","name":"invitation_token","in":"query"}],"responses":{"302":{"description":"Signed in (`Set-Cookie` carries `mm_session`), our next screen, or back to `/login` with an error.","headers":{"Location":{"description":"Where to go next.","schema":{"type":"string"}},"Set-Cookie":{"description":"`mm_session=<token>; HttpOnly; SameSite=Lax; Path=/` (plus `Secure` on https).","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/claim":{"get":{"operationId":"session_claimPreview","tags":["Dashboard Auth"],"summary":"Preview Claim","description":"Called by the dashboard `/claim` page for a signed-in human before confirming. Pass `user_code` or `claim_attempt_token`. Returns the registration (its agent-described `name` is untrusted), the claim email and the sandbox inbox. `403` when the registration is bound to a different email than the signed-in user; `429` after too many lookups (per user, 10 minute window).","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"The 6-digit code the agent shows; spaces and dashes are ignored.","name":"user_code","in":"query"},{"schema":{"type":"string"},"required":false,"description":"The `cat_...` token from `verification_uri`.","name":"claim_attempt_token","in":"query"}],"responses":{"200":{"description":"The pending registration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimPreviewResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"session_claim","tags":["Dashboard Auth"],"summary":"Complete Claim","description":"Called by the dashboard `/claim` page for a signed-in human. Binds the agent registration to their organization, moves the sandbox inbox into their default pod (made permanent) and invalidates pre-claim tokens. `403` when the signed-in user does not match the claim email; `429` after too many attempts (per user, 10 minute window).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimCompleteRequest"}}}},"responses":{"200":{"description":"Claimed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimCompleteResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: the agent inbox's received mail would take the organization past its monthly messages cap (`limit_key: \"messages_per_month\"`); nothing is claimed. Received mail counts toward the month it is claimed in."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/cli/device":{"get":{"operationId":"cliAuth_preview","tags":["CLI Auth"],"summary":"Preview CLI Sign-In","description":"Called by the dashboard `/cli` page for a signed-in human before approving. Returns what the CLI reported (client, hostname; self-reported) and the key approval would create; never the device code. `404` for an unknown, decided or expired code. Dashboard session only: API keys are not accepted. Every call counts against a per-user and per-IP limit on code lookups (brute-force brake): `429` with `Retry-After`.","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"The code the CLI printed (`XXXX-XXXX`); case, spaces and dashes are ignored.","name":"user_code","in":"query"}],"responses":{"200":{"description":"The pending sign-in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceAuthorization"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/cli/device/approve":{"post":{"operationId":"cliAuth_approve","tags":["CLI Auth"],"summary":"Approve CLI Sign-In","description":"Approves a pending code for the signed-in user. The CLI's next poll receives a new API key named `CLI on <hostname>` in the organization the session is signed in to (every permission except `inbound_raw`), listed under API keys and revocable there. Dashboard session only. Every call counts against a per-user and per-IP limit on code lookups (brute-force brake): `429` with `Retry-After`.\n\nA person in several organizations creates the key in another one by switching the session to it first (`POST /auth/organizations/switch`, which applies that organization’s sign-in policy), then approving. `organization_id` names the organization the page showed: `409 conflict` when the session is no longer on it.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}}},"responses":{"200":{"description":"Approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceDecision"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/cli/device/code":{"post":{"operationId":"cliAuth_deviceCode","tags":["CLI Auth"],"summary":"Start CLI Sign-In","description":"RFC 8628 device authorization request, made by `mm login`. Returns a `device_code` for the CLI to poll with and a `user_code` (`XXXX-XXXX`) for the human to approve at `verification_uri` (`https://machinemail.dev/cli`) while signed in to the dashboard. Both expire after 10 minutes.\n\nForm-encoded or JSON body. `client_id` must be `machinemail-cli` (`401 invalid_client` otherwise). Rate limited per client IP: `429 rate_limited` with `Retry-After`.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CliDeviceCodeRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceCodeRequest"}}}},"responses":{"200":{"description":"Codes issued","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceCodeResponse"}}}},"400":{"description":"OAuth error `invalid_request`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"OAuth error `invalid_client`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"OAuth error `rate_limited`.","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/cli/device/deny":{"post":{"operationId":"cliAuth_deny","tags":["CLI Auth"],"summary":"Deny CLI Sign-In","description":"Denies a pending code: the CLI's next poll gets `access_denied` and no key is created. Dashboard session only. Every call counts against a per-user and per-IP limit on code lookups (brute-force brake): `429` with `Retry-After`.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceDecisionRequest"}}}},"responses":{"200":{"description":"Denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceDecision"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/cli/device/token":{"post":{"operationId":"cliAuth_deviceToken","tags":["CLI Auth"],"summary":"Poll CLI Sign-In","description":"RFC 8628 token request with `grant_type=urn:ietf:params:oauth:grant-type:device_code`. Poll no faster than `interval` seconds until the human decides.\n\nAfter approval the next poll returns a new organization API key (`CLI on <hostname>`, every permission except `inbound_raw`, attributed to the approving user) as `access_token`, once: the device code is then spent.\n\nErrors (RFC 6749 section 5.2 bodies, status `400`): `authorization_pending` (keep polling), `slow_down` (polled faster than the interval; add 5 seconds), `expired_token` (start again), `access_denied` (denied in the browser), `invalid_grant` (unknown or already used device code), `unsupported_grant_type`, `invalid_request`.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CliDeviceTokenRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceTokenRequest"}}}},"responses":{"200":{"description":"The new API key, returned once","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}},"Pragma":{"description":"`no-cache`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceTokenResponse"}}}},"400":{"description":"OAuth error: `authorization_pending`, `slow_down`, `expired_token`, `access_denied`, `invalid_grant`, `unsupported_grant_type`, `invalid_request`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/config":{"get":{"operationId":"session_config","tags":["Dashboard Auth"],"summary":"Sign-in Options","description":"How people sign in to MachineMail: email codes (`POST /auth/email/start`), social providers (`GET /auth/social/{provider}`), SSO and passkeys (`POST /auth/passkey/options`), all on MachineMail’s own pages.","security":[],"x-machinemail":true,"responses":{"200":{"description":"Sign-in options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthConfigResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/email-codes":{"put":{"operationId":"session_setEmailCodes","tags":["Dashboard Auth"],"summary":"Turn Email Sign-in Codes On or Off","description":"Turns email sign-in codes off for the signed-in person (they sign in with a passkey, or a connected Google, GitHub or single sign-on account), or back on. While off, asking for a code for the address sends no code, and the address gets an email saying to use a passkey instead. Each change is emailed to the address.\n\nTurning codes off needs at least one passkey (`409` otherwise) and a recent sign-in (see below). Turning them on needs neither. Lost every passkey with codes off? Contact support@machinemail.dev.\n\nNeeds a recent sign-in: within 10 minutes of signing in, or of confirming it’s you on this session (`POST /auth/step-up/email/verify` or `POST /auth/step-up/passkey/verify`). Otherwise `403` with `error.code` `step_up_required` and `error.methods`, the ways this account can confirm.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCodesRequest"}}}},"responses":{"200":{"description":"The setting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCodesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"Confirm it’s you first (`error.code` `step_up_required`, with `error.methods`), or the request came from another site."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/email/start":{"post":{"operationId":"session_emailStart","tags":["Dashboard Auth"],"summary":"Send Sign-in Code","description":"Starts an email-code sign-in: emails a 6-digit code, valid 10 minutes, and sets the `mm_signin` cookie that `POST /auth/email/verify` needs. Sending it again sends a new code. The answer is the same whether or not the address has an account; a malformed address is `400`, and an unknown or used `invitation_token` is `404`.\n\nSSO discovery first: when the address’s domain is verified by an organization with an active SSO connection, no code is sent and `redirect_to` is that connection.\n\nWith an `invitation_token` and no `email`, the code goes to the invited address; signing in accepts the invitation.\n\n`429` also while email codes for the address are paused for this client IP (too many wrong codes from it; see `POST /auth/email/verify`), when this client IP (an IPv6 client by its /64) has had 5 new codes for the address in 15 minutes, and when the address has had 10 new codes in the last hour from any IP, counting verification codes. These limits only hold back new codes: a code already sent can still be used.\n\n`404` when email-code sign-in is not available (`GET /auth/config`).\n\nRate limited per client IP and per email address (5 codes per 15 minutes per address and client IP; 10 per hour per address): `429` with `Retry-After`.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCodeStartRequest"}}}},"responses":{"202":{"description":"Code sent (if the address can receive mail), or the SSO redirect","headers":{"Set-Cookie":{"description":"`mm_signin=<handle>; HttpOnly; SameSite=Lax; Path=/auth` (the sign-in in progress, 10 minutes), and `mm_session` once signed in.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCodeStartResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/email/verify":{"post":{"operationId":"session_emailVerify","tags":["Dashboard Auth"],"summary":"Verify Sign-in Code","description":"Checks the emailed code for the sign-in in the `mm_signin` cookie. Signed in: sets `mm_session` and `redirect_to` is `next`. The sign-in may need another step first (`signed_in: false`, `redirect_to` is our organization picker, the email verification screen or SSO).\n\nA wrong code is `400` (param `code`); after 3 wrong codes, or when the code has expired or was already used, there is no sign-in any more: `404`, send a new code. Only the newest code sent to the address works: an earlier one is `400`, and the newest works whichever browser asked for it. An invitation revoked, expired or accepted since the code was sent is `404` too. Other failures answer `redirect_to: /login?error=<code>`.\n\n`429` with `Retry-After` when the address has had 4 right codes in the last minute, or sign-in for the address is paused for a few minutes; the sign-in is kept, so the same code works once the wait is over. Wrong codes never count toward this, so guessing cannot hold the person back.\n\n`403` with `error.code` `signup_address_not_allowed` when the code is right but the address has no account yet and receives mail through MachineMail (an inbox on a MachineMail domain, or on a custom domain verified on MachineMail): new accounts need an address outside MachineMail, and the sign-in ends. An invitation from the organization that verified the custom domain is the exception. Codes are sent alike to every address, so this answer comes only to someone who proved they read the address’s mail.\n\n`403` with `error.code` `disposable_email_not_allowed` when the code is right but the address has no account yet and is a disposable email address: MachineMail doesn’t accept those for new accounts, and the sign-in ends. Like the answer above, it comes only after the code is checked; accounts that already exist sign in as before.\n\n`403` with `error.code` `mailbox_has_account` when the code is right but the address has no account yet and its mailbox already has one: one account per mailbox, and Gmail addresses with dots moved (or on googlemail.com) and `+` aliases on any domain are the same mailbox. The message names the existing account’s address, masked (`k•••@gmail.com`), to sign in with. Like the answer above, it comes only after the code is checked. Accounts made on such an address before this rule sign in as before.\n\n20 wrong codes for one address from one client IP (an IPv6 client by its /64) within 24 hours, across all codes, pause email codes for that address from that IP: this endpoint and `POST /auth/email/start` answer `429` to it until the oldest is a day old, and the address is emailed. Other IPs are not affected, so guessing cannot lock the person out of their right code.\n\nRate limited per client IP and per email address (5 attempts, then 1 per minute, per address and client IP): `429` with `Retry-After`.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCodeVerifyRequest"}}}},"responses":{"200":{"description":"Signed in, or the next step","headers":{"Set-Cookie":{"description":"`mm_signin=<handle>; HttpOnly; SameSite=Lax; Path=/auth` (the sign-in in progress, 10 minutes), and `mm_session` once signed in.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInStepResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden","description":"The request came from another site, or the code is right but would create a new account for an address that receives mail through MachineMail (`error.code` `signup_address_not_allowed`), for a disposable email address (`disposable_email_not_allowed`) or for a mailbox that already has an account (`mailbox_has_account`)."},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/first-key":{"get":{"operationId":"session_firstKey","tags":["Dashboard Auth"],"summary":"Get First API Key","description":"The organization API key created on first sign-in, with its plaintext secret. Returned once: the record is deleted on read and expires 10 minutes after sign-in; `404` afterwards.","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"The key, shown once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirstKeyResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/invitations/{token}":{"get":{"operationId":"session_invitation","tags":["Dashboard Auth"],"summary":"Preview Invitation","description":"What an invitation link (`/invite/{token}`) is for: the organization, the invited address (masked) and the state. Accept it by signing in with `invitation_token` (`POST /auth/email/start` or `GET /auth/social/{provider}`). `404` for an unknown token. An expired, revoked or already accepted invitation is a `200` with that `state`. `429` with `Retry-After` when the lookup is rate limited, or cannot be answered right now (an outage): retry after that many seconds.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"The token from the invitation link (`/invite/{token}`).","name":"token","in":"path"}],"responses":{"200":{"description":"The invitation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationPreviewResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/login":{"post":{"operationId":"session_login","tags":["Dashboard Auth"],"summary":"Log In (Deprecated)","description":"Deprecated: the dashboard signs in with an email code (`POST /auth/email/start`). Sets the `mm_session` cookie.\n\nNot available: `404`.\n\nRate limited per client IP and per email address (5 attempts, then 1 per minute; a successful sign-in resets the address): `429` with `Retry-After`.","deprecated":true,"security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Signed in","headers":{"Set-Cookie":{"description":"`mm_session=<token>; HttpOnly; SameSite=Lax; Path=/` (plus `Secure` on https).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/logout":{"post":{"operationId":"session_logout","tags":["Dashboard Auth"],"summary":"Log Out","description":"Ends the session in the `mm_session` cookie, if any, and clears the cookie. Succeeds without a session too.","security":[],"x-machinemail":true,"responses":{"200":{"description":"Signed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/magic":{"get":{"operationId":"session_magic","tags":["Dashboard Auth"],"summary":"Redeem Magic Link","description":"The link in the sign-in email. Consumes the token (single use), sets the `mm_session` cookie and redirects to `next` (default `/app`). On a first sign-in it creates the user, an organization, a Default Pod and a first organization API key, and adds `welcome=1` to the redirect; fetch that key once with `GET /auth/first-key`.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"The token from the emailed link. A missing, unknown, used or expired token redirects to `/login?error=expired`.","name":"token","in":"query"}],"responses":{"302":{"description":"Signed in: `Location` is `next` and `Set-Cookie` carries `mm_session`. Otherwise `Location` is `/login?error=expired`, `/login?error=address_not_allowed` when the link would create an account for an address that receives mail through MachineMail, `/login?error=disposable_address` when it would create one for a disposable email address, or `/login?error=mailbox_has_account&account=<masked address>` (with `&invited=1` for an invitation) when the address’s mailbox already has an account.","headers":{"Location":{"description":"Where to go next.","schema":{"type":"string"}},"Set-Cookie":{"description":"`mm_session=<token>; HttpOnly; SameSite=Lax; Path=/` (plus `Secure` on https).","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/magic-link":{"post":{"operationId":"session_magicLink","tags":["Dashboard Auth"],"summary":"Request Magic Link","description":"Not available on MachineMail, which uses email-code sign-in: returns `404`. Sign in with an email code instead (`POST /auth/email/start`).\n\nRate limited per client IP and per email address (5 links per 15 minutes per address): `429` with `Retry-After`.","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkRequest"}}}},"responses":{"202":{"description":"Accepted. The link was sent if the address can receive mail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MagicLinkResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/me":{"get":{"operationId":"session_me","tags":["Dashboard Auth"],"summary":"Current User","description":"The signed-in user and the organization the session is on; `user.role` is their role there. For what an API key can see, use `GET /v0/auth/me`.","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"The session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/oauth/authorize":{"get":{"operationId":"session_oauthPreview","tags":["Dashboard Auth"],"summary":"Preview App Authorization","description":"Called by the dashboard `/connect` page for a signed-in person. Returns the client (its name and logo are self-reported unless it identified itself with a metadata document URL), where the response goes, the resource and the requested scopes. `404` for an unknown, decided or expired request. Dashboard session only: API keys are not accepted.","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"The `request` parameter of the `/connect` page URL.","name":"request_id","in":"query"}],"responses":{"200":{"description":"The pending request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthAuthorizationRequest"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/oauth/authorize/approve":{"post":{"operationId":"session_oauthApprove","tags":["Dashboard Auth"],"summary":"Approve App Authorization","description":"Approves a pending request for the organization the session is signed in to, optionally limited to one pod or one inbox of it, and returns `redirect_to` (the client’s `redirect_uri` with `code`, `state` and `iss`) for the browser to follow. The app then appears under Connected apps (`/v0/oauth-grants`). Dashboard session only.\n\nA person in several organizations connects the app to another one by switching the session to it first (`POST /auth/organizations/switch`, which applies that organization’s sign-in policy), then approving. `organization_id` names the organization the page showed: `409 conflict` when the session is no longer on it. A `pod_id` or `inbox_id` outside the session’s organization is `404`.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthApproveRequest"}}}},"responses":{"200":{"description":"Approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthDecision"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/oauth/authorize/deny":{"post":{"operationId":"session_oauthDeny","tags":["Dashboard Auth"],"summary":"Deny App Authorization","description":"Denies a pending request and returns `redirect_to` (the client’s `redirect_uri` with `error=access_denied`, `state` and `iss`). Dashboard session only.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthDenyRequest"}}}},"responses":{"200":{"description":"Denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthDecision"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/organizations":{"get":{"operationId":"session_listOrganizations","tags":["Dashboard Auth"],"summary":"List My Organizations","description":"Every organization the signed-in person belongs to, with their role, for the organization switcher.","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"Organizations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSessionOrganizationsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"session_createOrganization","tags":["Dashboard Auth"],"summary":"Create Organization","description":"Creates an organization (with its Default Pod) owned by the signed-in person, and switches the session to it.\n\n`403` with `error.code` `signup_address_not_allowed` when the person’s email address receives mail through MachineMail (someone an organization invited on a custom domain it verified): they can belong to organizations that invite them, but not create one.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionOrganizationRequest"}}}},"responses":{"201":{"description":"Created; the session is on the new organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"An account can own one Free organization, and this one already does (`limit_key: \"free_organizations\"`). Upgrade it, or contact support@machinemail.dev."},"403":{"$ref":"#/components/responses/Forbidden","description":"The person’s address receives mail through MachineMail (`error.code` `signup_address_not_allowed`), or an organization they belong to is suspended (`account_suspended`)."},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/organizations/switch":{"post":{"operationId":"session_switchOrganization","tags":["Dashboard Auth"],"summary":"Switch Organization","description":"Moves the session to another organization the person belongs to. `404` when they do not belong to it.\n\nAn organization other than the one the session signed in to must allow how the session signed in, under its own sign-in policy. A sign-in that has expired with the sign-in service (sessions here can outlast it) still switches to any organization that does not use single sign-on.\n\n`403` with `error.code` `sso_required` when the organization uses single sign-on and the session did not sign in with it: send the browser to `GET /auth/sso?organization_id=…`, which signs in through the organization’s single sign-on and lands on it. `403` with `error.code` `sign_in_required` when the organization allows only other sign-in methods, or the sign-in could not be confirmed for it: sign in to it again.\n\n`429` when the sign-in service could not be reached, or another request changed the session at the same time: retry after `Retry-After`. The session stays where it was.","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwitchOrganizationRequest"}}}},"responses":{"200":{"description":"The session, on the organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"The organization needs another sign-in: single sign-on (`error.code` `sso_required`), or another method (`sign_in_required`)."},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkey/options":{"post":{"operationId":"session_passkeyOptions","tags":["Dashboard Auth"],"summary":"Start Passkey Sign-in","description":"Starts a passkey sign-in: returns the options for the browser’s WebAuthn API (no address needed: the browser offers the person’s passkeys for MachineMail, also as autofill on the email field) and sets the `mm_passkey` cookie that `POST /auth/passkey/verify` needs. The challenge works once, for 5 minutes; ask again for a new one.\n\n`404` when passkey sign-in is not available (`GET /auth/config`).\n\nRate limited per client IP: `429` with `Retry-After`.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeySignInOptionsRequest"}}}},"responses":{"200":{"description":"Options for the browser","headers":{"Set-Cookie":{"description":"`mm_passkey=<handle>; HttpOnly; SameSite=Lax; Path=/auth` (this browser’s passkey sign-ins, 5 minutes; kept across requests, so several tabs can sign in at once).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyOptionsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkey/verify":{"post":{"operationId":"session_passkeyVerify","tags":["Dashboard Auth"],"summary":"Sign In with a Passkey","description":"Checks the browser’s passkey assertion against the challenge it signed, which must have been issued to this browser (the `mm_passkey` cookie); the challenge is used up either way. Signed in: sets `mm_session` and `redirect_to` is `next`. The sign-in may need another step first (`signed_in: false`, `redirect_to` is the organization picker or single sign-on), as for `POST /auth/email/verify`; other failures answer `redirect_to: /login?error=<code>`.\n\nA passkey MachineMail no longer knows (removed from the account) is `400` with `error.code` `passkey_unknown` and `error.credential_id`: tell the browser it is gone (`PublicKeyCredential.signalUnknownCredential`) and ask the person to remove it from their password manager. Any other passkey that does not check out is `400` with `error.code` `passkey_invalid`. No challenge, or an expired one, is `404`: start again.\n\n`429` with `Retry-After` when the address has had 4 passkey sign-ins in the last minute, or sign-in for it is paused for a few minutes.\n\nRate limited per client IP.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyCredentialRequest"}}}},"responses":{"200":{"description":"Signed in, or the next step","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInStepResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkeys":{"get":{"operationId":"session_listPasskeys","tags":["Dashboard Auth"],"summary":"List My Passkeys","description":"The signed-in person’s passkeys, whether email sign-in codes are on, how to confirm it’s them before sensitive changes, and whether to offer creating a passkey.\n\n`404` when passkeys are not available to this account.","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"Passkeys and settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPasskeysResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"session_registerPasskey","tags":["Dashboard Auth"],"summary":"Add a Passkey","description":"Adds the passkey the browser created from `POST /auth/passkeys/registration` (within 5 minutes, on the same session; `404` otherwise). User verification (a device PIN, fingerprint or face) is required. A passkey already on an account is `409`; one that does not check out is `400`. The account’s address gets an email saying a passkey was added.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterPasskeyRequest"}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Passkey"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkeys/prompt":{"post":{"operationId":"session_passkeyPrompt","tags":["Dashboard Auth"],"summary":"Answer the Passkey Offer","description":"“Not now” (ask again in 14 days) or “Don’t ask again” on the offer to create a passkey.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyPromptRequest"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkeys/registration":{"post":{"operationId":"session_passkeyRegistrationOptions","tags":["Dashboard Auth"],"summary":"Start Adding a Passkey","description":"Options for the browser to create a passkey for this account (`navigator.credentials.create()`). Finish within 5 minutes with `POST /auth/passkeys`, on this session. An account can have 20 passkeys (`409` past that).\n\nNeeds a recent sign-in: within 10 minutes of signing in, or of confirming it’s you on this session (`POST /auth/step-up/email/verify` or `POST /auth/step-up/passkey/verify`). Otherwise `403` with `error.code` `step_up_required` and `error.methods`, the ways this account can confirm.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"Options for the browser","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyRegistrationOptionsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"Confirm it’s you first (`error.code` `step_up_required`, with `error.methods`), or the request came from another site."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/passkeys/{passkey_id}":{"patch":{"operationId":"session_renamePasskey","tags":["Dashboard Auth"],"summary":"Rename a Passkey","description":"Renames one of the signed-in person’s passkeys (1 to 64 characters).\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the passkey (`pk_…`).","name":"passkey_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenamePasskeyRequest"}}}},"responses":{"200":{"description":"Renamed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Passkey"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"session_removePasskey","tags":["Dashboard Auth"],"summary":"Remove a Passkey","description":"Removes one of the signed-in person’s passkeys and signs out every session it signed in (this one too, when it did: `signed_out`). The account’s address gets an email saying so.\n\n`409` for the last passkey while email sign-in codes are off: turn them on first (`PUT /auth/email-codes`), or add another passkey.\n\nNeeds a recent sign-in: within 10 minutes of signing in, or of confirming it’s you on this session (`POST /auth/step-up/email/verify` or `POST /auth/step-up/passkey/verify`). Otherwise `403` with `error.code` `step_up_required` and `error.methods`, the ways this account can confirm.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the passkey (`pk_…`).","name":"passkey_id","in":"path"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePasskeyResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"Confirm it’s you first (`error.code` `step_up_required`, with `error.methods`), or the request came from another site."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/pending":{"get":{"operationId":"session_pending","tags":["Dashboard Auth"],"summary":"Get Sign-in in Progress","description":"The sign-in in progress in this browser (`mm_signin` cookie), for the code, organization picker and email verification screens. `404` when there is none or it expired.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The sign-in in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingSignInResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/pending/organization":{"post":{"operationId":"session_pendingOrganization","tags":["Dashboard Auth"],"summary":"Choose Organization","description":"Finishes a sign-in that needs an organization picked (`organization_selection_required`) with one of the organizations offered (`GET /auth/pending`); any other ID is `400`.\n\n`403` with `error.code` `signup_address_not_allowed` when this step would create a new account for an address that receives mail through MachineMail, `disposable_email_not_allowed` when it would create one for a disposable email address, or `mailbox_has_account` when the address’s mailbox already has an account, as for `POST /auth/email/verify`. Existing accounts are not affected.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingOrganizationRequest"}}}},"responses":{"200":{"description":"Signed in, or the next step","headers":{"Set-Cookie":{"description":"`mm_signin=<handle>; HttpOnly; SameSite=Lax; Path=/auth` (the sign-in in progress, 10 minutes), and `mm_session` once signed in.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInStepResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden","description":"The request came from another site, or this step would create a new account for an address that receives mail through MachineMail (`error.code` `signup_address_not_allowed`), for a disposable email address (`disposable_email_not_allowed`) or for a mailbox that already has an account (`mailbox_has_account`)."},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/pending/verify":{"post":{"operationId":"session_pendingVerify","tags":["Dashboard Auth"],"summary":"Verify Email","description":"Finishes a sign-in that needs the email verified (`email_verification_required`, for example a GitHub account whose email GitHub does not vouch for) with the code emailed to that address. Wrong codes as for `POST /auth/email/verify`. Each such sign-in is a new code for the address, counted with email codes (`POST /auth/email/start`): past those limits the callback goes to `/login?error=codes_paused` and no code is sent.\n\n`403` with `error.code` `signup_address_not_allowed` when this step would create a new account for an address that receives mail through MachineMail, `disposable_email_not_allowed` when it would create one for a disposable email address, or `mailbox_has_account` when the address’s mailbox already has an account, as for `POST /auth/email/verify`. Existing accounts are not affected.\n\nRate limited per client IP and per email address (5 attempts, then 1 per minute, per address and client IP): `429` with `Retry-After`.\n\nA request whose `Origin` is another site is refused (`403`).","security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingVerifyRequest"}}}},"responses":{"200":{"description":"Signed in, or the next step","headers":{"Set-Cookie":{"description":"`mm_signin=<handle>; HttpOnly; SameSite=Lax; Path=/auth` (the sign-in in progress, 10 minutes), and `mm_session` once signed in.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInStepResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden","description":"The request came from another site, or this step would create a new account for an address that receives mail through MachineMail (`error.code` `signup_address_not_allowed`), for a disposable email address (`disposable_email_not_allowed`) or for a mailbox that already has an account (`mailbox_has_account`)."},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/sessions/revoke-others":{"post":{"operationId":"session_revokeOtherSessions","tags":["Dashboard Auth"],"summary":"Sign Out Other Sessions","description":"Signs the person out of every session except this one, on every device.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"Signed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeOtherSessionsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/signup":{"post":{"operationId":"session_signup","tags":["Dashboard Auth"],"summary":"Sign Up (Deprecated)","description":"Deprecated: the dashboard signs in with an email code (`POST /auth/email/start`). Creates a user, an organization, a Default Pod and a first organization API key (returned once as `api_key`), and sets the `mm_session` cookie.\n\nIt does not verify the email address, so it is not available: `404`.\n\nA taken address and a password shorter than 8 characters both answer `409` with the same message.\n\nRate limited per client IP and per email address (5 attempts, then 1 per minute): `429` with `Retry-After`.","deprecated":true,"security":[],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}}},"responses":{"201":{"description":"Signed up and signed in","headers":{"Set-Cookie":{"description":"`mm_session=<token>; HttpOnly; SameSite=Lax; Path=/` (plus `Secure` on https).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"403":{"$ref":"#/components/responses/Forbidden","description":"This would create a new account for an address that receives mail through MachineMail (`error.code` `signup_address_not_allowed`): new accounts need an email address outside MachineMail. Or for a disposable email address (`disposable_email_not_allowed`): MachineMail doesn’t accept those."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/social/{provider}":{"get":{"operationId":"session_social","tags":["Dashboard Auth"],"summary":"Sign In with a Social Provider","description":"Sends the browser straight to Google, GitHub, Apple or Microsoft (no page in between), with a single-use `state` bound to this browser by a short-lived cookie (`mm_oauth_state`, `Path=/auth/callback`). The provider returns to `GET /auth/callback`.\n\n`404` when that provider is not offered (`GET /auth/config` lists them).","security":[],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/SocialProvider"},"required":true,"description":"A social sign-in provider.","name":"provider","in":"path"},{"schema":{"type":"string"},"required":false,"description":"Same-origin path to land on after sign-in. Default `/app`.","name":"next","in":"query"},{"schema":{"type":"string"},"required":false,"description":"An invitation token (from `/invite/{token}`): signing in accepts that invitation.","name":"invitation_token","in":"query"}],"responses":{"302":{"description":"To the provider.","headers":{"Location":{"description":"Where to go next.","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/sso":{"get":{"operationId":"session_organizationSso","tags":["Dashboard Auth"],"summary":"Sign In to an Organization with SSO","description":"Where the dashboard sends the browser when switching to an organization answers `sso_required`: straight to that organization’s single sign-on (no page in between), under a single-use `state` bound to this browser (`mm_oauth_state`, as for `GET /auth/social/{provider}`). Back at `GET /auth/callback`, the session is on that organization.\n\nNeeds a signed-in session and membership in the organization: without a session, redirects to `/login`. `404` when the person does not belong to the organization. An organization with no single sign-on (any more) redirects to `next`, on the organization the session is on: switch again from there.","security":[{"SessionCookie":[]}],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"ID of an organization the signed-in person belongs to.","name":"organization_id","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Same-origin path to land on after sign-in. Default `/app`.","name":"next","in":"query"}],"responses":{"302":{"description":"To the organization’s single sign-on, `/login` without a session, or `next` when the organization has no single sign-on.","headers":{"Location":{"description":"Where to go next.","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/step-up/email":{"post":{"operationId":"session_stepUpEmail","tags":["Dashboard Auth"],"summary":"Email a Confirmation Code","description":"Emails a 6-digit code (10 minutes, 3 tries) that confirms it’s the signed-in person before a sensitive change; check it with `POST /auth/step-up/email/verify`. A new code replaces the last. `409` while email codes are off for the account: confirm with a passkey. `429` after 3 codes in an hour.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"202":{"description":"Code sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpEmailResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/step-up/email/verify":{"post":{"operationId":"session_stepUpEmailVerify","tags":["Dashboard Auth"],"summary":"Confirm with an Emailed Code","description":"Checks the code from `POST /auth/step-up/email` for this session. Right: sensitive changes need no further confirmation for 10 minutes (`recent_until`). A wrong code is `400` (param `code`), and the third ends the code: send a new one.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpEmailVerifyRequest"}}}},"responses":{"200":{"description":"Confirmed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/step-up/passkey/options":{"post":{"operationId":"session_stepUpPasskeyOptions","tags":["Dashboard Auth"],"summary":"Start Confirming with a Passkey","description":"Options for the browser to confirm it’s the signed-in person with one of their passkeys (5 minutes). `409` when they have none.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"responses":{"200":{"description":"Options for the browser","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyOptionsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/auth/step-up/passkey/verify":{"post":{"operationId":"session_stepUpPasskeyVerify","tags":["Dashboard Auth"],"summary":"Confirm with a Passkey","description":"Checks the browser’s passkey assertion against `POST /auth/step-up/passkey/options` (on this session). It must be one of the signed-in person’s passkeys. Confirmed: sensitive changes need no further confirmation for 10 minutes (`recent_until`). Errors as for `POST /auth/passkey/verify`.\n\n`404` when passkeys are not available to this account.\n\nA request whose `Origin` is another site is refused (`403`).","security":[{"SessionCookie":[]}],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasskeyCredentialRequest"}}}},"responses":{"200":{"description":"Confirmed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/health":{"get":{"operationId":"health_get","tags":["Health"],"summary":"Liveness","description":"Always `200 {\"status\": \"ok\"}` while the process serves requests. No authentication.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The process is up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/health/ready":{"get":{"operationId":"health_ready","tags":["Health"],"summary":"Readiness","description":"Pings the storage backend: `200` with `status: ready` (`checks.storage: true`) when it answers, `503` with `status: unavailable` when it does not. No authentication.","security":[],"x-machinemail":true,"responses":{"200":{"description":"Ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadyResponse"}}}},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Not ready: storage did not answer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadyResponse"}}}}}}},"/inbound/raw":{"post":{"operationId":"inbound_raw","tags":["Inbound"],"summary":"Inject Raw Message","description":"Stores a raw RFC 5322 message (the request body, any Content-Type, at most 40 MB) as if it had been received, once per recipient inbox in the credential’s scope. The recipient is `X-Recipient`, otherwise every To and Cc address.\n\nInjected messages are marked `received_via: \"raw\"`. Their trust report never believes the authentication results they carry (headers and provider verdicts are ignored): authentication is `none`, so the trust level is at most `unknown`.\n\nAn unrestricted key (`*`) does not imply `inbound_raw`; it must be granted by name.\n\nInjected mail counts toward plan limits like any other inbound mail, even when the trust layer marks it spam or quarantined (its content is yours). On the Free plan, a copy past the monthly or daily allowance (or past storage) is held: it is listed in `held`, not in `messages`, and delivered when the allowance resets or after an upgrade.\n\nRequires the `inbound_raw` permission.","x-permission":["inbound_raw"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"Recipient address. Defaults to the To and Cc addresses of the message.","name":"X-Recipient","in":"header"}],"requestBody":{"required":true,"content":{"message/rfc822":{"schema":{"type":"string","format":"binary","description":"The message bytes."}}}},"responses":{"201":{"description":"Stored (or held)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRawResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: this organization already holds as much undelivered mail as it may (`limit_key: \"held_messages\"`, or `\"held_bytes\"` when the size cap binds: then `limit` and `used` are bytes); the message was not stored."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/mcp":{"get":{"operationId":"mcp_get","servers":[{"url":"https://mcp.machinemail.dev","description":"MCP server; `https://machinemail.dev/mcp` is a legacy alias"}],"tags":["MCP"],"summary":"MCP Description or Stream","description":"Without `Accept: text/event-stream` (a browser, for example): the server description, no authentication. With it, this would be the standalone MCP server-to-client stream; the server is stateless and has none, so an authenticated request answers `405` (use POST) and an unauthenticated one `401` with the `WWW-Authenticate` challenge. `HEAD` needs a valid token whatever the `Accept` (`401` with the challenge otherwise), so clients can probe for the challenge.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The server description","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDescription"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"405":{"description":"Stateless server: no standalone stream.","headers":{"Allow":{"description":"`POST`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"mcp_post","servers":[{"url":"https://mcp.machinemail.dev","description":"MCP server; `https://machinemail.dev/mcp` is a legacy alias"}],"tags":["MCP"],"summary":"MCP JSON-RPC (Streamable HTTP)","description":"MachineMail as a remote MCP server over Streamable HTTP, stateless: send one JSON-RPC message per request with `Authorization: Bearer` set to an API key, an OAuth access token for the MCP server (`aud` `https://mcp.machinemail.dev/mcp`, `https://machinemail.dev/mcp` or `https://machinemail.dev/`) or an auth.md access token (the session cookie is not accepted). Every request is served independently; there is no `Mcp-Session-Id`.\n\nThe canonical URL is `https://mcp.machinemail.dev/mcp`; `https://machinemail.dev/mcp` is the same server, kept as a legacy alias.\n\nWithout a valid token the answer is `401` with `WWW-Authenticate: Bearer resource_metadata=\"<origin>/.well-known/oauth-protected-resource/mcp\", scope=\"...\"` on the host the request came to (plus `error=\"invalid_token\"` when a token was sent): MCP clients follow it to the authorization server and sign the person in with OAuth (authorization code with PKCE).\n\nProtocol 2026-07-28 (per-request `_meta`, `server/discover`), with stateless fallback for 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05 clients (`initialize`). The tools act with the credential’s scope and permissions. Bodies over 2 MiB are rejected.\n\nResponses are JSON, or `text/event-stream` when the client accepts it; protocol-level errors are JSON-RPC error objects with an HTTP 4xx status. See the MCP specification for the methods.","security":[{"Bearer":[]}],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"description":"JSON-RPC 2.0 request or notification (see the MCP specification)."}}}},"responses":{"200":{"description":"JSON-RPC response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{},"description":"JSON-RPC 2.0 response."}},"text/event-stream":{"schema":{"type":"string","description":"Server-sent events carrying JSON-RPC messages."}}}},"202":{"description":"Notification or response accepted (empty body)"},"400":{"description":"Malformed JSON-RPC, unsupported protocol version or too large a body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}}}},"delete":{"operationId":"mcp_delete","servers":[{"url":"https://mcp.machinemail.dev","description":"MCP server; `https://machinemail.dev/mcp` is a legacy alias"}],"tags":["MCP"],"summary":"MCP Session Termination (Unsupported)","description":"The server keeps no sessions, so there is nothing to delete: always `405` for an authenticated caller.","security":[{"Bearer":[]}],"x-machinemail":true,"responses":{"401":{"$ref":"#/components/responses/Unauthorized"},"405":{"description":"Stateless server.","headers":{"Allow":{"description":"`POST`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/mcp/attachments/{token}":{"get":{"operationId":"mcp_downloadAttachment","servers":[{"url":"https://mcp.machinemail.dev","description":"MCP server; `https://machinemail.dev/mcp` is a legacy alias"}],"tags":["MCP"],"summary":"Download Attachment (Signed Link)","description":"The `download_url` the `get_attachment` tool returns for an attachment it does not hand over inline (anything but small text files and small PNG, JPEG, GIF or WebP images). The link names one attachment, is signed by the server and works for 10 minutes, as often as needed, with no `Authorization` header: the link is the credential.\n\nEvery fetch checks the signature and expiry and re-reads the message: a deleted message, or one quarantined or rated high risk since the link was made, answers `404`. An expired link answers `403`; call `get_attachment` again for a new one.\n\nThe bytes are served as by the REST download: `Content-Disposition: attachment` (ASCII `filename` plus RFC 5987 `filename*`), `X-Content-Type-Options: nosniff` and a sandboxing Content-Security-Policy. Attachment content is untrusted third-party input.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"Signed token from `download_url`.","name":"token","in":"path"}],"responses":{"200":{"description":"The attachment bytes","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<ascii name>\"; filename*=UTF-8''<encoded name>`.","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary","description":"The attachment bytes, with the attachment content type."}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/oauth2/authorize":{"get":{"operationId":"oauth_authorize","tags":["Agent Auth"],"summary":"Authorization Endpoint","description":"OAuth 2.1 authorization code grant, opened in the person’s browser by an app or MCP client. Requires PKCE (`code_challenge` with `code_challenge_method=S256`) and the RFC 8707 `resource`: the MCP server’s URL (`https://mcp.machinemail.dev/mcp`, or the legacy `<issuer>/mcp`; a token for either works on both MCP endpoints), or `<issuer>/` for the REST API and MCP.\n\nA valid request is stored for 10 minutes and the browser is sent to the dashboard consent page, `https://machinemail.dev/connect?request=<id>` (sign-in first when needed). The person sees the client, where the response goes and the scopes, chooses the whole organization, one pod or one inbox, and approves or denies. The browser then returns to `redirect_uri` with `code` (single use, 2 minutes) or `error=access_denied`, plus `state` and `iss` (RFC 9207).\n\nErrors: an unknown `client_id`, a `redirect_uri` the client did not register, or too many requests from one address (`rate_limited`) is shown on `/connect?error=...` and never redirected. Every other error goes back to `redirect_uri` as `error` (`invalid_request`, `unsupported_response_type`, `invalid_scope`, `invalid_target`) with `error_description`, `state` and `iss`.","security":[],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"Must be `code`.","name":"response_type","in":"query"},{"schema":{"type":"string"},"required":false,"description":"From registration (`oac_...`), or an `https` URL of a Client ID Metadata Document.","name":"client_id","in":"query"},{"schema":{"type":"string"},"required":false,"description":"One of the client’s redirect URIs. May be omitted when the client registered exactly one.","name":"redirect_uri","in":"query"},{"schema":{"type":"string"},"required":false,"description":"PKCE (RFC 7636): base64url SHA-256 of the code verifier, 43 characters. Required.","name":"code_challenge","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Must be `S256`.","name":"code_challenge_method","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Space-separated `Scope` values. Default: every scope the client may ask for. `offline_access` is accepted and ignored (refresh tokens are always issued); other unknown values are dropped, and a list of only unknown values counts as the default.","name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Returned unchanged with the response.","name":"state","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"required":false,"description":"RFC 8707 resource indicator: the MCP server’s URL (`https://mcp.machinemail.dev/mcp`, from its protected resource metadata; the legacy `<issuer>/mcp` and the MCP host’s origin are also accepted), or `<issuer>/` (the REST API and MCP). Default (omitted): the MCP server. May be repeated when every value names the same resource (a token has one audience).","name":"resource","in":"query"}],"responses":{"302":{"description":"To the consent page, to `redirect_uri` with an error, or to the error page.","headers":{"Location":{"description":"`https://machinemail.dev/connect?request=...`, `<redirect_uri>?error=...&state=...&iss=...` or `https://machinemail.dev/connect?error=...`.","schema":{"type":"string"}},"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/oauth2/register":{"post":{"operationId":"oauth_register","tags":["Agent Auth"],"summary":"Register OAuth Client","description":"RFC 7591 Dynamic Client Registration for apps and MCP clients. Public clients by default (`token_endpoint_auth_method` `none`, no secret). A client that asks for `client_secret_post` or `client_secret_basic` is confidential: the response carries its `client_secret` (shown once, never expires: `client_secret_expires_at` `0`) and the token and revocation endpoints then require it, by either method. Any other method is replaced with `none`. Every authorization uses PKCE, confidential or not. No registration access token is issued (registrations cannot be read or changed later; register again instead).\n\nClients that can host a Client ID Metadata Document should use its https URL as `client_id` instead of registering (`client_id_metadata_document_supported` in the server metadata). Registrations never used for an authorization are deleted after 7 days.\n\nRate limited per client IP and overall: `429 rate_limited` with `Retry-After`.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationRequest"}}}},"responses":{"201":{"description":"Registered","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationResponse"}}}},"400":{"description":"OAuth error `invalid_redirect_uri` or `invalid_client_metadata` (RFC 7591 section 3.2.2), including a body that fails validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"OAuth error `rate_limited`.","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/oauth2/revoke":{"post":{"operationId":"agentAuth_revoke","tags":["Agent Auth"],"summary":"Revoke Token","description":"RFC 7009. Idempotent: unknown tokens succeed too. Revoking an access token ends only that token; revoking a refresh token ends its whole grant (the app is disconnected); revoking an identity assertion (tried first with `token_type_hint=identity_assertion`) revokes the whole registration. A confidential client that names itself authenticates as at the token endpoint (`401 invalid_client` otherwise). Form-encoded or JSON bodies.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/RevokeRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/RevokeRequest"}}}},"responses":{"200":{"description":"Revoked (empty body)"},"400":{"description":"OAuth error `invalid_request`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"OAuth error `invalid_client`: a confidential client sent no or a wrong `client_secret`.","headers":{"WWW-Authenticate":{"description":"`Basic realm=\"MachineMail\"` when the client authenticated with HTTP Basic.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/oauth2/token":{"post":{"operationId":"agentAuth_token","tags":["Agent Auth"],"summary":"Token Endpoint","description":"The token endpoint of the MachineMail authorization server. Public clients (`token_endpoint_auth_method` `none`: URL client IDs and registrations without a secret) send `client_id` in the body. Confidential clients (registered with `client_secret_post` or `client_secret_basic`) authenticate with HTTP Basic or `client_secret` in the body, either way; a missing or wrong secret is `401 invalid_client`. PKCE applies to every client.\n\n`authorization_code` redeems a code from `/oauth2/authorize` with its PKCE `code_verifier` and returns an access token bound to the requested `resource` and a `refresh_token`. `refresh_token` returns a new access token and a new refresh token, and the old one stops working: presenting it again within 60 seconds returns the same new refresh token (concurrent refreshes and retries are safe), later it revokes the whole grant (reuse detection). A code redeemed twice also revokes its grant.\n\n`urn:ietf:params:oauth:grant-type:device_code` is the `mm login` device grant (same as `/auth/cli/device/token`; the response is a `CliDeviceTokenResponse` with an API key).\n\n`urn:ietf:params:oauth:grant-type:jwt-bearer` (RFC 7523) exchanges an auth.md `identity_assertion` for an access token. `urn:workos:agent-auth:grant-type:claim` is polled with a `claim_token` until the human finishes the claim, then returns an access token and the post-claim `identity_assertion`.\n\nForm-encoded (RFC 6749) or JSON bodies.","security":[],"x-machinemail":true,"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Access token (an API key for the device grant)","headers":{"Cache-Control":{"description":"`no-store`","schema":{"type":"string"}},"Pragma":{"description":"`no-cache`","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TokenResponse"},{"$ref":"#/components/schemas/CliDeviceTokenResponse"}]}}}},"400":{"description":"OAuth error: `invalid_request`, `unsupported_grant_type`, `invalid_grant`, `invalid_target`, `invalid_scope` (authorization_code, refresh_token, jwt-bearer); `authorization_pending`, `slow_down`, `expired_token`, `access_denied` (claim and device grants).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"OAuth error `invalid_client`: a confidential client sent no or a wrong `client_secret` (with `WWW-Authenticate: Basic` when it used HTTP Basic), `client_id` does not match the assertion (jwt-bearer), or is not `machinemail-cli` (device grant).","headers":{"WWW-Authenticate":{"description":"`Basic realm=\"MachineMail\"` when the client authenticated with HTTP Basic.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/agent-registrations":{"get":{"operationId":"agentRegistrations_list","tags":["Agent Registrations"],"summary":"List Agent Registrations","description":"Agent registrations bound to the organization. Requires an organization-scoped credential with `api_key_read`; pod, inbox and sandbox credentials get `403`.","x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"string","enum":["pending_claim","claimed","revoked"]},"required":false,"description":"Only registrations with this status.","name":"status","in":"query"}],"responses":{"200":{"description":"A page of registrations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAgentRegistrationsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/agent-registrations/{agent_id}":{"get":{"operationId":"agentRegistrations_get","tags":["Agent Registrations"],"summary":"Get Agent Registration","description":"Requires an organization-scoped credential with `api_key_read`.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the registration.","name":"agent_id","in":"path"}],"responses":{"200":{"description":"The registration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRegistration"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"agentRegistrations_delete","tags":["Agent Registrations"],"summary":"Revoke Agent Registration","description":"Revokes the registration; its tokens stop working immediately. Returns the registration with `status: revoked` (revoking twice is not an error). Requires an organization-scoped credential with `api_key_delete`.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the registration.","name":"agent_id","in":"path"}],"responses":{"200":{"description":"The revoked registration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRegistration"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/api-keys":{"get":{"operationId":"apiKeys_list","tags":["API Keys"],"summary":"List API Keys","description":"Keys that are not revoked. Under `/v0/pods/{pod_id}` or `/v0/inboxes/{inbox_id}`, only the keys scoped to that pod or inbox; a pod or inbox credential sees only keys in its own scope.\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"parameters":[{"schema":{"type":"string","enum":["bearer","public_key"]},"required":false,"description":"Only this credential family. Every key is `bearer`, so `public_key` returns an empty list.","name":"type","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_ListApiKeysResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"apiKeys_create","tags":["API Keys"],"summary":"Create API Key","description":"The route sets the scope of the new key: `POST /v0/api-keys` makes an organization key, `POST /v0/pods/{pod_id}/api-keys` a pod key, `POST /v0/inboxes/{inbox_id}/api-keys` an inbox key.\n\nOnly organization-scoped credentials (and dashboard sessions) can create keys, and only with permissions they have themselves (`403`). `api_key` is returned once.\n\n`expires_at` makes a key that stops working at that time (`401` after it). A key created with an expiring API key never outlives it.\n\nRequires the `api_key_create` permission.","x-permission":["api_key_create"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateBearerApiKeyRequest"}}}},"responses":{"201":{"description":"Created. `api_key` is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateApiKeyResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/api-keys/{api_key_id}":{"get":{"operationId":"apiKeys_get","tags":["API Keys"],"summary":"Get API Key","description":"Also returns revoked keys (with `revoked_at`).\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"The key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"apiKeys_update","tags":["API Keys"],"summary":"Update API Key","description":"Rename a key or replace its permissions. Only organization-scoped credentials (and dashboard sessions) can update keys, and cannot grant permissions they lack (`403`).\n\nRequires the `api_key_update` permission.","x-permission":["api_key_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_UpdateApiKeyRequest"}}}},"responses":{"200":{"description":"The updated key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"apiKeys_delete","tags":["API Keys"],"summary":"Delete API Key","description":"Revokes the key: it stops working immediately. The record is kept (with `revoked_at`) and no longer listed.\n\nRequires the `api_key_delete` permission.","x-permission":["api_key_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/auth/me":{"get":{"operationId":"auth_me","tags":["Auth"],"summary":"Who Am I","description":"The identity and scope of the credential: which organization, pod and inbox it is bound to. Useful with a pod or inbox key to discover its scope.","responses":{"200":{"description":"The credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/auth_Identity"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/domains":{"get":{"operationId":"domains_list","tags":["Domains"],"summary":"List Domains","description":"Requires the `domain_read` permission.","x-permission":["domain_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_ListDomainsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"domains_create","tags":["Domains"],"summary":"Create Domain","description":"Registers the domain and returns the DNS records to publish (`status: NOT_STARTED`). Publish them, then call Verify Domain. A background worker re-checks `PENDING`, `INVALID` and `VERIFYING` domains about every 5 minutes until 7 days after creation; a `NOT_STARTED` domain is only checked by Verify Domain. A domain that is never verified is removed 14 days after it was added, together with its inboxes and the mail in them; owners and admins of the organization are emailed at least 3 days before. A domain that was verified once is never removed this way.\n\nA domain can be registered by one organization only (`409`), and the shared domain cannot be added (`409`). Inbox-scoped credentials cannot add domains (`403`).\n\n`allow_conflicting_provider`, `subdomains_enabled` and `tracking_enabled` are not supported.\n\n`502 upstream_error` when the email provider cannot register the domain (for example its domain capacity is reached, or it is rate limiting registrations): nothing is created.\n\nRequires the `domain_create` permission.","x-permission":["domain_create"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_CreateDomainRequest"}}}},"responses":{"200":{"description":"A domain with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: the organization already has its 1 custom domain (`limit_key: \"custom_domains\"`). Paid plans can add domains past their allowance (billed as extra)."},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/domains/{domain_id}":{"get":{"operationId":"domains_get","tags":["Domains"],"summary":"Get Domain","description":"Requires the `domain_read` permission.","x-permission":["domain_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"domains_update","tags":["Domains"],"summary":"Update Domain","description":"Fields you omit are unchanged. `subdomains_enabled` and `tracking_enabled` are not supported.\n\nRequires the `domain_update` permission.","x-permission":["domain_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_UpdateDomainRequest"}}}},"responses":{"200":{"description":"The updated domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"domains_delete","tags":["Domains"],"summary":"Delete Domain","description":"Inboxes on the domain are not deleted.\n\nRequires the `domain_delete` permission.","x-permission":["domain_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/domains/{domain_id}/domain-connect":{"get":{"operationId":"domains_domainConnect","tags":["Domains"],"summary":"Get Domain Connect Setup","description":"Discovers whether the domain's DNS provider supports Domain Connect (TXT `_domainconnect.<zone>` and the provider's `/v2/<zone>/settings`) and has onboarded the MachineMail template (`machinemail.dev`/`email`). When it has, `apply_url` is a signed synchronous-flow link (RS256, `key=_dck1`, `sig` last) that opens the provider with the outstanding MX, SPF, DKIM and DMARC records prefilled. Discovery is cached on the domain (6 h; provider errors 10 min) and re-run by Verify Domain.\n\nRequires the `domain_read` permission.","x-permission":["domain_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"Domain Connect support for the domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_DomainConnect"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/domains/{domain_id}/verify":{"post":{"operationId":"domains_verify","tags":["Domains"],"summary":"Verify Domain","description":"Checks every DNS record now, updates `records[].status` and `status`, and re-runs Domain Connect discovery. A `domain.verified` event is emitted when the domain becomes `VERIFIED`.\n\nRequires the `domain_update` permission.","x-permission":["domain_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain after the check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/domains/{domain_id}/zone-file":{"get":{"operationId":"domains_getZoneFile","tags":["Domains"],"summary":"Get Zone File","description":"Requires the `domain_read` permission.","x-permission":["domain_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"A BIND zone file with the records to publish","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<domain>.zone\"`","schema":{"type":"string"}}},"content":{"text/plain":{"schema":{"type":"string","description":"BIND zone file (`text/plain; charset=utf-8`)."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/drafts":{"get":{"operationId":"drafts_list","tags":["Drafts"],"summary":"List Drafts","description":"Drafts of every inbox in scope, newest first. The `labels` filter is not supported.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of drafts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_ListDraftsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/drafts/{draft_id}":{"get":{"operationId":"drafts_get","tags":["Drafts"],"summary":"Get Draft","description":"Requires the `draft_read` permission.","x-permission":["draft_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"The draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/events":{"get":{"operationId":"events_list","tags":["Events"],"summary":"List Events","description":"The replayable event log, newest first. Pass `after` (an event ID or a time) to read forward from a point, oldest first. Events are kept without a retention limit. Only the events the credential may read are listed, as on the live streams: `message.*` needs `message_read`, `inbox.*` `inbox_read`, `domain.*` `domain_read`, `draft.*` `draft_read`, `webhook.test` `webhook_read`, and the audit events (agent registrations, members) `metrics_read`. `event_types` cannot add others.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first. Defaults to true when `after` is set.","name":"ascending","in":"query"},{"schema":{"type":"string"},"required":false,"description":"An event ID (`evt_...`): only events stored after it, in commit order. Or an ISO 8601 time: only events created after it. Either one makes the default order oldest first.","name":"after","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only events created before this time.","name":"before","in":"query"},{"schema":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"}},"required":false,"description":"Only these event types (repeat the parameter, or comma-separate). Omit for every type.","name":"event_types","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this inbox.","name":"inbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this pod.","name":"pod_id","in":"query"}],"responses":{"200":{"description":"A page of events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_ListEventsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/events/stream":{"get":{"operationId":"events_stream","tags":["Events"],"summary":"Stream Events (SSE)","description":"Server-Sent Events of everything in the credential scope that its permissions allow, narrowed by the query filters.\n\nEach event is sent only when the credential holds the read permission of what it describes: `message.*` needs `message_read`, `domain.*` needs `domain_read`, `inbox.*` needs `inbox_read`, `draft.*` needs `draft_read`, `webhook.*` needs `webhook_read`, `trusted_domain.*` needs `trusted_domain_read`. Other events are skipped, without an error, and `event_types` cannot add them. The credential is re-checked every 30 seconds: when it is revoked or expired, or its permissions or pod/inbox scope change, the stream ends with an error (reconnect to get the events the credential allows now).\n\nFrames are `id: <event_id>`, `event: <event_type>`, `data: <JSON>`, where the JSON is the webhook event envelope (`type: \"event\"`, `event_id`, `event_type`, `timestamp`, `data`, and the `data` keys repeated at the top level), not the `Event` object of `GET /v0/events`. The first frame is `event: ready` with `data: {\"type\":\"subscribed\"}`. A `: ping` comment is sent after 15 seconds without events.\n\nWith a `Last-Event-ID: evt_...` header, up to 500 missed events are replayed first. The replay applies `event_types`, the credential scope and the per-event permissions, not the `inbox_id` or `pod_id` filters. When the API runs on several servers, the replay also repeats events from the few seconds before `Last-Event-ID` (an event from another server can reach a stream after a later one): dedupe by event id.\n\nAn `event: resync` frame (`data: {\"type\":\"resync\"}`) means the stream may have missed events; the stream then ends. Its `id:` is a cursor from before the gap, which an `EventSource` takes as its last event ID: reconnect with it as `Last-Event-ID` to replay what was missed, some events again (dedupe by event id).\n\nA stream opened with a dashboard session cookie also receives that person's session events (`session.agent.claimed`, `session.cli.device`, `session.oauth.request`): live notices that a hand-off they started (an agent claim, a CLI sign-in, an OAuth consent) was completed, so their other tabs can finish too. Their frames have no `id:` line and their `data` is `{\"type\":\"session\",\"event_type\",\"timestamp\",\"data\"}`; they are never stored, replayed or sent to API keys, OAuth tokens, webhooks or the WebSocket. They need no permission: they go only to the session of the person they are about.\n\nRequires the `metrics_read` permission.","security":[{"Bearer":[]},{"SessionCookie":[]},{"QueryToken":[]}],"x-permission":["metrics_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only events of these inboxes (repeat the parameter, or comma-separate).","name":"inbox_id","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Same as `inbox_id`.","name":"inbox_ids","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only events of these pods (repeat the parameter, or comma-separate).","name":"pod_id","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Same as `pod_id`.","name":"pod_ids","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"}},"required":false,"description":"Only these event types (repeat the parameter, or comma-separate). Omit for every type.","name":"event_types","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Resume after this event (`evt_...`): missed events are sent first.","name":"Last-Event-Id","in":"header"}],"responses":{"200":{"description":"The event stream","content":{"text/event-stream":{"schema":{"type":"string","description":"SSE frames."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/events/{event_id}":{"get":{"operationId":"events_get","tags":["Events"],"summary":"Get Event","description":"One event of the log. An event the credential may not read (see `GET /v0/events`) is a `404`, like one outside its scope.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the event (`evt_...`).","name":"event_id","in":"path"}],"responses":{"200":{"description":"The event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_Event"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes":{"get":{"operationId":"inboxes_list","tags":["Inboxes"],"summary":"List Inboxes","description":"Requires the `inbox_read` permission.","x-permission":["inbox_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Only ephemeral (`true`) or only permanent (`false`) inboxes.","name":"ephemeral","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of inboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_ListInboxesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_create","tags":["Inboxes"],"summary":"Create Inbox","description":"`ephemeral: true` without `ttl_seconds` creates an inbox with a one hour TTL (3600 seconds).\n\nAn organization can have at most 1,000 inboxes on the shared domain; past that the API returns `403`. Add your own domain for more. Inbox-scoped credentials cannot create inboxes (`403`).\n\nA taken address returns `409`, and so does a reserved one: role and brand names on the shared domain, and `{slug}@` on the shared domain, which only the organization with that slug can create (`agent-` followed by 16 or more hex digits is reserved the same way).\n\nRequires the `inbox_create` permission.","x-permission":["inbox_create"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_CreateInboxRequest"}}}},"responses":{"200":{"description":"An inbox with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/availability":{"get":{"operationId":"inboxes_availability","tags":["Inboxes"],"summary":"Check Inbox Availability","description":"Whether `username@domain` can be created by this organization now. Never a 4xx for a bad name: `reason` says why it is not available.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":false,"description":"Local part to check.","name":"username","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Domain to check. Defaults to the shared domain.","name":"domain","in":"query"}],"responses":{"200":{"description":"Availability of the address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_InboxAvailability"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/search":{"get":{"operationId":"inboxes_search","tags":["Inboxes"],"summary":"Search Inboxes","description":"Inboxes whose address or display name contains `q` (case-insensitive), newest first. Searches the newest 500 inboxes in scope; the response has `truncated: true` when there were more. Not ranked by relevance.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"description":"Text to find in the address or display name (case-insensitive substring).","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"}],"responses":{"200":{"description":"A page of matching inboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_SearchInboxesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}":{"get":{"operationId":"inboxes_get","tags":["Inboxes"],"summary":"Get Inbox","description":"Requires the `inbox_read` permission.","x-permission":["inbox_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"responses":{"200":{"description":"The inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_update","tags":["Inboxes"],"summary":"Update Inbox","description":"Fields you omit are unchanged. To pause an inbox, set `status` to `paused`; set it back to `active` to resume.\n\nRequires the `inbox_update` permission.","x-permission":["inbox_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_UpdateInboxRequest"}}}},"responses":{"200":{"description":"The updated inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_delete","tags":["Inboxes"],"summary":"Delete Inbox","description":"Deletes the inbox with its messages, attachments, threads and drafts. Inbox-scoped credentials cannot delete their own inbox (`403`).\n\nRequires the `inbox_delete` permission.","x-permission":["inbox_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/api-keys":{"get":{"operationId":"inboxes_apiKeys_list","tags":["API Keys"],"summary":"List API Keys in Inbox","description":"Same as List API Keys (`GET /v0/api-keys`), limited to the inbox.\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"x-scoped-copy-of":"apiKeys_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"string","enum":["bearer","public_key"]},"required":false,"description":"Only this credential family. Every key is `bearer`, so `public_key` returns an empty list.","name":"type","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_ListApiKeysResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_apiKeys_create","tags":["API Keys"],"summary":"Create API Key in Inbox","description":"Same as Create API Key (`POST /v0/api-keys`), limited to the inbox.\n\nRequires the `api_key_create` permission.","x-permission":["api_key_create"],"x-scoped-copy-of":"apiKeys_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateBearerApiKeyRequest"}}}},"responses":{"201":{"description":"Created. `api_key` is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateApiKeyResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/api-keys/{api_key_id}":{"get":{"operationId":"inboxes_apiKeys_get","tags":["API Keys"],"summary":"Get API Key in Inbox","description":"Same as Get API Key (`GET /v0/api-keys/{api_key_id}`), limited to the inbox.\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"x-scoped-copy-of":"apiKeys_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"The key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_apiKeys_update","tags":["API Keys"],"summary":"Update API Key in Inbox","description":"Same as Update API Key (`PATCH /v0/api-keys/{api_key_id}`), limited to the inbox.\n\nRequires the `api_key_update` permission.","x-permission":["api_key_update"],"x-scoped-copy-of":"apiKeys_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_UpdateApiKeyRequest"}}}},"responses":{"200":{"description":"The updated key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_apiKeys_delete","tags":["API Keys"],"summary":"Delete API Key in Inbox","description":"Same as Delete API Key (`DELETE /v0/api-keys/{api_key_id}`), limited to the inbox.\n\nRequires the `api_key_delete` permission.","x-permission":["api_key_delete"],"x-scoped-copy-of":"apiKeys_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/drafts":{"get":{"operationId":"inboxes_drafts_list","tags":["Drafts"],"summary":"List Drafts","description":"Drafts of the inbox, newest first. The `labels` filter is not supported.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of drafts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_ListDraftsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_drafts_create","tags":["Drafts"],"summary":"Create Draft","description":"With `send_at` the draft is scheduled: a background worker sends it at that time (`send_status: scheduled`). A scheduled send that fails sets `send_status: failed` and is not retried, except when the email provider could not take mail for now (throttled, sending paused, daily quota used up, or unavailable): the draft stays scheduled and a later pass sends it.\n\nReply drafts: set `in_reply_to` to a message ID in this inbox; recipients are not filled in for you. Forward drafts (`forward_of`) and `reply_all` are not supported.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`. The cap is checked when the draft is created or updated, and again when it is sent: a scheduled draft over the cap at send time gets `send_status: failed`.\n\nRequires the `draft_create` permission.","x-permission":["draft_create"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_CreateDraftRequest"}}}},"responses":{"200":{"description":"A draft with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its storage (1 GB: messages, drafts and held mail): a draft cannot grow past it (`limit_key: \"storage_bytes\"`). Delete mail or drafts to make room. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable","description":"The draft sets or moves `send_at` and the scheduler is unavailable for a moment: nothing was saved. Retry with backoff."}}}},"/v0/inboxes/{inbox_id}/drafts/{draft_id}":{"get":{"operationId":"inboxes_drafts_get","tags":["Drafts"],"summary":"Get Draft","description":"Requires the `draft_read` permission.","x-permission":["draft_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"The draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_drafts_update","tags":["Drafts"],"summary":"Update Draft","description":"Fields you omit are unchanged; `null` clears a field. `in_reply_to` cannot be changed.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nRequires the `draft_update` permission.","x-permission":["draft_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_UpdateDraftRequest"}}}},"responses":{"200":{"description":"The updated draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its storage (1 GB: messages, drafts and held mail): a draft cannot grow past it (`limit_key: \"storage_bytes\"`). Delete mail or drafts to make room. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable","description":"The draft sets or moves `send_at` and the scheduler is unavailable for a moment: nothing was saved. Retry with backoff."}}},"delete":{"operationId":"inboxes_drafts_delete","tags":["Drafts"],"summary":"Delete Draft","description":"Requires the `draft_delete` permission.","x-permission":["draft_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/drafts/{draft_id}/attachments/{attachment_id}/download":{"get":{"operationId":"inboxes_drafts_downloadAttachment","tags":["Drafts"],"summary":"Download Draft Attachment","description":"The bytes of a base64 attachment on a draft, served like a message attachment download (`nosniff`, RFC 6266 `Content-Disposition`, `disposition=inline` previews for images, PDF and plain text only). `url` attachments are fetched when the draft is sent, so they return `404` until then.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"},{"schema":{"type":"string","enum":["attachment","inline"],"default":"attachment"},"required":false,"description":"`inline` previews raster images, PDF and plain text in the browser; every other type downloads regardless.","name":"disposition","in":"query"}],"responses":{"200":{"description":"The attachment bytes","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<ascii name>\"; filename*=UTF-8''<encoded name>` (or `inline; …` for a preview).","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary","description":"The attachment bytes, with the attachment content type."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/drafts/{draft_id}/send":{"post":{"operationId":"inboxes_drafts_send","tags":["Drafts"],"summary":"Send Draft","description":"Sends the draft now and deletes it; a `draft.sent` and a `message.sent` event are emitted. The sent message gets the draft labels plus `add_labels`, minus `remove_labels`.\n\nSuppressed recipients and recipients on a send block list return `403`, a paused inbox `403`. A draft already being sent returns `409`.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nAn unclaimed sandbox agent can send at most 10 messages to at most 10 different recipients per rolling 24 hours: `429` with `Retry-After`.\n\nRequires the `draft_send` permission.","x-permission":["draft_send"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_UpdateMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/inboxes/{inbox_id}/events":{"get":{"operationId":"inboxes_events_list","tags":["Events"],"summary":"List Events in Inbox","description":"Same as List Events (`GET /v0/events`), limited to the inbox.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"events_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first. Defaults to true when `after` is set.","name":"ascending","in":"query"},{"schema":{"type":"string"},"required":false,"description":"An event ID (`evt_...`): only events stored after it, in commit order. Or an ISO 8601 time: only events created after it. Either one makes the default order oldest first.","name":"after","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only events created before this time.","name":"before","in":"query"},{"schema":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"}},"required":false,"description":"Only these event types (repeat the parameter, or comma-separate). Omit for every type.","name":"event_types","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this inbox.","name":"inbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this pod.","name":"pod_id","in":"query"}],"responses":{"200":{"description":"A page of events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_ListEventsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/events/{event_id}":{"get":{"operationId":"inboxes_events_get","tags":["Events"],"summary":"Get Event in Inbox","description":"Same as Get Event (`GET /v0/events/{event_id}`), limited to the inbox.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"events_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the event (`evt_...`).","name":"event_id","in":"path"}],"responses":{"200":{"description":"The event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_Event"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/export":{"get":{"operationId":"inboxes_export","tags":["Export"],"summary":"Export Inbox","description":"Every message in the inbox, oldest first, streamed as an attachment named `<inbox_id>.<format>`.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","enum":["mbox","jsonl"],"default":"mbox"},"required":false,"description":"`mbox`: every message as raw MIME in one mbox file. `jsonl`: one Message JSON object per line.","name":"format","in":"query"}],"responses":{"200":{"description":"The export","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<inbox_id>.<format>\"`","schema":{"type":"string"}}},"content":{"application/mbox":{"schema":{"type":"string","description":"`format=mbox`: raw MIME messages, each after a `From ` separator line."}},"application/x-ndjson":{"schema":{"type":"string","description":"`format=jsonl`: one Message JSON object per line."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/lists/{direction}/{type}":{"get":{"operationId":"inboxes_lists_list","tags":["Lists"],"summary":"List Entries in Inbox","description":"Same as List Entries (`GET /v0/lists/{direction}/{type}`), limited to the inbox. While any allow entry applies for a direction, every address that matches none is blocked (allow-only).\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-scoped-copy-of":"lists_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"`false` sorts by entry descending. Default `true`.","name":"ascending","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListListEntriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_lists_create","tags":["Lists"],"summary":"Create List Entry in Inbox","description":"Same as Create List Entry (`POST /v0/lists/{direction}/{type}`), limited to the inbox. A `receive/allow` entry here makes this scope allow-only: mail from every sender that matches no allow entry is labeled `BLOCKED` and withheld from agents. An allow-listed sender reaches `verified` only with an aligned DMARC pass.\n\nRequires the `list_entry_create` permission.","x-permission":["list_entry_create"],"x-scoped-copy-of":"lists_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_CreateListEntryRequest"}}}},"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/lists/{direction}/{type}/{entry}":{"get":{"operationId":"inboxes_lists_get","tags":["Lists"],"summary":"Get List Entry in Inbox","description":"Same as Get List Entry (`GET /v0/lists/{direction}/{type}/{entry}`), limited to the inbox.\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-scoped-copy-of":"lists_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_lists_delete","tags":["Lists"],"summary":"Delete List Entry in Inbox","description":"Same as Delete List Entry (`DELETE /v0/lists/{direction}/{type}/{entry}`), limited to the inbox.\n\nRequires the `list_entry_delete` permission.","x-permission":["list_entry_delete"],"x-scoped-copy-of":"lists_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages":{"get":{"operationId":"inboxes_messages_list","tags":["Messages"],"summary":"List Messages","description":"Messages in the inbox, newest first.\n\nSpam, blocked, trash, quarantined and unauthenticated messages are hidden unless you pass the matching `include_*` flag or ask for the label in `labels`. Spam, blocked, trash and unauthenticated also need the matching `label_*_read` permission; without it the flag is ignored.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include quarantined messages (trust level `quarantined`).","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: the words must appear in the subject, sender, recipients, body or attachment file names. Combines with the other filters.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ListMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/batch-get":{"post":{"operationId":"inboxes_messages_batchGet","tags":["Messages"],"summary":"Batch Get Messages","description":"Up to 100 messages by ID in one request, as full Message objects. Duplicate IDs are read once; IDs past the first 100 distinct ones are dropped. Missing IDs and IDs from other inboxes are omitted: compare `count` with `limit` (the number of IDs you sent).\n\nRequires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchGetMessagesRequest"}}}},"responses":{"200":{"description":"The messages found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchGetMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/batch-update":{"post":{"operationId":"inboxes_messages_batchUpdate","tags":["Messages"],"summary":"Batch Update Messages","description":"Apply one label change to up to 100 messages: the same `add_labels` and `remove_labels` apply to every message. Messages are updated one at a time, not atomically. Missing IDs are skipped: compare `count` with `limit`.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchUpdateMessagesRequest"}}}},"responses":{"200":{"description":"The updated messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchUpdateMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/search":{"get":{"operationId":"inboxes_messages_search","tags":["Messages"],"summary":"Search Messages","description":"Full-text search across messages in the inbox, newest first (not ranked by relevance). Every word of `q` must appear in the subject, sender, recipients (to and cc), body text or attachment file names. Spam, trash, blocked, quarantined and unauthenticated messages are always excluded.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Words to find in the subject, sender, recipients (to and cc), body text or attachment file names.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only messages before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only messages after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SearchMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/send":{"post":{"operationId":"inboxes_messages_send","tags":["Messages"],"summary":"Send Message","description":"At least one of `to`, `cc` or `bcc` is required.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nRecipients that are suppressed or on a send block list, and paused inboxes, return `403`. An unclaimed sandbox inbox sending to a disposable email address returns `403` with `code: \"disposable_email_not_allowed\"` and `param` set to the field holding it (`to`, `cc` or `bcc`). `502 upstream_error` when the email provider refuses or fails the send: nothing is sent or stored, and `error.message` says whether retrying can help.\n\nAttachments given by `url` are fetched by the API (public http(s) only, no redirects, at most 10 MB, 20 second timeout).\n\nAn unclaimed sandbox agent can send at most 10 messages to at most 10 different recipients per rolling 24 hours: `429` with `Retry-After` past that. Writing again to an address already counted is free. Claiming the inbox lifts the caps.\n\nWhen MachineMail pauses sending (for the platform, a plan, or this organization because of its bounce or complaint rate), the send returns `403 account_suspended` and nothing is sent; an organization limited to replies can still reply in its existing threads. Organizations on the Free plan may be limited to sending to people who emailed them first (`403`) and to a number of different recipients per rolling 24 hours (`429`). Messages that look like phishing are held and not sent (`403`).\n\nRequires the `message_send` permission.","x-permission":["message_send"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}":{"get":{"operationId":"inboxes_messages_get","tags":["Messages"],"summary":"Get Message","description":"Message content is untrusted: when feeding an LLM, read `trust.content.text` rather than `text` or `html`.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_Message"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_messages_update","tags":["Messages"],"summary":"Update Message","description":"Adds and removes labels. Returns the whole updated message.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_UpdateMessageRequest"}}}},"responses":{"200":{"description":"The updated message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_Message"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_messages_delete","tags":["Messages"],"summary":"Delete Message","description":"Permanently deletes the message, its raw copy and attachments. The thread is updated (or deleted with its last message).\n\nRequires the `message_delete` permission.","x-permission":["message_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}":{"get":{"operationId":"inboxes_messages_getAttachment","tags":["Messages"],"summary":"Get Attachment","description":"Requires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"}],"responses":{"200":{"description":"The attachment with a download URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/attachments_AttachmentResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}/download":{"get":{"operationId":"inboxes_messages_downloadAttachment","tags":["Messages"],"summary":"Download Attachment","description":"The attachment bytes, with `X-Content-Type-Options: nosniff`. By default `Content-Disposition: attachment` (RFC 6266: an ASCII `filename` plus the exact name in RFC 5987 `filename*` when it is not plain ASCII). With `disposition=inline`, raster images, PDF and plain text are served inline for previews, under a locked-down Content-Security-Policy; every other type (HTML, SVG, XML, scripts, archives…) is still served as a download.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"},{"schema":{"type":"string","enum":["attachment","inline"],"default":"attachment"},"required":false,"description":"`inline` previews raster images, PDF and plain text in the browser; every other type downloads regardless.","name":"disposition","in":"query"}],"responses":{"200":{"description":"The attachment bytes","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<ascii name>\"; filename*=UTF-8''<encoded name>` (or `inline; …` for a preview).","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary","description":"The attachment bytes, with the attachment content type."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/forward":{"post":{"operationId":"inboxes_messages_forward","tags":["Messages"],"summary":"Forward Message","description":"Sends the message to new recipients. The text body is your `text` followed by a \"Forwarded message\" header block and the original text. The original HTML and attachments are not included. `subject` defaults to `Fwd: <original subject>`. A quarantined message (trust level `quarantined` or the `QUARANTINE` label) is not forwarded: `409 conflict` with `param: \"message_id\"`; a person can review it in the dashboard.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nRecipients that are suppressed or on a send block list, and paused inboxes, return `403`. An unclaimed sandbox inbox sending to a disposable email address returns `403` with `code: \"disposable_email_not_allowed\"` and `param` set to the field holding it (`to`, `cc` or `bcc`). `502 upstream_error` when the email provider refuses or fails the send: nothing is sent or stored, and `error.message` says whether retrying can help.\n\nAttachments given by `url` are fetched by the API (public http(s) only, no redirects, at most 10 MB, 20 second timeout).\n\nAn unclaimed sandbox agent can send at most 10 messages to at most 10 different recipients per rolling 24 hours: `429` with `Retry-After` past that. Writing again to an address already counted is free. Claiming the inbox lifts the caps.\n\nWhen MachineMail pauses sending (for the platform, a plan, or this organization because of its bounce or complaint rate), the send returns `403 account_suspended` and nothing is sent; an organization limited to replies can still reply in its existing threads. Organizations on the Free plan may be limited to sending to people who emailed them first (`403`) and to a number of different recipients per rolling 24 hours (`429`). Messages that look like phishing are held and not sent (`403`).\n\nRequires the `message_send` permission.","x-permission":["message_send"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/raw":{"get":{"operationId":"inboxes_messages_getRaw","tags":["Messages"],"summary":"Get Raw Message","description":"The original RFC 5322 message bytes, as received or sent. AgentMail returns a JSON object with a download URL instead.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The raw message","content":{"message/rfc822":{"schema":{"type":"string","format":"binary","description":"RFC 5322 message bytes."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/reply":{"post":{"operationId":"inboxes_messages_reply","tags":["Messages"],"summary":"Reply To Message","description":"Sends a reply in the thread of the message, with `In-Reply-To` and `References` set.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nRecipients that are suppressed or on a send block list, and paused inboxes, return `403`. An unclaimed sandbox inbox sending to a disposable email address returns `403` with `code: \"disposable_email_not_allowed\"` and `param` set to the field holding it (`to`, `cc` or `bcc`). `502 upstream_error` when the email provider refuses or fails the send: nothing is sent or stored, and `error.message` says whether retrying can help.\n\nAttachments given by `url` are fetched by the API (public http(s) only, no redirects, at most 10 MB, 20 second timeout).\n\nAn unclaimed sandbox agent can send at most 10 messages to at most 10 different recipients per rolling 24 hours: `429` with `Retry-After` past that. Writing again to an address already counted is free. Claiming the inbox lifts the caps.\n\nWhen MachineMail pauses sending (for the platform, a plan, or this organization because of its bounce or complaint rate), the send returns `403 account_suspended` and nothing is sent; an organization limited to replies can still reply in its existing threads. Organizations on the Free plan may be limited to sending to people who emailed them first (`403`) and to a number of different recipients per rolling 24 hours (`429`). Messages that look like phishing are held and not sent (`403`).\n\nRequires the `message_reply` or `message_send` permission.","x-permission":["message_reply","message_send"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ReplyToMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/reply-all":{"post":{"operationId":"inboxes_messages_reply-all","tags":["Messages"],"summary":"Reply All Message","description":"Replies to the sender and every `to` and `cc` recipient of the message, except this inbox. `to` and `cc` add more recipients.\n\nA message can have at most 50 recipients: `to`, `cc` and `bcc` together, each address counted once. An unclaimed sandbox inbox can have at most 5. More is a `400` `validation` error with `param: \"to\"`.\n\nRecipients that are suppressed or on a send block list, and paused inboxes, return `403`. An unclaimed sandbox inbox sending to a disposable email address returns `403` with `code: \"disposable_email_not_allowed\"` and `param` set to the field holding it (`to`, `cc` or `bcc`). `502 upstream_error` when the email provider refuses or fails the send: nothing is sent or stored, and `error.message` says whether retrying can help.\n\nAttachments given by `url` are fetched by the API (public http(s) only, no redirects, at most 10 MB, 20 second timeout).\n\nAn unclaimed sandbox agent can send at most 10 messages to at most 10 different recipients per rolling 24 hours: `429` with `Retry-After` past that. Writing again to an address already counted is free. Claiming the inbox lifts the caps.\n\nWhen MachineMail pauses sending (for the platform, a plan, or this organization because of its bounce or complaint rate), the send returns `403 account_suspended` and nothing is sent; an organization limited to replies can still reply in its existing threads. Organizations on the Free plan may be limited to sending to people who emailed them first (`403`) and to a number of different recipients per rolling 24 hours (`429`). Messages that look like phishing are held and not sent (`403`).\n\nRequires the `message_reply` or `message_send` permission.","x-permission":["message_reply","message_send"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ReplyAllMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/inboxes/{inbox_id}/messages/{message_id}/trust":{"get":{"operationId":"inboxes_messages_getTrust","tags":["Trust"],"summary":"Get Message Trust Report","description":"The same object as the message `trust`. `404` for messages without a report (outbound messages).\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The trust report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrustReport"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/metrics":{"get":{"operationId":"inboxes_metrics_queryEventsAlias","tags":["Metrics"],"summary":"Query Events (alias) in Inbox","description":"Same as Query Events (alias) (`GET /v0/metrics`), limited to the inbox.\n\nRequires the `metrics_read` permission.","deprecated":true,"x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"metrics_queryEventsAlias","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/metrics/events":{"get":{"operationId":"inboxes_metrics_queryEvents","tags":["Metrics"],"summary":"Query Events in Inbox","description":"Same as Query Events (`GET /v0/metrics/events`), limited to the inbox.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryEvents","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/metrics/rates":{"get":{"operationId":"inboxes_metrics_queryRates","tags":["Metrics"],"summary":"Query Rates in Inbox","description":"Same as Query Rates (`GET /v0/metrics/rates`), limited to the inbox.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryRates","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Rate types: `bounce`, `complaint`. Default: both. Another value is a `400`.","name":"rate_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points.","name":"period","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How far back each point looks, in seconds: a whole multiple of `period`, at most 2592000 (30 days). Default 86400 when that is a multiple of `period`, otherwise `period`.","name":"window","in":"query"}],"responses":{"200":{"description":"Rates by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryRatesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/metrics/usage":{"get":{"operationId":"inboxes_metrics_queryUsage","tags":["Metrics"],"summary":"Query Usage in Inbox","description":"Same as Query Usage (`GET /v0/metrics/usage`), limited to the inbox.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryUsage","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Usage types: `storage_bytes`, `message_count`, `thread_count`, `inbox_count`, `pod_count`, `domain_count`. Default: all. Another value is a `400`.","name":"usage_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period.","name":"period","in":"query"}],"responses":{"200":{"description":"Usage by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryUsageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/threads":{"get":{"operationId":"inboxes_threads_list","tags":["Threads"],"summary":"List Threads","description":"Threads, most recently active first. Pass `q` to keep only threads with a message matching the words.\n\nThreads with a spam, blocked, trash, quarantined or unauthenticated message are hidden unless you pass the matching `include_*` flag or ask for the label in `labels`.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ListThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/threads/search":{"get":{"operationId":"inboxes_threads_search","tags":["Threads"],"summary":"Search Threads","description":"Threads with a message whose subject, sender, recipients, body or attachment file names contain every word of `q`, ordered by thread activity (not ranked by relevance). Scans the newest 500 matching messages; the response has `truncated: true` when it hit that cap.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only threads with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_SearchThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/threads/{thread_id}":{"get":{"operationId":"inboxes_threads_get","tags":["Threads"],"summary":"Get Thread","description":"The thread with its messages, which carry their bodies and trust reports. Messages come in pages of `limit` (default and maximum 500): the first page has the newest messages, oldest first within the page; follow `next_page_token` for older ones.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of messages to return. Default and maximum 500.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous response: the next, older page of messages.","name":"page_token","in":"query"}],"responses":{"200":{"description":"The thread with a page of its messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_Thread"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_threads_update","tags":["Threads"],"summary":"Update Thread","description":"Adds and removes labels on every message in the thread (up to 500 messages); the thread labels are their union. Labels are free strings, system labels included. Returns the updated thread without messages.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_UpdateThreadRequest"}}}},"responses":{"200":{"description":"The updated thread, without messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ThreadItem"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_threads_delete","tags":["Threads"],"summary":"Delete Thread","description":"Permanently deletes the thread and its messages (up to 500).\n\nRequires the `thread_delete` permission.","x-permission":["thread_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/trusted-domains":{"get":{"operationId":"inboxes_trustedDomains_list","tags":["Trusted Domains"],"summary":"List Trusted Domains in Inbox","description":"Same as List Trusted Domains (`GET /v0/trusted-domains`), limited to the inbox.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of trusted domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_ListTrustedDomainsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_trustedDomains_create","tags":["Trusted Domains"],"summary":"Create Trusted Domain in Inbox","description":"Same as Create Trusted Domain (`POST /v0/trusted-domains`), limited to the inbox.\n\nRequires the `trusted_domain_create` permission.","x-permission":["trusted_domain_create"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The existing entry for this domain or `client_id`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"The organization already has as many trusted domains as its plan allows (`limit_key: \"trusted_domains\"`): 10 on Free, 500 on paid plans, none for unclaimed sandbox agents. Remove one first."},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_create`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict","description":"`client_id` is already used at another level."},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"`trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/trusted-domains/preview":{"post":{"operationId":"inboxes_trustedDomains_preview","tags":["Trusted Domains"],"summary":"Preview Trusted Domain in Inbox","description":"Same as Preview Trusted Domain (`POST /v0/trusted-domains/preview`), limited to the inbox.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_preview","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainRequest"}}}},"responses":{"200":{"description":"The preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/trusted-domains/{trusted_domain_id}":{"get":{"operationId":"inboxes_trustedDomains_get","tags":["Trusted Domains"],"summary":"Get Trusted Domain in Inbox","description":"Same as Get Trusted Domain (`GET /v0/trusted-domains/{trusted_domain_id}`), limited to the inbox.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_trustedDomains_update","tags":["Trusted Domains"],"summary":"Update Trusted Domain in Inbox","description":"Same as Update Trusted Domain (`PATCH /v0/trusted-domains/{trusted_domain_id}`), limited to the inbox.\n\nRequires the `trusted_domain_update` permission.","x-permission":["trusted_domain_update"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_UpdateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The updated entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_update`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"Turning on `include_subdomains`: `trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_trustedDomains_delete","tags":["Trusted Domains"],"summary":"Delete Trusted Domain in Inbox","description":"Same as Delete Trusted Domain (`DELETE /v0/trusted-domains/{trusted_domain_id}`), limited to the inbox.\n\nRequires the `trusted_domain_delete` permission.","x-permission":["trusted_domain_delete"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks":{"get":{"operationId":"inboxes_webhooks_list","tags":["Webhooks"],"summary":"List Webhooks in Inbox","description":"Same as List Webhooks (`GET /v0/webhooks`), limited to the inbox.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of webhooks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListWebhooksResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"inboxes_webhooks_create","tags":["Webhooks"],"summary":"Create Webhook in Inbox","description":"Same as Create Webhook (`POST /v0/webhooks`), limited to the inbox.\n\nRequires the `webhook_create` permission.","x-permission":["webhook_create"],"x-scoped-copy-of":"webhooks_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_CreateWebhookRequest"}}}},"responses":{"200":{"description":"A webhook with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks/{webhook_id}":{"get":{"operationId":"inboxes_webhooks_get","tags":["Webhooks"],"summary":"Get Webhook in Inbox","description":"Same as Get Webhook (`GET /v0/webhooks/{webhook_id}`), limited to the inbox.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_webhooks_update","tags":["Webhooks"],"summary":"Update Webhook in Inbox","description":"Same as Update Webhook (`PATCH /v0/webhooks/{webhook_id}`), limited to the inbox.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-scoped-copy-of":"webhooks_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookRequest"}}}},"responses":{"200":{"description":"The updated webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"inboxes_webhooks_delete","tags":["Webhooks"],"summary":"Delete Webhook in Inbox","description":"Same as Delete Webhook (`DELETE /v0/webhooks/{webhook_id}`), limited to the inbox.\n\nRequires the `webhook_delete` permission.","x-permission":["webhook_delete"],"x-scoped-copy-of":"webhooks_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks/{webhook_id}/deliveries":{"get":{"operationId":"inboxes_webhooks_deliveries_list","tags":["Webhooks"],"summary":"List Deliveries in Inbox","description":"Same as List Deliveries (`GET /v0/webhooks/{webhook_id}/deliveries`), limited to the inbox.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_deliveries_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"string","enum":["pending","delivered","failed"]},"required":false,"description":"Only deliveries with this status.","name":"status","in":"query"}],"responses":{"200":{"description":"A page of deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListDeliveriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/replay":{"post":{"operationId":"inboxes_webhooks_deliveries_replay","tags":["Webhooks"],"summary":"Replay Delivery in Inbox","description":"Same as Replay Delivery (`POST /v0/webhooks/{webhook_id}/deliveries/{delivery_id}/replay`), limited to the inbox.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_deliveries_replay","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the delivery to replay.","name":"delivery_id","in":"path"}],"responses":{"200":{"description":"The new delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks/{webhook_id}/headers":{"get":{"operationId":"inboxes_webhooks_getHeaders","tags":["Webhooks"],"summary":"Get Webhook Headers in Inbox","description":"Same as Get Webhook Headers (`GET /v0/webhooks/{webhook_id}/headers`), limited to the inbox.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_getHeaders","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The header names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookHeaderNamesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"inboxes_webhooks_updateHeaders","tags":["Webhooks"],"summary":"Update Webhook Headers in Inbox","description":"Same as Update Webhook Headers (`PATCH /v0/webhooks/{webhook_id}/headers`), limited to the inbox.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-scoped-copy-of":"webhooks_updateHeaders","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookHeadersRequest"}}}},"responses":{"204":{"description":"Updated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/inboxes/{inbox_id}/webhooks/{webhook_id}/test":{"post":{"operationId":"inboxes_webhooks_test","tags":["Webhooks"],"summary":"Send Test Event in Inbox","description":"Same as Send Test Event (`POST /v0/webhooks/{webhook_id}/test`), limited to the inbox.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_test","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the inbox.","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The test delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/lists/{direction}/{type}":{"get":{"operationId":"lists_list","tags":["Lists"],"summary":"List Entries","description":"Entries stored at this exact level. Mail is checked against the organization, pod and inbox lists together. An allow entry wins over a block entry; while any allow entry exists for a direction, every address that matches none is blocked (allow-only).\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"`false` sorts by entry descending. Default `true`.","name":"ascending","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListListEntriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"lists_create","tags":["Lists"],"summary":"Create List Entry","description":"An address (`user@example.com`) or a domain (`example.com`); a domain also matches its subdomains. Adding an entry that exists returns it unchanged.\n\n**An `allow` entry makes its scope allow-only.** The first `receive/allow` entry at the organization (`/v0/lists`), a pod (`/v0/pods/{pod_id}/lists`) or an inbox (`/v0/inboxes/{inbox_id}/lists`) blocks every sender that does not match an allow entry: their mail is labeled `BLOCKED`, emits `message.received.blocked` and is withheld from agents. Likewise, a `send/allow` entry blocks sending to every other recipient. An allow-listed sender reaches trust level `verified` only when DMARC passes and is aligned; do not add one only to raise trust. Prior correspondence (an inbox in the organization has written to the sender) is the usual way to reach `verified`.\n\nRequires the `list_entry_create` permission.","x-permission":["list_entry_create"],"parameters":[{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_CreateListEntryRequest"}}}},"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/lists/{direction}/{type}/{entry}":{"get":{"operationId":"lists_get","tags":["Lists"],"summary":"Get List Entry","description":"Requires the `list_entry_read` permission.","x-permission":["list_entry_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"lists_delete","tags":["Lists"],"summary":"Delete List Entry","description":"Deleting the last `allow` entry for a direction at every level that applies ends allow-only mode: unmatched addresses are allowed again unless a block entry matches.\n\nRequires the `list_entry_delete` permission.","x-permission":["list_entry_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/metrics":{"get":{"operationId":"metrics_queryEventsAlias","tags":["Metrics"],"summary":"Query Events (alias)","description":"Alias of `GET /v0/metrics/events`.\n\nRequires the `metrics_read` permission.","deprecated":true,"x-permission":["metrics_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/metrics/events":{"get":{"operationId":"metrics_queryEvents","tags":["Metrics"],"summary":"Query Events","description":"Counts of events per event type over time, in buckets of `period` seconds (default one day), over the last 24 hours unless `start` and `end` say otherwise. `message.received` includes its sub-types (spam, blocked, unauthenticated, quarantined). At most 100,000 events are counted per query.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"parameters":[{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/metrics/rates":{"get":{"operationId":"metrics_queryRates","tags":["Metrics"],"summary":"Query Rates","description":"Rolling bounce and complaint rates. At each `period` grid point: the bounced (or complained) messages over the preceding `window`, divided by the messages sent over the same window, with the send count alongside. Defaults: the last 24 hours, `period` 3600, `window` 86400.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"parameters":[{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Rate types: `bounce`, `complaint`. Default: both. Another value is a `400`.","name":"rate_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points.","name":"period","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How far back each point looks, in seconds: a whole multiple of `period`, at most 2592000 (30 days). Default 86400 when that is a multiple of `period`, otherwise `period`.","name":"window","in":"query"}],"responses":{"200":{"description":"Rates by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryRatesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/metrics/usage":{"get":{"operationId":"metrics_queryUsage","tags":["Metrics"],"summary":"Query Usage","description":"Current usage in the scope. Usage history is not kept yet: each series has a single point, at `end`, with the value now.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"parameters":[{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Usage types: `storage_bytes`, `message_count`, `thread_count`, `inbox_count`, `pod_count`, `domain_count`. Default: all. Another value is a `400`.","name":"usage_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period.","name":"period","in":"query"}],"responses":{"200":{"description":"Usage by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryUsageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/oauth-grants":{"get":{"operationId":"oauthGrants_list","tags":["Connected Apps"],"summary":"List Connected Apps","description":"Apps and MCP clients people in the organization connected with OAuth. Requires an organization-scoped credential with `api_key_read`; pod, inbox and sandbox credentials get `403`.","x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of grants","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOAuthGrantsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/oauth-grants/{grant_id}":{"delete":{"operationId":"oauthGrants_delete","tags":["Connected Apps"],"summary":"Disconnect App","description":"Revokes the grant: its refresh token and every access token issued from it stop working immediately (`401` on `/mcp` and `/v0`). Returns the grant as it was. Requires an organization-scoped credential with `api_key_delete`.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the grant (`oag_...`).","name":"grant_id","in":"path"}],"responses":{"200":{"description":"The revoked grant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthGrant"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/openapi.json":{"get":{"operationId":"openapi_get","tags":["OpenAPI"],"summary":"Get OpenAPI Document","description":"This OpenAPI 3.1 document, as JSON. No authentication.","security":[],"x-machinemail":true,"responses":{"200":{"description":"The OpenAPI document","content":{"application/json":{"schema":{"type":"object","additionalProperties":{},"description":"An OpenAPI 3.1 document."}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organization":{"get":{"operationId":"organization_getAlias","tags":["Organization"],"summary":"Get Organization (alias)","description":"Alias of `GET /v0/organizations`.","deprecated":true,"x-machinemail":true,"responses":{"200":{"description":"The organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Organization"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations":{"get":{"operationId":"organizations_get","tags":["Organization"],"summary":"Get Organization","description":"The organization of the credential, with inbox and domain counts and usage. `inbox_count` and `usage` count what the credential can see (a pod key: its pod).","responses":{"200":{"description":"The organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Organization"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"organizations_update","tags":["Organization"],"summary":"Update Organization","description":"Rename the organization, turn undo send in the dashboard on or off (`undo_send`), or change the default inbox (`default_inbox_id`).\n\nThe organization slug is fixed when it is created and never changes: a different `slug` in the body is `400` (the current value is accepted and ignored). The slug reserves `{slug}@` on the shared domain for this organization.\n\nOrganization-scoped credentials only: pod and inbox credentials get `403`.","x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_UpdateOrganizationRequest"}}}},"responses":{"200":{"description":"The organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Organization"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"organizations_delete","tags":["Organization"],"summary":"Delete Organization","description":"Delete the organization, with the `code` emailed by `POST /v0/organizations/deletion`. It cannot be undone.\n\nAccess ends at once: every member's dashboard sessions and open streams for the organization stop working, every API key is revoked, connected apps and agents are disconnected, pending invitations are revoked, webhooks stop, and mail to the organization's addresses is refused as unknown. Its inboxes, messages, attachments, drafts, threads, domains, webhooks, events, pods and lists are then removed in the background. The slug stays reserved: no organization can use it again. Your session moves to another organization you belong to (as when leaving one); when there is none, it ends and the `mm_session` cookie is cleared.\n\nOwners only, from a dashboard session (the `mm_session` cookie): admins, members, API keys and access tokens get `403`.","x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_DeleteOrganizationRequest"}}}},"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_DeleteOrganizationResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/deletion":{"post":{"operationId":"organizations_startDeletion","tags":["Organization"],"summary":"Start Deleting Organization","description":"First step of deleting the organization: send `confirm_name`, the organization's name (any case), and a 6-digit confirmation code is emailed to you. The code works once, for 10 minutes and 3 tries; asking again sends a new one (at most 3 an hour, and 10 a day for the organization). `502` when the email could not be sent: no code exists, try again. Then confirm with `DELETE /v0/organizations`.\n\n`409` with `code: billing_subscription_active` while a paid plan is in force: cancel it under Billing first, and delete the organization once the plan has ended.\n\nOwners only, from a dashboard session (the `mm_session` cookie): admins, members, API keys and access tokens get `403`.","x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_StartOrganizationDeletionRequest"}}}},"responses":{"202":{"description":"Code sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_OrganizationDeletionStarted"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/organizations/invitations":{"get":{"operationId":"organizations_listInvitations","tags":["Organization"],"summary":"List Invitations","description":"Pending invitations, newest first (`ascending=true`: oldest first). Dashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"Pending invitations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_ListInvitationsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"organizations_createInvitation","tags":["Organization"],"summary":"Invite Member","description":"Email an invitation to join the organization, valid for 7 days and only for that address. `409` when the address is already a member or already invited.\n\nThe email links to `/invite/{token}`, where the person signs in (email code, social or SSO) and accepts it.\n\n`403` with `error.code` `signup_address_not_allowed` when the address is on a MachineMail domain (the shared domain, or a subdomain of it): those addresses can’t be used for accounts. The answer depends on the address’s domain only, never on whether it has an account. An address on a custom domain verified on MachineMail can be invited, but someone without an account can accept only an invitation from the organization that verified the domain; those people can join that organization but not create organizations of their own.\n\nDashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_CreateInvitationRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Invitation"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"The plan allows no more members: members plus pending invitations are at its seat limit (Free: 1; `limit_key: \"seats\"`). Existing members are kept."},"403":{"$ref":"#/components/responses/Forbidden","description":"Not allowed to invite members, or the address is on a MachineMail domain (`error.code` `signup_address_not_allowed`)."},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/invitations/{invitation_id}":{"delete":{"operationId":"organizations_revokeInvitation","tags":["Organization"],"summary":"Revoke Invitation","description":"Revoke a pending invitation: its link stops working. Dashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the invitation.","name":"invitation_id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/invitations/{invitation_id}/resend":{"post":{"operationId":"organizations_resendInvitation","tags":["Organization"],"summary":"Resend Invitation","description":"Send a pending invitation again. Dashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the invitation.","name":"invitation_id","in":"path"}],"responses":{"200":{"description":"Sent again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Invitation"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/members":{"get":{"operationId":"organizations_listMembers","tags":["Organization"],"summary":"List Members","description":"The people who sign in to the dashboard for this organization, with their role in it, oldest first. Organization-scoped credentials only: pod and inbox credentials get `403`.","x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of members","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_ListMembersResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/members/{user_id}":{"patch":{"operationId":"organizations_updateMember","tags":["Organization"],"summary":"Update Member","description":"Change a member's role. The last owner cannot be demoted (`409`). Dashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the member (`user_id`).","name":"user_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_UpdateMemberRequest"}}}},"responses":{"200":{"description":"The member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_Member"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"organizations_removeMember","tags":["Organization"],"summary":"Remove Member","description":"Remove a member, or leave the organization with your own `user_id` (any role). The last owner cannot leave or be removed (`409`).\n\nTheir access ends at once: their dashboard sessions and open event streams for this organization stop working, the API keys they created here are revoked (CLI keys, and keys minted with those keys, included), the apps they connected with OAuth (MCP clients) are disconnected, and invitations they sent that are still pending are revoked. Keys that record no creator (made before organizations had members) are not revoked: review them under API keys. Leaving moves your session to another organization you belong to whose sign-in policy your session meets (its single sign-on and sign-in method rules apply, as for switching); when there is none, the session ends and the `mm_session` cookie is cleared.\n\nDashboard session only (the `mm_session` cookie): API keys and access tokens get `403`. Owners and admins manage members; only owners grant, change or remove the owner role.","x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the member (`user_id`).","name":"user_id","in":"path"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/organizations/usage":{"get":{"operationId":"organizations_getUsage","tags":["Organization"],"summary":"Get Plan Usage","description":"The plan of the organization, its allowances and its usage in the current period: a calendar month in UTC, with the daily cap resetting at UTC midnight.\n\nInbound messages count once each; outbound messages count once per distinct recipient (to, cc and bcc). Spam and quarantined mail never count (mail your own receive lists block does). Storage includes drafts and held mail. Deleting mail frees storage but does not give back messages already counted.\n\nOn the Free plan, inbound mail past an allowance is held (`held`) and delivered when the allowance resets or after an upgrade; sends past it are refused with `402` `plan_limit_exceeded`. Paid plans are never blocked: usage past an allowance is billed as overage.\n\nOrganization-wide whatever the credential: Organization-scoped credentials only: pod and inbox credentials get `403`.","x-machinemail":true,"responses":{"200":{"description":"Plan allowances and usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/organizations_PlanUsage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods":{"get":{"operationId":"pods_list","tags":["Pods"],"summary":"List Pods","description":"Requires the `pod_read` permission.","x-permission":["pod_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of pods","content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_ListPodsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_create","tags":["Pods"],"summary":"Create Pod","description":"Organization-scoped credentials only: pod and inbox credentials get `403`.\n\nRequires the `pod_create` permission.","x-permission":["pod_create"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_CreatePodRequest"}}}},"responses":{"200":{"description":"A pod with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_Pod"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_Pod"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}":{"get":{"operationId":"pods_get","tags":["Pods"],"summary":"Get Pod","description":"Requires the `pod_read` permission.","x-permission":["pod_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/pods_PodId"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"responses":{"200":{"description":"The pod","content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_Pod"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_update","tags":["Pods"],"summary":"Update Pod","description":"Rename the pod.\n\nRequires the `pod_update` permission.","x-permission":["pod_update"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/pods_PodId"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_UpdatePodRequest"}}}},"responses":{"200":{"description":"The updated pod","content":{"application/json":{"schema":{"$ref":"#/components/schemas/pods_Pod"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_delete","tags":["Pods"],"summary":"Delete Pod","description":"The default pod, and pods that still have inboxes, cannot be deleted (`409`).\n\nRequires the `pod_delete` permission.","x-permission":["pod_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/pods_PodId"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/api-keys":{"get":{"operationId":"pods_apiKeys_list","tags":["API Keys"],"summary":"List API Keys in Pod","description":"Same as List API Keys (`GET /v0/api-keys`), limited to the pod.\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"x-scoped-copy-of":"apiKeys_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string","enum":["bearer","public_key"]},"required":false,"description":"Only this credential family. Every key is `bearer`, so `public_key` returns an empty list.","name":"type","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_ListApiKeysResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_apiKeys_create","tags":["API Keys"],"summary":"Create API Key in Pod","description":"Same as Create API Key (`POST /v0/api-keys`), limited to the pod.\n\nRequires the `api_key_create` permission.","x-permission":["api_key_create"],"x-scoped-copy-of":"apiKeys_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateBearerApiKeyRequest"}}}},"responses":{"201":{"description":"Created. `api_key` is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_CreateApiKeyResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/api-keys/{api_key_id}":{"get":{"operationId":"pods_apiKeys_get","tags":["API Keys"],"summary":"Get API Key in Pod","description":"Same as Get API Key (`GET /v0/api-keys/{api_key_id}`), limited to the pod.\n\nRequires the `api_key_read` permission.","x-permission":["api_key_read"],"x-scoped-copy-of":"apiKeys_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"The key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_apiKeys_update","tags":["API Keys"],"summary":"Update API Key in Pod","description":"Same as Update API Key (`PATCH /v0/api-keys/{api_key_id}`), limited to the pod.\n\nRequires the `api_key_update` permission.","x-permission":["api_key_update"],"x-scoped-copy-of":"apiKeys_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_UpdateApiKeyRequest"}}}},"responses":{"200":{"description":"The updated key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_apiKeys_delete","tags":["API Keys"],"summary":"Delete API Key in Pod","description":"Same as Delete API Key (`DELETE /v0/api-keys/{api_key_id}`), limited to the pod.\n\nRequires the `api_key_delete` permission.","x-permission":["api_key_delete"],"x-scoped-copy-of":"apiKeys_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"required":true,"description":"ID of the API key.","name":"api_key_id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/domains":{"get":{"operationId":"pods_domains_list","tags":["Domains"],"summary":"List Domains in Pod","description":"Same as List Domains (`GET /v0/domains`), limited to the pod.\n\nRequires the `domain_read` permission.","x-permission":["domain_read"],"x-scoped-copy-of":"domains_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_ListDomainsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_domains_create","tags":["Domains"],"summary":"Create Domain in Pod","description":"Same as Create Domain (`POST /v0/domains`), limited to the pod.\n\nRequires the `domain_create` permission.","x-permission":["domain_create"],"x-scoped-copy-of":"domains_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_CreateDomainRequest"}}}},"responses":{"200":{"description":"A domain with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: the organization already has its 1 custom domain (`limit_key: \"custom_domains\"`). Paid plans can add domains past their allowance (billed as extra)."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/domains/{domain_id}":{"get":{"operationId":"pods_domains_get","tags":["Domains"],"summary":"Get Domain in Pod","description":"Same as Get Domain (`GET /v0/domains/{domain_id}`), limited to the pod.\n\nRequires the `domain_read` permission.","x-permission":["domain_read"],"x-scoped-copy-of":"domains_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_domains_update","tags":["Domains"],"summary":"Update Domain in Pod","description":"Same as Update Domain (`PATCH /v0/domains/{domain_id}`), limited to the pod.\n\nRequires the `domain_update` permission.","x-permission":["domain_update"],"x-scoped-copy-of":"domains_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_UpdateDomainRequest"}}}},"responses":{"200":{"description":"The updated domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_domains_delete","tags":["Domains"],"summary":"Delete Domain in Pod","description":"Same as Delete Domain (`DELETE /v0/domains/{domain_id}`), limited to the pod.\n\nRequires the `domain_delete` permission.","x-permission":["domain_delete"],"x-scoped-copy-of":"domains_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/domains/{domain_id}/domain-connect":{"get":{"operationId":"pods_domains_domainConnect","tags":["Domains"],"summary":"Get Domain Connect Setup in Pod","description":"Same as Get Domain Connect Setup (`GET /v0/domains/{domain_id}/domain-connect`), limited to the pod.\n\nRequires the `domain_read` permission.","x-permission":["domain_read"],"x-machinemail":true,"x-scoped-copy-of":"domains_domainConnect","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"Domain Connect support for the domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_DomainConnect"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/domains/{domain_id}/verify":{"post":{"operationId":"pods_domains_verify","tags":["Domains"],"summary":"Verify Domain in Pod","description":"Same as Verify Domain (`POST /v0/domains/{domain_id}/verify`), limited to the pod.\n\nRequires the `domain_update` permission.","x-permission":["domain_update"],"x-scoped-copy-of":"domains_verify","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain after the check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/domains_Domain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/domains/{domain_id}/zone-file":{"get":{"operationId":"pods_domains_getZoneFile","tags":["Domains"],"summary":"Get Zone File in Pod","description":"Same as Get Zone File (`GET /v0/domains/{domain_id}/zone-file`), limited to the pod.\n\nRequires the `domain_read` permission.","x-permission":["domain_read"],"x-scoped-copy-of":"domains_getZoneFile","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/domains_DomainId"},"required":true,"description":"ID of the domain.","name":"domain_id","in":"path"}],"responses":{"200":{"description":"A BIND zone file with the records to publish","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<domain>.zone\"`","schema":{"type":"string"}}},"content":{"text/plain":{"schema":{"type":"string","description":"BIND zone file (`text/plain; charset=utf-8`)."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/drafts":{"get":{"operationId":"pods_drafts_list","tags":["Drafts"],"summary":"List Drafts in Pod","description":"Same as List Drafts (`GET /v0/drafts`), limited to the pod.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-scoped-copy-of":"drafts_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of drafts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_ListDraftsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/drafts/{draft_id}":{"get":{"operationId":"pods_drafts_get","tags":["Drafts"],"summary":"Get Draft in Pod","description":"Same as Get Draft (`GET /v0/drafts/{draft_id}`), limited to the pod.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-scoped-copy-of":"drafts_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"The draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/events":{"get":{"operationId":"pods_events_list","tags":["Events"],"summary":"List Events in Pod","description":"Same as List Events (`GET /v0/events`), limited to the pod.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"events_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first. Defaults to true when `after` is set.","name":"ascending","in":"query"},{"schema":{"type":"string"},"required":false,"description":"An event ID (`evt_...`): only events stored after it, in commit order. Or an ISO 8601 time: only events created after it. Either one makes the default order oldest first.","name":"after","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only events created before this time.","name":"before","in":"query"},{"schema":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"}},"required":false,"description":"Only these event types (repeat the parameter, or comma-separate). Omit for every type.","name":"event_types","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this inbox.","name":"inbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Only events of this pod.","name":"pod_id","in":"query"}],"responses":{"200":{"description":"A page of events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_ListEventsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/events/{event_id}":{"get":{"operationId":"pods_events_get","tags":["Events"],"summary":"Get Event in Pod","description":"Same as Get Event (`GET /v0/events/{event_id}`), limited to the pod.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"events_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the event (`evt_...`).","name":"event_id","in":"path"}],"responses":{"200":{"description":"The event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_Event"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes":{"get":{"operationId":"pods_inboxes_list","tags":["Inboxes"],"summary":"List Inboxes in Pod","description":"Same as List Inboxes (`GET /v0/inboxes`), limited to the pod.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"x-scoped-copy-of":"inboxes_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Only ephemeral (`true`) or only permanent (`false`) inboxes.","name":"ephemeral","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of inboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_ListInboxesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_inboxes_create","tags":["Inboxes"],"summary":"Create Inbox in Pod","description":"Same as Create Inbox (`POST /v0/inboxes`), limited to the pod.\n\nRequires the `inbox_create` permission.","x-permission":["inbox_create"],"x-scoped-copy-of":"inboxes_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_CreateInboxRequest"}}}},"responses":{"200":{"description":"An inbox with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/availability":{"get":{"operationId":"pods_inboxes_availability","tags":["Inboxes"],"summary":"Check Inbox Availability in Pod","description":"Same as Check Inbox Availability (`GET /v0/inboxes/availability`), limited to the pod.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"x-machinemail":true,"x-scoped-copy-of":"inboxes_availability","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string"},"required":false,"description":"Local part to check.","name":"username","in":"query"},{"schema":{"type":"string"},"required":false,"description":"Domain to check. Defaults to the shared domain.","name":"domain","in":"query"}],"responses":{"200":{"description":"Availability of the address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_InboxAvailability"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/search":{"get":{"operationId":"pods_inboxes_search","tags":["Inboxes"],"summary":"Search Inboxes in Pod","description":"Same as Search Inboxes (`GET /v0/inboxes/search`), limited to the pod.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"x-scoped-copy-of":"inboxes_search","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Text to find in the address or display name (case-insensitive substring).","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"}],"responses":{"200":{"description":"A page of matching inboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_SearchInboxesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}":{"get":{"operationId":"pods_inboxes_get","tags":["Inboxes"],"summary":"Get Inbox in Pod","description":"Same as Get Inbox (`GET /v0/inboxes/{inbox_id}`), limited to the pod.\n\nRequires the `inbox_read` permission.","x-permission":["inbox_read"],"x-scoped-copy-of":"inboxes_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"responses":{"200":{"description":"The inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_inboxes_update","tags":["Inboxes"],"summary":"Update Inbox in Pod","description":"Same as Update Inbox (`PATCH /v0/inboxes/{inbox_id}`), limited to the pod.\n\nRequires the `inbox_update` permission.","x-permission":["inbox_update"],"x-scoped-copy-of":"inboxes_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_UpdateInboxRequest"}}}},"responses":{"200":{"description":"The updated inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inboxes_Inbox"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_inboxes_delete","tags":["Inboxes"],"summary":"Delete Inbox in Pod","description":"Same as Delete Inbox (`DELETE /v0/inboxes/{inbox_id}`), limited to the pod.\n\nRequires the `inbox_delete` permission.","x-permission":["inbox_delete"],"x-scoped-copy-of":"inboxes_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/drafts":{"get":{"operationId":"pods_inboxes_drafts_list","tags":["Drafts"],"summary":"List Drafts in Pod","description":"Same as List Drafts (`GET /v0/inboxes/{inbox_id}/drafts`), limited to the pod.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-scoped-copy-of":"inboxes_drafts_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only drafts created after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of drafts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_ListDraftsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_inboxes_drafts_create","tags":["Drafts"],"summary":"Create Draft in Pod","description":"Same as Create Draft (`POST /v0/inboxes/{inbox_id}/drafts`), limited to the pod.\n\nRequires the `draft_create` permission.","x-permission":["draft_create"],"x-scoped-copy-of":"inboxes_drafts_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_CreateDraftRequest"}}}},"responses":{"200":{"description":"A draft with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its storage (1 GB: messages, drafts and held mail): a draft cannot grow past it (`limit_key: \"storage_bytes\"`). Delete mail or drafts to make room. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable","description":"The draft sets or moves `send_at` and the scheduler is unavailable for a moment: nothing was saved. Retry with backoff."}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/drafts/{draft_id}":{"get":{"operationId":"pods_inboxes_drafts_get","tags":["Drafts"],"summary":"Get Draft in Pod","description":"Same as Get Draft (`GET /v0/inboxes/{inbox_id}/drafts/{draft_id}`), limited to the pod.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-scoped-copy-of":"inboxes_drafts_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"The draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_inboxes_drafts_update","tags":["Drafts"],"summary":"Update Draft in Pod","description":"Same as Update Draft (`PATCH /v0/inboxes/{inbox_id}/drafts/{draft_id}`), limited to the pod.\n\nRequires the `draft_update` permission.","x-permission":["draft_update"],"x-scoped-copy-of":"inboxes_drafts_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_UpdateDraftRequest"}}}},"responses":{"200":{"description":"The updated draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/drafts_Draft"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its storage (1 GB: messages, drafts and held mail): a draft cannot grow past it (`limit_key: \"storage_bytes\"`). Delete mail or drafts to make room. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable","description":"The draft sets or moves `send_at` and the scheduler is unavailable for a moment: nothing was saved. Retry with backoff."}}},"delete":{"operationId":"pods_inboxes_drafts_delete","tags":["Drafts"],"summary":"Delete Draft in Pod","description":"Same as Delete Draft (`DELETE /v0/inboxes/{inbox_id}/drafts/{draft_id}`), limited to the pod.\n\nRequires the `draft_delete` permission.","x-permission":["draft_delete"],"x-scoped-copy-of":"inboxes_drafts_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/drafts/{draft_id}/attachments/{attachment_id}/download":{"get":{"operationId":"pods_inboxes_drafts_downloadAttachment","tags":["Drafts"],"summary":"Download Draft Attachment in Pod","description":"Same as Download Draft Attachment (`GET /v0/inboxes/{inbox_id}/drafts/{draft_id}/attachments/{attachment_id}/download`), limited to the pod.\n\nRequires the `draft_read` permission.","x-permission":["draft_read"],"x-machinemail":true,"x-scoped-copy-of":"inboxes_drafts_downloadAttachment","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"},{"schema":{"type":"string","enum":["attachment","inline"],"default":"attachment"},"required":false,"description":"`inline` previews raster images, PDF and plain text in the browser; every other type downloads regardless.","name":"disposition","in":"query"}],"responses":{"200":{"description":"The attachment bytes","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<ascii name>\"; filename*=UTF-8''<encoded name>` (or `inline; …` for a preview).","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary","description":"The attachment bytes, with the attachment content type."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/drafts/{draft_id}/send":{"post":{"operationId":"pods_inboxes_drafts_send","tags":["Drafts"],"summary":"Send Draft in Pod","description":"Same as Send Draft (`POST /v0/inboxes/{inbox_id}/drafts/{draft_id}/send`), limited to the pod.\n\nRequires the `draft_send` permission.","x-permission":["draft_send"],"x-scoped-copy-of":"inboxes_drafts_send","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/drafts_DraftId"},"required":true,"description":"ID of the draft.","name":"draft_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_UpdateMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/export":{"get":{"operationId":"pods_inboxes_export","tags":["Export"],"summary":"Export Inbox in Pod","description":"Same as Export Inbox (`GET /v0/inboxes/{inbox_id}/export`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"x-scoped-copy-of":"inboxes_export","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","enum":["mbox","jsonl"],"default":"mbox"},"required":false,"description":"`mbox`: every message as raw MIME in one mbox file. `jsonl`: one Message JSON object per line.","name":"format","in":"query"}],"responses":{"200":{"description":"The export","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<inbox_id>.<format>\"`","schema":{"type":"string"}}},"content":{"application/mbox":{"schema":{"type":"string","description":"`format=mbox`: raw MIME messages, each after a `From ` separator line."}},"application/x-ndjson":{"schema":{"type":"string","description":"`format=jsonl`: one Message JSON object per line."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages":{"get":{"operationId":"pods_inboxes_messages_list","tags":["Messages"],"summary":"List Messages in Pod","description":"Same as List Messages (`GET /v0/inboxes/{inbox_id}/messages`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include quarantined messages (trust level `quarantined`).","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: the words must appear in the subject, sender, recipients, body or attachment file names. Combines with the other filters.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ListMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/batch-get":{"post":{"operationId":"pods_inboxes_messages_batchGet","tags":["Messages"],"summary":"Batch Get Messages in Pod","description":"Same as Batch Get Messages (`POST /v0/inboxes/{inbox_id}/messages/batch-get`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_batchGet","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchGetMessagesRequest"}}}},"responses":{"200":{"description":"The messages found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchGetMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/batch-update":{"post":{"operationId":"pods_inboxes_messages_batchUpdate","tags":["Messages"],"summary":"Batch Update Messages in Pod","description":"Same as Batch Update Messages (`POST /v0/inboxes/{inbox_id}/messages/batch-update`), limited to the pod.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"x-scoped-copy-of":"inboxes_messages_batchUpdate","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchUpdateMessagesRequest"}}}},"responses":{"200":{"description":"The updated messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_BatchUpdateMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/search":{"get":{"operationId":"pods_inboxes_messages_search","tags":["Messages"],"summary":"Search Messages in Pod","description":"Same as Search Messages (`GET /v0/inboxes/{inbox_id}/messages/search`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_search","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Words to find in the subject, sender, recipients (to and cc), body text or attachment file names.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only messages before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only messages after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SearchMessagesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/send":{"post":{"operationId":"pods_inboxes_messages_send","tags":["Messages"],"summary":"Send Message in Pod","description":"Same as Send Message (`POST /v0/inboxes/{inbox_id}/messages/send`), limited to the pod.\n\nRequires the `message_send` permission.","x-permission":["message_send"],"x-scoped-copy-of":"inboxes_messages_send","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}":{"get":{"operationId":"pods_inboxes_messages_get","tags":["Messages"],"summary":"Get Message in Pod","description":"Same as Get Message (`GET /v0/inboxes/{inbox_id}/messages/{message_id}`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_Message"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_inboxes_messages_update","tags":["Messages"],"summary":"Update Message in Pod","description":"Same as Update Message (`PATCH /v0/inboxes/{inbox_id}/messages/{message_id}`), limited to the pod.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"x-scoped-copy-of":"inboxes_messages_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_UpdateMessageRequest"}}}},"responses":{"200":{"description":"The updated message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_Message"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_inboxes_messages_delete","tags":["Messages"],"summary":"Delete Message in Pod","description":"Same as Delete Message (`DELETE /v0/inboxes/{inbox_id}/messages/{message_id}`), limited to the pod.\n\nRequires the `message_delete` permission.","x-permission":["message_delete"],"x-scoped-copy-of":"inboxes_messages_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}":{"get":{"operationId":"pods_inboxes_messages_getAttachment","tags":["Messages"],"summary":"Get Attachment in Pod","description":"Same as Get Attachment (`GET /v0/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_getAttachment","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"}],"responses":{"200":{"description":"The attachment with a download URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/attachments_AttachmentResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}/download":{"get":{"operationId":"pods_inboxes_messages_downloadAttachment","tags":["Messages"],"summary":"Download Attachment in Pod","description":"Same as Download Attachment (`GET /v0/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}/download`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"x-scoped-copy-of":"inboxes_messages_downloadAttachment","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"},{"schema":{"$ref":"#/components/schemas/attachments_AttachmentId"},"required":true,"description":"ID of the attachment.","name":"attachment_id","in":"path"},{"schema":{"type":"string","enum":["attachment","inline"],"default":"attachment"},"required":false,"description":"`inline` previews raster images, PDF and plain text in the browser; every other type downloads regardless.","name":"disposition","in":"query"}],"responses":{"200":{"description":"The attachment bytes","headers":{"Content-Disposition":{"description":"`attachment; filename=\"<ascii name>\"; filename*=UTF-8''<encoded name>` (or `inline; …` for a preview).","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary","description":"The attachment bytes, with the attachment content type."}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/forward":{"post":{"operationId":"pods_inboxes_messages_forward","tags":["Messages"],"summary":"Forward Message in Pod","description":"Same as Forward Message (`POST /v0/inboxes/{inbox_id}/messages/{message_id}/forward`), limited to the pod.\n\nRequires the `message_send` permission.","x-permission":["message_send"],"x-scoped-copy-of":"inboxes_messages_forward","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/raw":{"get":{"operationId":"pods_inboxes_messages_getRaw","tags":["Messages"],"summary":"Get Raw Message in Pod","description":"Same as Get Raw Message (`GET /v0/inboxes/{inbox_id}/messages/{message_id}/raw`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-scoped-copy-of":"inboxes_messages_getRaw","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The raw message","content":{"message/rfc822":{"schema":{"type":"string","format":"binary","description":"RFC 5322 message bytes."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/reply":{"post":{"operationId":"pods_inboxes_messages_reply","tags":["Messages"],"summary":"Reply To Message in Pod","description":"Same as Reply To Message (`POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply`), limited to the pod.\n\nRequires the `message_reply` or `message_send` permission.","x-permission":["message_reply","message_send"],"x-scoped-copy-of":"inboxes_messages_reply","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ReplyToMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/reply-all":{"post":{"operationId":"pods_inboxes_messages_reply-all","tags":["Messages"],"summary":"Reply All Message in Pod","description":"Same as Reply All Message (`POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply-all`), limited to the pod.\n\nRequires the `message_reply` or `message_send` permission.","x-permission":["message_reply","message_send"],"x-scoped-copy-of":"inboxes_messages_reply-all","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_ReplyAllMessageRequest"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/messages_SendMessageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan over its messages cap: 3,000 a month or 100 a day, inbound messages and outbound recipients together (each recipient counts once). `error.limit_key` is `messages_per_month` or `messages_per_day`; `resets_at` and `Retry-After` say when the allowance resets (absent when this message has more recipients than the cap itself). Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited","description":"Unclaimed sandbox agent over a send cap: at most 10 messages to at most 10 different recipients per rolling 24 hours. `Retry-After` says when the next send fits. Claiming the inbox lifts the caps. Also returned when a Free organization goes over its daily number of different recipients."},"500":{"$ref":"#/components/responses/InternalError"},"501":{"$ref":"#/components/responses/NotImplemented"},"502":{"$ref":"#/components/responses/UpstreamError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/messages/{message_id}/trust":{"get":{"operationId":"pods_inboxes_messages_getTrust","tags":["Trust"],"summary":"Get Message Trust Report in Pod","description":"Same as Get Message Trust Report (`GET /v0/inboxes/{inbox_id}/messages/{message_id}/trust`), limited to the pod.\n\nRequires the `message_read` permission.","x-permission":["message_read"],"x-machinemail":true,"x-scoped-copy-of":"inboxes_messages_getTrust","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/messages_MessageId"},"required":true,"description":"ID of the message.","name":"message_id","in":"path"}],"responses":{"200":{"description":"The trust report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrustReport"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/threads":{"get":{"operationId":"pods_inboxes_threads_list","tags":["Threads"],"summary":"List Threads in Pod","description":"Same as List Threads (`GET /v0/inboxes/{inbox_id}/threads`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"inboxes_threads_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ListThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/threads/search":{"get":{"operationId":"pods_inboxes_threads_search","tags":["Threads"],"summary":"Search Threads in Pod","description":"Same as Search Threads (`GET /v0/inboxes/{inbox_id}/threads/search`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"inboxes_threads_search","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only threads with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_SearchThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/inboxes/{inbox_id}/threads/{thread_id}":{"get":{"operationId":"pods_inboxes_threads_get","tags":["Threads"],"summary":"Get Thread in Pod","description":"Same as Get Thread (`GET /v0/inboxes/{inbox_id}/threads/{thread_id}`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"inboxes_threads_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of messages to return. Default and maximum 500.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous response: the next, older page of messages.","name":"page_token","in":"query"}],"responses":{"200":{"description":"The thread with a page of its messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_Thread"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_inboxes_threads_update","tags":["Threads"],"summary":"Update Thread in Pod","description":"Same as Update Thread (`PATCH /v0/inboxes/{inbox_id}/threads/{thread_id}`), limited to the pod.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"x-scoped-copy-of":"inboxes_threads_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_UpdateThreadRequest"}}}},"responses":{"200":{"description":"The updated thread, without messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ThreadItem"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_inboxes_threads_delete","tags":["Threads"],"summary":"Delete Thread in Pod","description":"Same as Delete Thread (`DELETE /v0/inboxes/{inbox_id}/threads/{thread_id}`), limited to the pod.\n\nRequires the `thread_delete` permission.","x-permission":["thread_delete"],"x-scoped-copy-of":"inboxes_threads_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/inboxes_InboxId"},"required":true,"description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`).","name":"inbox_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/lists/{direction}/{type}":{"get":{"operationId":"pods_lists_list","tags":["Lists"],"summary":"List Entries in Pod","description":"Same as List Entries (`GET /v0/lists/{direction}/{type}`), limited to the pod. While any allow entry applies for a direction, every address that matches none is blocked (allow-only).\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-scoped-copy-of":"lists_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"`false` sorts by entry descending. Default `true`.","name":"ascending","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListListEntriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_lists_create","tags":["Lists"],"summary":"Create List Entry in Pod","description":"Same as Create List Entry (`POST /v0/lists/{direction}/{type}`), limited to the pod. A `receive/allow` entry here makes this scope allow-only: mail from every sender that matches no allow entry is labeled `BLOCKED` and withheld from agents. An allow-listed sender reaches `verified` only with an aligned DMARC pass.\n\nRequires the `list_entry_create` permission.","x-permission":["list_entry_create"],"x-scoped-copy-of":"lists_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_CreateListEntryRequest"}}}},"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/lists/{direction}/{type}/{entry}":{"get":{"operationId":"pods_lists_get","tags":["Lists"],"summary":"Get List Entry in Pod","description":"Same as Get List Entry (`GET /v0/lists/{direction}/{type}/{entry}`), limited to the pod.\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-scoped-copy-of":"lists_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/lists_ListEntry"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_lists_delete","tags":["Lists"],"summary":"Delete List Entry in Pod","description":"Same as Delete List Entry (`DELETE /v0/lists/{direction}/{type}/{entry}`), limited to the pod.\n\nRequires the `list_entry_delete` permission.","x-permission":["list_entry_delete"],"x-scoped-copy-of":"lists_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_Direction"},"required":true,"description":"`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.","name":"direction","in":"path"},{"schema":{"$ref":"#/components/schemas/lists_ListType"},"required":true,"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass.","name":"type","in":"path"},{"schema":{"type":"string"},"required":true,"description":"Email address or domain.","name":"entry","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/metrics":{"get":{"operationId":"pods_metrics_queryEventsAlias","tags":["Metrics"],"summary":"Query Events (alias) in Pod","description":"Same as Query Events (alias) (`GET /v0/metrics`), limited to the pod.\n\nRequires the `metrics_read` permission.","deprecated":true,"x-permission":["metrics_read"],"x-machinemail":true,"x-scoped-copy-of":"metrics_queryEventsAlias","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/metrics/events":{"get":{"operationId":"pods_metrics_queryEvents","tags":["Metrics"],"summary":"Query Events in Pod","description":"Same as Query Events (`GET /v0/metrics/events`), limited to the pod.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryEvents","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Event types to count: `message.received`, `message.received.spam`, `message.received.blocked`, `message.received.unauthenticated`, `message.received.quarantined`, `message.sent`, `message.delivered`, `message.bounced`, `message.complained`, `message.rejected`, `domain.verified` (the default is all of them). `message.received` counts every inbound message, including the `message.received.*` sub-types, which are also reported under their own keys. Other values give a series of zeros.","name":"event_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets.","name":"period","in":"query"}],"responses":{"200":{"description":"Event counts by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/metrics/rates":{"get":{"operationId":"pods_metrics_queryRates","tags":["Metrics"],"summary":"Query Rates in Pod","description":"Same as Query Rates (`GET /v0/metrics/rates`), limited to the pod.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryRates","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Rate types: `bounce`, `complaint`. Default: both. Another value is a `400`.","name":"rate_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points.","name":"period","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"How far back each point looks, in seconds: a whole multiple of `period`, at most 2592000 (30 days). Default 86400 when that is a multiple of `period`, otherwise `period`.","name":"window","in":"query"}],"responses":{"200":{"description":"Rates by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryRatesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/metrics/usage":{"get":{"operationId":"pods_metrics_queryUsage","tags":["Metrics"],"summary":"Query Usage in Pod","description":"Same as Query Usage (`GET /v0/metrics/usage`), limited to the pod.\n\nRequires the `metrics_read` permission.","x-permission":["metrics_read"],"x-scoped-copy-of":"metrics_queryUsage","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Usage types: `storage_bytes`, `message_count`, `thread_count`, `inbox_count`, `pod_count`, `domain_count`. Default: all. Another value is a `400`.","name":"usage_types","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Start of the range. Default: 24 hours before `end`.","name":"start","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"End of the range. Default: now; a later time is clamped to now.","name":"end","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Return at most this many points per series.","name":"limit","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Newest point first.","name":"descending","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period.","name":"period","in":"query"}],"responses":{"200":{"description":"Usage by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/metrics_QueryUsageResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/threads":{"get":{"operationId":"pods_threads_list","tags":["Threads"],"summary":"List Threads in Pod","description":"Same as List Threads (`GET /v0/threads`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"threads_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ListThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/threads/search":{"get":{"operationId":"pods_threads_search","tags":["Threads"],"summary":"Search Threads in Pod","description":"Same as Search Threads (`GET /v0/threads/search`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"threads_search","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only threads with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_SearchThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/threads/{thread_id}":{"get":{"operationId":"pods_threads_get","tags":["Threads"],"summary":"Get Thread in Pod","description":"Same as Get Thread (`GET /v0/threads/{thread_id}`), limited to the pod.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"x-scoped-copy-of":"threads_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of messages to return. Default and maximum 500.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous response: the next, older page of messages.","name":"page_token","in":"query"}],"responses":{"200":{"description":"The thread with a page of its messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_Thread"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_threads_update","tags":["Threads"],"summary":"Update Thread in Pod","description":"Same as Update Thread (`PATCH /v0/threads/{thread_id}`), limited to the pod.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"x-scoped-copy-of":"threads_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_UpdateThreadRequest"}}}},"responses":{"200":{"description":"The updated thread, without messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ThreadItem"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_threads_delete","tags":["Threads"],"summary":"Delete Thread in Pod","description":"Same as Delete Thread (`DELETE /v0/threads/{thread_id}`), limited to the pod.\n\nRequires the `thread_delete` permission.","x-permission":["thread_delete"],"x-scoped-copy-of":"threads_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/trusted-domains":{"get":{"operationId":"pods_trustedDomains_list","tags":["Trusted Domains"],"summary":"List Trusted Domains in Pod","description":"Same as List Trusted Domains (`GET /v0/trusted-domains`), limited to the pod.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of trusted domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_ListTrustedDomainsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_trustedDomains_create","tags":["Trusted Domains"],"summary":"Create Trusted Domain in Pod","description":"Same as Create Trusted Domain (`POST /v0/trusted-domains`), limited to the pod.\n\nRequires the `trusted_domain_create` permission.","x-permission":["trusted_domain_create"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The existing entry for this domain or `client_id`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"The organization already has as many trusted domains as its plan allows (`limit_key: \"trusted_domains\"`): 10 on Free, 500 on paid plans, none for unclaimed sandbox agents. Remove one first."},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_create`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict","description":"`client_id` is already used at another level."},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"`trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/trusted-domains/preview":{"post":{"operationId":"pods_trustedDomains_preview","tags":["Trusted Domains"],"summary":"Preview Trusted Domain in Pod","description":"Same as Preview Trusted Domain (`POST /v0/trusted-domains/preview`), limited to the pod.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_preview","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainRequest"}}}},"responses":{"200":{"description":"The preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/trusted-domains/{trusted_domain_id}":{"get":{"operationId":"pods_trustedDomains_get","tags":["Trusted Domains"],"summary":"Get Trusted Domain in Pod","description":"Same as Get Trusted Domain (`GET /v0/trusted-domains/{trusted_domain_id}`), limited to the pod.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_trustedDomains_update","tags":["Trusted Domains"],"summary":"Update Trusted Domain in Pod","description":"Same as Update Trusted Domain (`PATCH /v0/trusted-domains/{trusted_domain_id}`), limited to the pod.\n\nRequires the `trusted_domain_update` permission.","x-permission":["trusted_domain_update"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_UpdateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The updated entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_update`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"Turning on `include_subdomains`: `trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_trustedDomains_delete","tags":["Trusted Domains"],"summary":"Delete Trusted Domain in Pod","description":"Same as Delete Trusted Domain (`DELETE /v0/trusted-domains/{trusted_domain_id}`), limited to the pod.\n\nRequires the `trusted_domain_delete` permission.","x-permission":["trusted_domain_delete"],"x-machinemail":true,"x-scoped-copy-of":"trustedDomains_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks":{"get":{"operationId":"pods_webhooks_list","tags":["Webhooks"],"summary":"List Webhooks in Pod","description":"Same as List Webhooks (`GET /v0/webhooks`), limited to the pod.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of webhooks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListWebhooksResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"pods_webhooks_create","tags":["Webhooks"],"summary":"Create Webhook in Pod","description":"Same as Create Webhook (`POST /v0/webhooks`), limited to the pod.\n\nRequires the `webhook_create` permission.","x-permission":["webhook_create"],"x-scoped-copy-of":"webhooks_create","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_CreateWebhookRequest"}}}},"responses":{"200":{"description":"A webhook with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks/{webhook_id}":{"get":{"operationId":"pods_webhooks_get","tags":["Webhooks"],"summary":"Get Webhook in Pod","description":"Same as Get Webhook (`GET /v0/webhooks/{webhook_id}`), limited to the pod.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_get","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_webhooks_update","tags":["Webhooks"],"summary":"Update Webhook in Pod","description":"Same as Update Webhook (`PATCH /v0/webhooks/{webhook_id}`), limited to the pod.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-scoped-copy-of":"webhooks_update","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookRequest"}}}},"responses":{"200":{"description":"The updated webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"pods_webhooks_delete","tags":["Webhooks"],"summary":"Delete Webhook in Pod","description":"Same as Delete Webhook (`DELETE /v0/webhooks/{webhook_id}`), limited to the pod.\n\nRequires the `webhook_delete` permission.","x-permission":["webhook_delete"],"x-scoped-copy-of":"webhooks_delete","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks/{webhook_id}/deliveries":{"get":{"operationId":"pods_webhooks_deliveries_list","tags":["Webhooks"],"summary":"List Deliveries in Pod","description":"Same as List Deliveries (`GET /v0/webhooks/{webhook_id}/deliveries`), limited to the pod.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_deliveries_list","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"string","enum":["pending","delivered","failed"]},"required":false,"description":"Only deliveries with this status.","name":"status","in":"query"}],"responses":{"200":{"description":"A page of deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListDeliveriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/replay":{"post":{"operationId":"pods_webhooks_deliveries_replay","tags":["Webhooks"],"summary":"Replay Delivery in Pod","description":"Same as Replay Delivery (`POST /v0/webhooks/{webhook_id}/deliveries/{delivery_id}/replay`), limited to the pod.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_deliveries_replay","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the delivery to replay.","name":"delivery_id","in":"path"}],"responses":{"200":{"description":"The new delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks/{webhook_id}/headers":{"get":{"operationId":"pods_webhooks_getHeaders","tags":["Webhooks"],"summary":"Get Webhook Headers in Pod","description":"Same as Get Webhook Headers (`GET /v0/webhooks/{webhook_id}/headers`), limited to the pod.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-scoped-copy-of":"webhooks_getHeaders","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The header names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookHeaderNamesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"pods_webhooks_updateHeaders","tags":["Webhooks"],"summary":"Update Webhook Headers in Pod","description":"Same as Update Webhook Headers (`PATCH /v0/webhooks/{webhook_id}/headers`), limited to the pod.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-scoped-copy-of":"webhooks_updateHeaders","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookHeadersRequest"}}}},"responses":{"204":{"description":"Updated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/pods/{pod_id}/webhooks/{webhook_id}/test":{"post":{"operationId":"pods_webhooks_test","tags":["Webhooks"],"summary":"Send Test Event in Pod","description":"Same as Send Test Event (`POST /v0/webhooks/{webhook_id}/test`), limited to the pod.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"x-scoped-copy-of":"webhooks_test","parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the pod.","name":"pod_id","in":"path"},{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The test delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/suppressions":{"get":{"operationId":"suppressions_list","tags":["Suppressions"],"summary":"List Suppressions","description":"Every suppressed address in the organization (also for pod and inbox credentials). Addresses are added automatically on permanent bounces and complaints.\n\nRequires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of suppressions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/suppressions_ListSuppressionsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"suppressions_create","tags":["Suppressions"],"summary":"Add Suppression","description":"Suppress an address for the whole organization, with `reason: \"manual\"`. Adding an address that is already suppressed replaces a `bounce` or `manual` suppression (its `reason` becomes `manual`); a `complaint` suppression is returned unchanged. Sends to a suppressed address return `403`.\n\nRequires the `list_entry_create` permission.","x-permission":["list_entry_create"],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/suppressions_CreateSuppressionRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/suppressions_Suppression"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/suppressions/{email}":{"get":{"operationId":"suppressions_get","tags":["Suppressions"],"summary":"Get Suppression","description":"Requires the `list_entry_read` permission.","x-permission":["list_entry_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"The suppressed address (URL-encoded).","name":"email","in":"path"}],"responses":{"200":{"description":"The suppression","content":{"application/json":{"schema":{"$ref":"#/components/schemas/suppressions_Suppression"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"suppressions_delete","tags":["Suppressions"],"summary":"Remove Suppression","description":"Allow sending to the address again. Organization-scoped credentials only: pod and inbox credentials get `403`. Only `bounce` and `manual` suppressions can be removed: a `complaint` suppression returns `403` (`Complaint suppressions can only be removed by MachineMail support; email support@machinemail.dev`).\n\nRequires the `list_entry_delete` permission.","x-permission":["list_entry_delete"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"The suppressed address (URL-encoded).","name":"email","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/threads":{"get":{"operationId":"threads_list","tags":["Threads"],"summary":"List Threads","description":"Threads, most recently active first. Pass `q` to keep only threads with a message matching the words.\n\nThreads with a spam, blocked, trash, quarantined or unauthenticated message are hidden unless you pass the matching `include_*` flag or ask for the label in `labels`.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only items with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true},{"schema":{"type":"string"},"required":false,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ListThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/threads/search":{"get":{"operationId":"threads_search","tags":["Threads"],"summary":"Search Threads","description":"Threads with a message whose subject, sender, recipients, body or attachment file names contain every word of `q`, ordered by thread activity (not ranked by relevance). Scans the newest 500 matching messages; the response has `truncated: true` when it hit that cap.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"description":"Full-text filter: threads with a message whose subject, sender, recipients, body or attachment file names contain the words. Scans the newest 500 matching messages.","name":"q","in":"query"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp before this time.","name":"before","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"description":"Only items with a timestamp after this time.","name":"after","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query","x-machinemail":true},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"description":"Only threads with any of these labels. Asking for SPAM, BLOCKED, TRASH, QUARANTINE or UNAUTHENTICATED includes them.","name":"labels","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with spam (needs `label_spam_read`; ignored without it).","name":"include_spam","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with blocked mail (needs `label_blocked_read`; ignored without it).","name":"include_blocked","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with unauthenticated mail (needs `label_unauthenticated_read`; ignored without it).","name":"include_unauthenticated","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads with trash (needs `label_trash_read`; ignored without it).","name":"include_trash","in":"query","x-machinemail":true},{"schema":{"type":"boolean"},"required":false,"description":"Include threads that have a quarantined message.","name":"include_quarantine","in":"query","x-machinemail":true}],"responses":{"200":{"description":"A page of matching threads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_SearchThreadsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/threads/{thread_id}":{"get":{"operationId":"threads_get","tags":["Threads"],"summary":"Get Thread","description":"The thread with its messages, which carry their bodies and trust reports. Messages come in pages of `limit` (default and maximum 500): the first page has the newest messages, oldest first within the page; follow `next_page_token` for older ones.\n\nRequires the `thread_read` permission.","x-permission":["thread_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of messages to return. Default and maximum 500.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous response: the next, older page of messages.","name":"page_token","in":"query"}],"responses":{"200":{"description":"The thread with a page of its messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_Thread"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"threads_update","tags":["Threads"],"summary":"Update Thread","description":"Adds and removes labels on every message in the thread (up to 500 messages); the thread labels are their union. Labels are free strings, system labels included. Returns the updated thread without messages.\n\nRequires the `message_update` permission.","x-permission":["message_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_UpdateThreadRequest"}}}},"responses":{"200":{"description":"The updated thread, without messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/threads_ThreadItem"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"Free plan: removing `SPAM` or `QUARANTINE` makes the message count toward the messages cap and storage from now on, and the organization is over one (`limit_key` `messages_per_month`, `messages_per_day` or `storage_bytes`). The labels are unchanged. Paid plans are never refused."},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"threads_delete","tags":["Threads"],"summary":"Delete Thread","description":"Permanently deletes the thread and its messages (up to 500).\n\nRequires the `thread_delete` permission.","x-permission":["thread_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/threads_ThreadId"},"required":true,"description":"ID of the thread.","name":"thread_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/trusted-domains":{"get":{"operationId":"trustedDomains_list","tags":["Trusted Domains"],"summary":"List Trusted Domains","description":"Entries stored at exactly this level: `/v0/trusted-domains` lists the organization entries, `/v0/pods/{pod_id}/trusted-domains` a pod’s, `/v0/inboxes/{inbox_id}/trusted-domains` an inbox’s. Mail to an inbox is judged against all three.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of trusted domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_ListTrustedDomainsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"trustedDomains_create","tags":["Trusted Domains"],"summary":"Create Trusted Domain","description":"Trust a domain (`example.com`) or one address (`invoices@example.com`) at this level. Domains are stored in ASCII (punycode) form; responses carry both forms. Adding an entry that exists at this level (the same domain, or the same `client_id`) returns it unchanged with `200`.\n\nTrust takes effect only on mail that carries a DKIM signature of the trusted domain itself (`d=` equal to the domain, or a subdomain with `include_subdomains`); a block entry always wins over trust, and an allow-only scope still blocks every sender it does not allow.\n\nConflicts with block entries and allow-only scopes do not refuse the entry: they are returned as `warnings`.\n\nRefused with `422`: `trusted_domain_not_allowed` for names anyone can get mail from (`error.reason`: `free_mail`, `privacy_relay`, `shared_platform`, `public_suffix`, `disposable`, `invalid`, `confusable_idn`); `confirmation_required` 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`), until you resend with `confirm: true`. An address on a free mail provider (`someone@gmail.com`) can be trusted.\n\nRefused with `402` `plan_limit_exceeded` (`limit_key: \"trusted_domains\"`) past the organization’s limit: 10 on Free, 500 on paid plans, none for unclaimed sandbox agents. Entries at every level count.\n\nOnly an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain.\n\nRequires the `trusted_domain_create` permission.","x-permission":["trusted_domain_create"],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The existing entry for this domain or `client_id`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimitExceeded","description":"The organization already has as many trusted domains as its plan allows (`limit_key: \"trusted_domains\"`): 10 on Free, 500 on paid plans, none for unclaimed sandbox agents. Remove one first."},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_create`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"409":{"$ref":"#/components/responses/Conflict","description":"`client_id` is already used at another level."},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"`trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/trusted-domains/preview":{"post":{"operationId":"trustedDomains_preview","tags":["Trusted Domains"],"summary":"Preview Trusted Domain","description":"What creating this entry at this level would do, without saving anything: whether it is allowed (and if not, why), whether it needs `confirm: true`, and its warnings. For validating as someone types. `would_release` and `suggestions` are not computed yet and are always `null`.\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainRequest"}}}},"responses":{"200":{"description":"The preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_PreviewTrustedDomainResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/trusted-domains/{trusted_domain_id}":{"get":{"operationId":"trustedDomains_get","tags":["Trusted Domains"],"summary":"Get Trusted Domain","description":"An entry stored at this level (`404` for entries at another level).\n\nRequires the `trusted_domain_read` permission.","x-permission":["trusted_domain_read"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"trustedDomains_update","tags":["Trusted Domains"],"summary":"Update Trusted Domain","description":"Change `include_subdomains`, `reason` or `expires_at`. The domain and level are fixed: delete and create to change them. Turning on `include_subdomains` is checked like a create with it: refused (`422 trusted_domain_not_allowed`) when a privacy relay or MachineMail shared domain lies under the domain, and `422 confirmation_required` until you send `confirm: true` when a platform where anyone can write the content does. Returns the entry with its current `warnings`. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain.\n\nRequires the `trusted_domain_update` permission.","x-permission":["trusted_domain_update"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_UpdateTrustedDomainRequest"}}}},"responses":{"200":{"description":"The updated entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/trustedDomains_CreatedTrustedDomain"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden","description":"The credential lacks `trusted_domain_update`, or is not an organization API key or a dashboard session. Only an organization API key or a dashboard session can add or change an entry: pod and inbox keys, OAuth apps and agent access tokens get `403`, whatever their permissions, so an agent cannot be talked into trusting a domain."},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/TrustedDomainNotAllowed","description":"Turning on `include_subdomains`: `trusted_domain_not_allowed` (with `error.reason`) or `confirmation_required` (resend with `confirm: true`)."},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"trustedDomains_delete","tags":["Trusted Domains"],"summary":"Delete Trusted Domain","description":"Mail from the domain is judged normally again from now on. Any credential with `trusted_domain_delete` that can see the entry may remove it.\n\nRequires the `trusted_domain_delete` permission.","x-permission":["trusted_domain_delete"],"x-machinemail":true,"parameters":[{"schema":{"type":"string"},"required":true,"description":"ID of the entry (`td_...`).","name":"trusted_domain_id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks":{"get":{"operationId":"webhooks_list","tags":["Webhooks"],"summary":"List Webhooks","description":"With an organization credential, every webhook of the organization, paginated. With a pod or inbox credential (or under a scoped path), the webhooks in that scope from the newest 500, in one page without `next_page_token`.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"parameters":[{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"}],"responses":{"200":{"description":"A page of webhooks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListWebhooksResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"webhooks_create","tags":["Webhooks"],"summary":"Create Webhook","description":"The response includes `secret` (`whsec_...`), the key of the `X-MachineMail-Signature` HMAC. See the `webhooks` section of this document for the request MachineMail sends for each event type.\n\nUnder `/v0/pods/{pod_id}` or `/v0/inboxes/{inbox_id}`, or with a pod- or inbox-scoped credential, the webhook belongs to that pod or inbox (`pod_id`, `inbox_id`) and never receives events outside it.\n\nA webhook delivers no event its creator could not read: each listed event type needs its read permission (`message.*` needs `message_read`, `inbox.*` `inbox_read`, `domain.*` `domain_read`, `draft.*` `draft_read`, `webhook.test` `webhook_read`), else `403`. An empty `event_types` from a credential without all of them is stored as the types it may read (`403` when there are none).\n\nCustom request headers in `headers` are sent with every delivery (for example `Authorization: Bearer <token>` for an endpoint that requires it). Their values are write-only: responses list only `header_names`.\n\nRequires the `webhook_create` permission.","x-permission":["webhook_create"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_CreateWebhookRequest"}}}},"responses":{"200":{"description":"A webhook with this `client_id` already exists; it is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks/{webhook_id}":{"get":{"operationId":"webhooks_get","tags":["Webhooks"],"summary":"Get Webhook","description":"Requires the `webhook_read` permission.","x-permission":["webhook_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"webhooks_update","tags":["Webhooks"],"summary":"Update Webhook","description":"Fields you omit are unchanged. Webhooks are never disabled automatically after failed deliveries; `enabled: false` is the only way to disable one. New `event_types` follow the same permission rule as `POST /v0/webhooks`, and changing `url` needs the read permission of every event type the webhook delivers (`403` otherwise).\n\n`headers` replaces the custom delivery headers in full, `null` or `{}` removes them, and omitting it keeps them. While a webhook has custom headers, changing `url` to another origin (scheme, host or port) needs `headers` in the same request (`400` otherwise), so header values never follow the webhook to a new server unless you send them again.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookRequest"}}}},"responses":{"200":{"description":"The updated webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_Webhook"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"webhooks_delete","tags":["Webhooks"],"summary":"Delete Webhook","description":"Requires the `webhook_delete` permission.","x-permission":["webhook_delete"],"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks/{webhook_id}/deliveries":{"get":{"operationId":"webhooks_deliveries_list","tags":["Webhooks"],"summary":"List Deliveries","description":"Delivery attempts of the webhook, one per event (a replay is a new delivery).\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"integer"},"required":false,"description":"Maximum number of items to return. Default 50, maximum 500; larger values are capped.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"description":"`next_page_token` from the previous page.","name":"page_token","in":"query"},{"schema":{"type":"boolean"},"required":false,"description":"Sort oldest first.","name":"ascending","in":"query"},{"schema":{"type":"string","enum":["pending","delivered","failed"]},"required":false,"description":"Only deliveries with this status.","name":"status","in":"query"}],"responses":{"200":{"description":"A page of deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_ListDeliveriesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks/{webhook_id}/deliveries/{delivery_id}/replay":{"post":{"operationId":"webhooks_deliveries_replay","tags":["Webhooks"],"summary":"Replay Delivery","description":"Queues a new delivery of the same event to the webhook and attempts it right away, even when the webhook is disabled. Returns the new delivery after that attempt.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"},{"schema":{"type":"string"},"required":true,"description":"ID of the delivery to replay.","name":"delivery_id","in":"path"}],"responses":{"200":{"description":"The new delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks/{webhook_id}/headers":{"get":{"operationId":"webhooks_getHeaders","tags":["Webhooks"],"summary":"Get Webhook Headers","description":"Names of the custom HTTP headers sent with every delivery to this webhook. Values are write-only and never returned.\n\nRequires the `webhook_read` permission.","x-permission":["webhook_read"],"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The header names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookHeaderNamesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"webhooks_updateHeaders","tags":["Webhooks"],"summary":"Update Webhook Headers","description":"Sets, replaces or removes custom delivery headers in one atomic change; headers you do not name keep their values. To replace the whole set (or clear it), use `headers` on `PATCH /v0/webhooks/{webhook_id}`. Values remain write-only.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_UpdateWebhookHeadersRequest"}}}},"responses":{"204":{"description":"Updated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/webhooks/{webhook_id}/test":{"post":{"operationId":"webhooks_test","tags":["Webhooks"],"summary":"Send Test Event","description":"Records a `webhook.test` event and delivers it to this webhook only (whatever its `event_types`, even when disabled), then returns the delivery after the first attempt.\n\nRequires the `webhook_update` permission.","x-permission":["webhook_update"],"x-machinemail":true,"parameters":[{"schema":{"$ref":"#/components/schemas/webhooks_WebhookId"},"required":true,"description":"ID of the webhook.","name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The test delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v0/ws":{"get":{"operationId":"events_ws","tags":["Events"],"summary":"WebSocket Event Stream","description":"Upgrades to a WebSocket (send `Connection: Upgrade` and `Upgrade: websocket`). The socket starts subscribed to every event in the credential scope; query parameters are not read.\n\nClient messages are JSON: `{\"type\":\"subscribe\",\"inbox_ids\":[...],\"pod_ids\":[...],\"event_types\":[...]}` replaces the subscription (the server answers `{\"type\":\"subscribed\",\"inbox_ids\",\"pod_ids\",\"event_types\"}`), `{\"type\":\"ping\"}` is answered with `{\"type\":\"pong\"}`, anything else with `{\"type\":\"error\",\"message\"}`. Event messages are the webhook event envelope (`type: \"event\"`, `event_id`, `event_type`, `timestamp`, `data`, and the `data` keys repeated at the top level), not the `Event` object of `GET /v0/events`.\n\nEach event is sent only when the credential holds the read permission of what it describes: `message.*` needs `message_read`, `domain.*` needs `domain_read`, `inbox.*` needs `inbox_read`, `draft.*` needs `draft_read`, `webhook.*` needs `webhook_read`, `trusted_domain.*` needs `trusted_domain_read`. Other events are skipped, without an error, and `event_types` cannot add them. The credential is re-checked every 30 seconds: when it is revoked or expired, or its permissions or pod/inbox scope change, the stream ends with an error (reconnect to get the events the credential allows now).\n\nOpening the socket needs at least one of those permissions; a credential with none is refused with `403`. A request without the upgrade headers is a `404`.\n\nThe server closes the socket with code `1012` when it may have missed events from other servers (its notification connection to the database was interrupted): reconnect and refetch, since the WebSocket has no replay.\n\nRequires the `message_read` or `domain_read` or `inbox_read` or `draft_read` or `webhook_read` or `trusted_domain_read` permission.","security":[{"Bearer":[]},{"SessionCookie":[]},{"QueryToken":[]}],"x-permission":["message_read","domain_read","inbox_read","draft_read","webhook_read","trusted_domain_read"],"x-machinemail":true,"responses":{"101":{"description":"Switching Protocols: the connection is now a WebSocket."},"400":{"description":"The WebSocket handshake failed (plain text `WebSocket upgrade failed`).","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"The credential holds no permission the stream serves events for (plain text `Forbidden`).","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"webhooks":{"domain.updated":{"post":{"operationId":"webhooks_events_domainUpdated","summary":"Domain Updated","description":"POSTed to webhooks subscribed to `domain.updated`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_DomainUpdatedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"domain.verified":{"post":{"operationId":"webhooks_events_domainVerified","summary":"Domain Verified","description":"POSTed to webhooks subscribed to `domain.verified`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_DomainVerifiedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"draft.sent":{"post":{"operationId":"webhooks_events_draftSent","summary":"Draft Sent","description":"POSTed to webhooks subscribed to `draft.sent`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_DraftSentEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"inbox.created":{"post":{"operationId":"webhooks_events_inboxCreated","summary":"Inbox Created","description":"POSTed to webhooks subscribed to `inbox.created`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_InboxCreatedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"inbox.expired":{"post":{"operationId":"webhooks_events_inboxExpired","summary":"Inbox Expired","description":"POSTed to webhooks subscribed to `inbox.expired`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_InboxExpiredEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.bounced":{"post":{"operationId":"webhooks_events_messageBounced","summary":"Message Bounced","description":"POSTed to webhooks subscribed to `message.bounced`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageBouncedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.complained":{"post":{"operationId":"webhooks_events_messageComplained","summary":"Message Complained","description":"POSTed to webhooks subscribed to `message.complained`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageComplainedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.delivered":{"post":{"operationId":"webhooks_events_messageDelivered","summary":"Message Delivered","description":"POSTed to webhooks subscribed to `message.delivered`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageDeliveredEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.received":{"post":{"operationId":"webhooks_events_messageReceived","summary":"Message Received","description":"POSTed to webhooks subscribed to `message.received`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageReceivedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.received.blocked":{"post":{"operationId":"webhooks_events_messageReceivedBlocked","summary":"Message Received (Blocked)","description":"POSTed to webhooks subscribed to `message.received.blocked`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageReceivedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.received.quarantined":{"post":{"operationId":"webhooks_events_messageReceivedQuarantined","summary":"Message Received (Quarantined)","description":"POSTed to webhooks subscribed to `message.received.quarantined`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageReceivedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.received.spam":{"post":{"operationId":"webhooks_events_messageReceivedSpam","summary":"Message Received (Spam)","description":"POSTed to webhooks subscribed to `message.received.spam`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageReceivedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.received.unauthenticated":{"post":{"operationId":"webhooks_events_messageReceivedUnauthenticated","summary":"Message Received (Unauthenticated)","description":"POSTed to webhooks subscribed to `message.received.unauthenticated`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageReceivedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.rejected":{"post":{"operationId":"webhooks_events_messageRejected","summary":"Message Rejected","description":"POSTed to webhooks subscribed to `message.rejected`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageRejectedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"message.sent":{"post":{"operationId":"webhooks_events_messageSent","summary":"Message Sent","description":"POSTed to webhooks subscribed to `message.sent`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_MessageSentEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"trusted_domain.created":{"post":{"operationId":"webhooks_events_trustedDomainCreated","summary":"Trusted Domain Created","description":"POSTed to webhooks subscribed to `trusted_domain.created`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_TrustedDomainCreatedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"trusted_domain.deleted":{"post":{"operationId":"webhooks_events_trustedDomainDeleted","summary":"Trusted Domain Deleted","description":"POSTed to webhooks subscribed to `trusted_domain.deleted`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_TrustedDomainDeletedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"trusted_domain.updated":{"post":{"operationId":"webhooks_events_trustedDomainUpdated","summary":"Trusted Domain Updated","description":"POSTed to webhooks subscribed to `trusted_domain.updated`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_TrustedDomainUpdatedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"webhook.test":{"post":{"operationId":"webhooks_events_webhookTest","summary":"Webhook Test","description":"POSTed to webhooks subscribed to `webhook.test`. Respond with a 2xx within 10 seconds; anything else (or no answer) is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, then daily, until 5 days after the event. Redirects are not followed. Delivery is at least once: dedupe on `X-MachineMail-Event-Id`.","tags":["Webhook Events"],"security":[],"parameters":[{"schema":{"type":"string"},"required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256>`: the HMAC of `<t>.<raw request body>` with the webhook `secret` as key. Recompute it over the raw body, compare in constant time, and reject old `t` values (the reference verifier allows 300 seconds).","name":"X-MachineMail-Signature","in":"header"},{"schema":{"type":"string"},"required":true,"description":"Event type, as in `event_type`.","name":"X-MachineMail-Event","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of the event, as in `event_id`. The same for every delivery and replay of the event: dedupe on it.","name":"X-MachineMail-Event-Id","in":"header"},{"schema":{"type":"string"},"required":true,"description":"ID of this delivery (`GET /v0/webhooks/{webhook_id}/deliveries`). A replay is a new delivery.","name":"X-MachineMail-Delivery-Id","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/events_WebhookTestEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}}},"components":{"responses":{"Conflict":{"description":"Conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"The credential lacks the permission or scope for this request (`error.type` `forbidden`), or MachineMail suspended the organization or its sending (`account_suspended`: `error.message` says what still works; do not retry or re-register).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Not found. Also returned for resources outside the credential scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotImplemented":{"description":"Not implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"PlanLimitExceeded":{"description":"The organization's plan does not allow this (`error.type` `plan_limit_exceeded`): `error.limit_key` names the limit, with `limit`, `used` and, when waiting helps, `resets_at` (and a `Retry-After` header). Do not retry before `resets_at`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"RateLimited":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TrustedDomainNotAllowed":{"description":"The domain or address cannot be trusted (`error.type` `trusted_domain_not_allowed`): `error.reason` is `free_mail`, `privacy_relay`, `shared_platform`, `public_suffix`, `disposable`, `invalid` or `confusable_idn`, and `error.message` says why in words.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Missing, invalid, expired or revoked credential.","headers":{"WWW-Authenticate":{"description":"`Bearer resource_metadata=\"https://<host>/.well-known/oauth-protected-resource\"` (RFC 9728).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unavailable":{"description":"A part of MachineMail this request needs is unavailable for a moment (`error.type` `unavailable`), for example the scheduler a draft with `send_at` is handed to. Nothing was changed: retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UpstreamError":{"description":"The email provider refused or failed the send (`error.type` is `upstream_error`). Nothing was sent and no message was stored. `error.message` says why: a rejected message or recipient is final, and so is a used-up sending quota until it resets; a throttled or unavailable provider can be retried later. A scheduled draft whose send fails this way is marked `send_status: failed`, unless the provider could not take mail for now (throttled, sending paused, quota used up, or unavailable): it stays scheduled and is retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ValidationError":{"description":"Invalid request: `error.type` is `validation` and `error.param` names the field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"AgentIdentityRequest":{"type":"object","properties":{"type":{"type":"string","enum":["anonymous","service_auth","identity_assertion"],"description":"Registration type."},"name":{"type":"string","description":"Agent label (first 100 characters). Untrusted; shown as agent-described in the dashboard."},"client_name":{"type":"string","description":"Alias of `name`."},"login_hint":{"type":"string","description":"`service_auth`: email address of the user the agent acts for. Required for that type."},"assertion_type":{"type":"string","description":"`identity_assertion`: `urn:ietf:params:oauth:token-type:id-jag`. Required for that type."},"assertion":{"type":"string","description":"`identity_assertion`: the ID-JAG (signed JWT). Required for that type."}},"required":["type"]},"AgentIdentityResponse":{"type":"object","properties":{"registration_id":{"type":"string"},"agent_id":{"type":"string","description":"Same value as `registration_id`."},"registration_type":{"$ref":"#/components/schemas/AgentRegistrationType"},"identity_assertion":{"type":"string","description":"Service-signed JWT to exchange at `/oauth2/token`. Absent for `service_auth` until the claim completes."},"assertion_expires":{"type":"string","format":"date-time"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"`identity_assertion` registrations: the granted scopes."},"pre_claim_scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"`anonymous` registrations: scopes before a human claims the agent (its sandbox inbox only)."},"post_claim_scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"Scopes after the claim."},"claim_url":{"type":"string","description":"Where to start the claim ceremony (`/agent/identity/claim`)."},"claim_token":{"type":"string","description":"Secret for `/agent/identity/claim` and the claim grant."},"claim_token_expires":{"type":"string","format":"date-time"},"claim":{"type":"object","properties":{"user_code":{"type":"string","description":"6-digit code the human enters in the dashboard."},"verification_uri":{"type":"string","description":"`https://machinemail.dev/claim?claim_attempt_token=cat_...`: the page to send the human to."},"expires_in":{"type":"integer","description":"Seconds until `user_code` expires."},"interval":{"type":"integer","description":"Minimum seconds between `/oauth2/token` polls."}},"required":["user_code","verification_uri","expires_in","interval"],"description":"`service_auth` registrations: the ceremony is already started."},"inbox":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the inbox belongs to."},"inbox_id":{"$ref":"#/components/schemas/inboxes_InboxId"},"email":{"type":"string","description":"Email address of the inbox."},"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"status":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"$ref":"#/components/schemas/inboxes_Metadata"},"updated_at":{"type":"string","format":"date-time","description":"Time at which the inbox was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the inbox was created."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"Whether the inbox expires (see `ttl_seconds`)."},"ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of an ephemeral inbox. Each inbound message pushes `expires_at` to now + `ttl_seconds`."},"expires_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When an ephemeral inbox and its mail are deleted."},"created_by":{"type":"string","enum":["api","catch_all","dashboard","agent"],"x-machinemail":true,"description":"What created the inbox: the API, a catch-all domain, the dashboard or an agent registration."}},"required":["pod_id","inbox_id","email","status","updated_at","created_at","organization_id","ephemeral","created_by"],"description":"`anonymous` registrations: the ephemeral sandbox inbox. There is no API key; authenticate with the access token from `/oauth2/token`."}},"required":["registration_id","agent_id","registration_type"]},"AgentRegistration":{"type":"object","properties":{"agent_id":{"type":"string","description":"ID of the registration (`reg_...`)."},"registration_id":{"type":"string","description":"Same value as `agent_id`."},"registration_type":{"$ref":"#/components/schemas/AgentRegistrationType"},"status":{"$ref":"#/components/schemas/AgentRegistrationStatus"},"name":{"type":"string","description":"Agent-described label. Untrusted."},"client":{"type":"string","description":"Provider name for `identity_assertion`, otherwise `agent (self-described)` or `anonymous agent`."},"organization_id":{"type":"string","description":"Organization the registration is bound to (after a claim, or right away for `identity_assertion`)."},"inbox_id":{"type":"string","description":"The sandbox inbox of an `anonymous` registration."},"email":{"type":"string","description":"Verified email bound at claim or carried by the identity assertion."},"issuer":{"type":"string","description":"Issuer of the identity assertion (`identity_assertion`)."},"agent_platform":{"type":"string","description":"`agent_platform` claim of the identity assertion."},"created_at":{"type":"string","format":"date-time","description":"When the agent registered."},"claimed_at":{"type":"string","format":"date-time","description":"When a human claimed the registration."},"revoked_at":{"type":"string","format":"date-time","description":"When the registration was revoked."},"expires_at":{"type":"string","format":"date-time","description":"When an unclaimed registration expires."}},"required":["agent_id","registration_id","registration_type","status","created_at"],"description":"An agent registration. Hashes and tokens are never included."},"AgentRegistrationStatus":{"type":"string","enum":["pending_claim","claimed","revoked"]},"AgentRegistrationType":{"type":"string","enum":["anonymous","service_auth","identity_assertion"],"description":"`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."},"AuthConfigResponse":{"type":"object","properties":{"workos":{"type":"boolean","description":"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":{"type":"boolean","description":"Email-code sign-in (`POST /auth/email/start`, then `POST /auth/email/verify`) is available."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/SocialProvider"},"description":"Social providers on offer (`GET /auth/social/{provider}`). Empty when none are offered."},"magic_link":{"type":"boolean","description":"Magic-link sign-in (`POST /auth/magic-link`) is available."},"password":{"type":"boolean","description":"The deprecated password endpoints are available."},"authkit":{"type":"boolean","description":"Deprecated: always `false`. Kept for older clients; see `email_code`.","deprecated":true},"passkey":{"type":"boolean","description":"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."}},"required":["workos","email_code","providers","magic_link","password","authkit","passkey"],"description":"How people sign in to MachineMail."},"AuthorizationServerMetadata":{"type":"object","properties":{"resource":{"type":"string","description":"The protected resource: `<issuer>/` (the REST API and MCP), or `<issuer>/<path>` 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, `<issuer>/mcp` is the legacy MCP alias."},"authorization_servers":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"},"description":"`header`."},"issuer":{"type":"string"},"authorization_endpoint":{"type":"string","description":"`<issuer>/oauth2/authorize`: authorization code grant with PKCE (`S256`)."},"token_endpoint":{"type":"string"},"registration_endpoint":{"type":"string","description":"`<issuer>/oauth2/register`: Dynamic Client Registration (RFC 7591), public or confidential clients."},"revocation_endpoint":{"type":"string"},"device_authorization_endpoint":{"type":"string","description":"`<issuer>/auth/cli/device/code`: the device grant of the MachineMail CLI (`client_id` `machinemail-cli` only)."},"jwks_uri":{"type":"string"},"service_documentation":{"type":"string"},"grant_types_supported":{"type":"array","items":{"type":"string"},"description":"`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":{"type":"array","items":{"type":"string"},"description":"`code`."},"response_modes_supported":{"type":"array","items":{"type":"string"},"description":"`query`."},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"},"description":"`S256`."},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"},"description":"`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":{"type":"array","items":{"type":"string"},"description":"Same as `token_endpoint_auth_methods_supported`."},"client_id_metadata_document_supported":{"type":"boolean","description":"`true`: an `https` URL is accepted as `client_id` (OAuth Client ID Metadata Document)."},"authorization_response_iss_parameter_supported":{"type":"boolean","description":"`true`: authorization responses carry `iss` (RFC 9207)."},"agent_auth":{"type":"object","properties":{"skill":{"type":"string","description":"The `/auth.md` document."},"identity_endpoint":{"type":"string"},"claim_endpoint":{"type":"string"},"events_endpoint":{"type":"string"},"identity_types_supported":{"type":"array","items":{"$ref":"#/components/schemas/AgentRegistrationType"},"description":"The registration types MachineMail accepts."},"identity_assertion":{"type":"object","properties":{"assertion_types_supported":{"type":"array","items":{"type":"string"}}},"required":["assertion_types_supported"]},"events_supported":{"type":"array","items":{"type":"string"}}},"required":["skill","identity_endpoint","claim_endpoint","events_endpoint","identity_types_supported","identity_assertion","events_supported"]}},"required":["resource","authorization_servers","scopes_supported","bearer_methods_supported","issuer","authorization_endpoint","token_endpoint","registration_endpoint","revocation_endpoint","device_authorization_endpoint","jwks_uri","service_documentation","grant_types_supported","response_types_supported","response_modes_supported","code_challenge_methods_supported","token_endpoint_auth_methods_supported","revocation_endpoint_auth_methods_supported","client_id_metadata_document_supported","authorization_response_iss_parameter_supported","agent_auth"],"description":"RFC 8414 Authorization Server Metadata (as the MCP authorization specification asks for it) plus the auth.md `agent_auth` block."},"ClaimBlock":{"type":"object","properties":{"user_code":{"type":"string","description":"6-digit code the human enters in the dashboard."},"verification_uri":{"type":"string","description":"`https://machinemail.dev/claim?claim_attempt_token=cat_...`: the page to send the human to."},"expires_in":{"type":"integer","description":"Seconds until `user_code` expires."},"interval":{"type":"integer","description":"Minimum seconds between `/oauth2/token` polls."}},"required":["user_code","verification_uri","expires_in","interval"],"description":"RFC 8628-shaped claim ceremony block."},"ClaimCompleteRequest":{"type":"object","properties":{"user_code":{"type":"string","description":"The 6-digit code the agent shows; spaces and dashes are ignored."},"claim_attempt_token":{"type":"string","description":"The `cat_...` token from `verification_uri`; when given, it must belong to the same attempt as `user_code`."}},"required":["user_code"]},"ClaimCompleteResponse":{"type":"object","properties":{"agent_id":{"type":"string","description":"ID of the registration (`reg_...`)."},"registration_id":{"type":"string","description":"Same value as `agent_id`."},"registration_type":{"$ref":"#/components/schemas/AgentRegistrationType"},"status":{"type":"string","enum":["claimed"]},"name":{"type":"string","description":"Agent-described label. Untrusted."},"client":{"type":"string","description":"Provider name for `identity_assertion`, otherwise `agent (self-described)` or `anonymous agent`."},"organization_id":{"type":"string","description":"The organization of the signed-in user."},"inbox_id":{"type":"string","description":"The sandbox inbox of an `anonymous` registration."},"email":{"type":"string","description":"Verified email bound at claim or carried by the identity assertion."},"issuer":{"type":"string","description":"Issuer of the identity assertion (`identity_assertion`)."},"agent_platform":{"type":"string","description":"`agent_platform` claim of the identity assertion."},"created_at":{"type":"string","format":"date-time","description":"When the agent registered."},"claimed_at":{"type":"string","format":"date-time","description":"When a human claimed the registration."},"revoked_at":{"type":"string","format":"date-time","description":"When the registration was revoked."},"expires_at":{"type":"string","format":"date-time","description":"When an unclaimed registration expires."},"inbox":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the inbox belongs to."},"inbox_id":{"$ref":"#/components/schemas/inboxes_InboxId"},"email":{"type":"string","description":"Email address of the inbox."},"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"status":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"$ref":"#/components/schemas/inboxes_Metadata"},"updated_at":{"type":"string","format":"date-time","description":"Time at which the inbox was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the inbox was created."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"Whether the inbox expires (see `ttl_seconds`)."},"ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of an ephemeral inbox. Each inbound message pushes `expires_at` to now + `ttl_seconds`."},"expires_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When an ephemeral inbox and its mail are deleted."},"created_by":{"type":"string","enum":["api","catch_all","dashboard","agent"],"x-machinemail":true,"description":"What created the inbox: the API, a catch-all domain, the dashboard or an agent registration."}},"required":["pod_id","inbox_id","email","status","updated_at","created_at","organization_id","ephemeral","created_by"],"description":"The former sandbox inbox, now permanent and in the user’s default pod."}},"required":["agent_id","registration_id","registration_type","status","organization_id","created_at"],"description":"The claimed registration plus the moved inbox."},"ClaimPreviewResponse":{"type":"object","properties":{"agent_id":{"type":"string","description":"ID of the registration (`reg_...`)."},"registration_id":{"type":"string","description":"Same value as `agent_id`."},"registration_type":{"$ref":"#/components/schemas/AgentRegistrationType"},"status":{"$ref":"#/components/schemas/AgentRegistrationStatus"},"name":{"type":"string","description":"Agent-described label. Untrusted."},"client":{"type":"string","description":"Provider name for `identity_assertion`, otherwise `agent (self-described)` or `anonymous agent`."},"organization_id":{"type":"string","description":"Organization the registration is bound to (after a claim, or right away for `identity_assertion`)."},"inbox_id":{"type":"string","description":"The sandbox inbox of an `anonymous` registration."},"email":{"type":"string","description":"Verified email bound at claim or carried by the identity assertion."},"issuer":{"type":"string","description":"Issuer of the identity assertion (`identity_assertion`)."},"agent_platform":{"type":"string","description":"`agent_platform` claim of the identity assertion."},"created_at":{"type":"string","format":"date-time","description":"When the agent registered."},"claimed_at":{"type":"string","format":"date-time","description":"When a human claimed the registration."},"revoked_at":{"type":"string","format":"date-time","description":"When the registration was revoked."},"expires_at":{"type":"string","format":"date-time","description":"When an unclaimed registration expires."},"claim_email":{"type":"string","description":"Only this user may claim the registration."},"user_code_expires_at":{"type":"string","format":"date-time","description":"When the code expires."},"sandbox_inbox":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the inbox belongs to."},"inbox_id":{"$ref":"#/components/schemas/inboxes_InboxId"},"email":{"type":"string","description":"Email address of the inbox."},"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"status":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"$ref":"#/components/schemas/inboxes_Metadata"},"updated_at":{"type":"string","format":"date-time","description":"Time at which the inbox was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the inbox was created."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"Whether the inbox expires (see `ttl_seconds`)."},"ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of an ephemeral inbox. Each inbound message pushes `expires_at` to now + `ttl_seconds`."},"expires_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When an ephemeral inbox and its mail are deleted."},"created_by":{"type":"string","enum":["api","catch_all","dashboard","agent"],"x-machinemail":true,"description":"What created the inbox: the API, a catch-all domain, the dashboard or an agent registration."}},"required":["pod_id","inbox_id","email","status","updated_at","created_at","organization_id","ephemeral","created_by"],"description":"The sandbox inbox of an `anonymous` registration."}},"required":["agent_id","registration_id","registration_type","status","created_at"],"description":"An agent registration plus the claim details."},"ClaimStartRequest":{"type":"object","properties":{"claim_token":{"type":"string","description":"Protocol form: the `claim_token` from registration."},"email":{"type":"string","description":"Binds the claim to this human. For `service_auth` and `identity_assertion` it must match the bound email."},"agent_id":{"type":"string","description":"Alternative to `claim_token`; needs the registration’s access token or identity assertion as `Authorization: Bearer`."},"registration_id":{"type":"string","description":"Alias of `agent_id`."}},"description":"Send `claim_token` (and optionally `email`), or `agent_id` with Bearer proof."},"ClaimStartResponse":{"type":"object","properties":{"registration_id":{"type":"string"},"agent_id":{"type":"string"},"claim_attempt_id":{"type":"string"},"status":{"type":"string","enum":["initiated"]},"expires_at":{"type":"string","format":"date-time","description":"When this attempt expires."},"claim_attempt":{"$ref":"#/components/schemas/ClaimBlock"},"user_code":{"type":"string","description":"6-digit code the human enters in the dashboard."},"verification_uri":{"type":"string","description":"`https://machinemail.dev/claim?claim_attempt_token=cat_...`: the page to send the human to."},"expires_in":{"type":"integer","description":"Seconds until `user_code` expires."},"interval":{"type":"integer","description":"Minimum seconds between `/oauth2/token` polls."}},"required":["registration_id","agent_id","claim_attempt_id","status","expires_at","claim_attempt","user_code","verification_uri","expires_in","interval"],"description":"The `claim_attempt` block and the flat `user_code`, `verification_uri`, `expires_in` and `interval` carry the same values."},"CliDeviceApproveRequest":{"type":"object","properties":{"user_code":{"type":"string","description":"The code the CLI printed (`XXXX-XXXX`); case, spaces and dashes are ignored."},"organization_id":{"type":"string","description":"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."}},"required":["user_code"]},"CliDeviceAuthorization":{"type":"object","properties":{"user_code":{"type":"string","description":"The code, formatted `XXXX-XXXX`."},"device_id":{"type":"string","description":"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":{"type":"string","description":"Always `machinemail-cli`."},"client_name":{"type":["string","null"],"description":"What the CLI says it is. Self-reported."},"hostname":{"type":["string","null"],"description":"The machine the CLI says it runs on. Self-reported."},"key_name":{"type":"string","description":"Name of the key approval creates: `CLI on <hostname>`."},"permissions":{"type":"array","items":{"type":"string"},"description":"Permissions of that key: `[\"*\"]` (every permission except `inbound_raw`)."},"created_at":{"type":"string","format":"date-time","description":"When the CLI asked for the code."},"expires_at":{"type":"string","format":"date-time","description":"When the code expires."}},"required":["user_code","device_id","client_id","client_name","hostname","key_name","permissions","created_at","expires_at"],"description":"A pending CLI sign-in, as the approval page shows it. Never includes the device code."},"CliDeviceCodeRequest":{"type":"object","properties":{"client_id":{"type":"string","description":"Always `machinemail-cli`."},"client_name":{"type":"string","maxLength":100,"description":"Shown to the human on the approval page, for example `MachineMail CLI 0.4.0`. At most 100 characters."},"hostname":{"type":"string","maxLength":253,"description":"The machine the CLI runs on. Names the key (`CLI on <hostname>`) and is shown on the approval page. At most 253 characters."}},"required":["client_id"]},"CliDeviceCodeResponse":{"type":"object","properties":{"device_code":{"type":"string","description":"Secret the CLI polls the token endpoint with. Never show it."},"user_code":{"type":"string","description":"Code the human checks on the approval page: 8 letters as `XXXX-XXXX` (consonants only, no look-alikes)."},"verification_uri":{"type":"string","description":"`https://machinemail.dev/cli`: where the human approves."},"verification_uri_complete":{"type":"string","description":"`verification_uri` with `?code=<user_code>`, for opening in a browser."},"expires_in":{"type":"integer","description":"Seconds until both codes expire (600)."},"interval":{"type":"integer","description":"Minimum seconds between polls of the token endpoint (5)."}},"required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"description":"RFC 8628 device authorization response."},"CliDeviceDecision":{"type":"object","properties":{"status":{"type":"string","enum":["approved","denied"]},"key_name":{"type":"string","description":"Name of the key the CLI receives (approved) or would have received (denied)."}},"required":["status","key_name"]},"CliDeviceDecisionRequest":{"type":"object","properties":{"user_code":{"type":"string","description":"The code the CLI printed (`XXXX-XXXX`); case, spaces and dashes are ignored."}},"required":["user_code"]},"CliDeviceTokenRequest":{"type":"object","properties":{"grant_type":{"type":"string","description":"`urn:ietf:params:oauth:grant-type:device_code`."},"device_code":{"type":"string","description":"The `device_code` from the device authorization response."},"client_id":{"type":"string","description":"Always `machinemail-cli`."}},"required":["grant_type","device_code","client_id"]},"CliDeviceTokenResponse":{"type":"object","properties":{"access_token":{"type":"string","description":"The new API key (`mm_live_...`). Returned once; send it as `Authorization: Bearer`."},"token_type":{"type":"string","enum":["Bearer"]},"api_key_id":{"type":"string","description":"ID of the key, for `DELETE /v0/api-keys/{api_key_id}` on logout."},"key_name":{"type":"string","description":"Name of the key: `CLI on <hostname>`."},"organization":{"$ref":"#/components/schemas/organizations_Organization","description":"The organization the key belongs to."},"user":{"$ref":"#/components/schemas/User","description":"The person who approved the sign-in."}},"required":["access_token","token_type","api_key_id","key_name","organization","user"],"description":"An organization API key with every permission except `inbound_raw`, minted for the approving user."},"ClientRegistrationRequest":{"type":"object","properties":{"redirect_uris":{"type":"array","items":{"type":"string","maxLength":2000},"minItems":1,"maxItems":10,"description":"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."},"client_name":{"type":"string","maxLength":200,"description":"Shown on the consent page, marked as unverified. At most 200 characters."},"client_uri":{"type":"string","maxLength":2000,"description":"Home page of the client; shown on the consent page when it is `https`."},"logo_uri":{"type":"string","maxLength":2000,"description":"Logo shown on the consent page when it is `https`."},"token_endpoint_auth_method":{"type":"string","description":"`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":{"type":"array","items":{"type":"string"},"description":"`authorization_code` and `refresh_token` (the default). Must include `authorization_code` (`invalid_client_metadata` otherwise); other values are dropped from the registration."},"response_types":{"type":"array","items":{"type":"string"},"description":"`code` (the default). Other values: `invalid_client_metadata`."},"scope":{"type":"string","maxLength":2000,"description":"Space-separated `Scope` values the client may ask for. Default: every scope."},"application_type":{"type":"string","enum":["native","web"],"description":"`native` or `web` (OpenID Connect Dynamic Client Registration; required by MCP 2026-07-28). Default `web`."},"software_id":{"type":"string","maxLength":200,"description":"Identifier of the client software. Stored, not verified."},"software_version":{"type":"string","maxLength":100,"description":"Version of the client software. Stored, not verified."}},"required":["redirect_uris"],"description":"RFC 7591 client metadata. Unknown members are ignored."},"ClientRegistrationResponse":{"type":"object","properties":{"client_id":{"type":"string","description":"The new client identifier (`oac_...`)."},"client_id_issued_at":{"type":"integer","description":"Seconds since the epoch."},"client_name":{"type":"string"},"client_uri":{"type":"string"},"logo_uri":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","enum":["none","client_secret_post","client_secret_basic"],"description":"As requested when supported, otherwise `none`."},"client_secret":{"type":"string","description":"Confidential clients only (`client_secret_post`, `client_secret_basic`): shown once, stored only as a hash. Keep it secret."},"client_secret_expires_at":{"type":"integer","description":"With `client_secret`: `0`, the secret does not expire."},"application_type":{"type":"string","enum":["native","web"]},"scope":{"type":"string"},"software_id":{"type":"string"},"software_version":{"type":"string"}},"required":["client_id","client_id_issued_at","redirect_uris","grant_types","response_types","token_endpoint_auth_method","application_type"],"description":"RFC 7591 client information response. A public client has no `client_secret`."},"Count":{"type":"integer","description":"Number of items returned."},"CreateSessionOrganizationRequest":{"type":"object","properties":{"name":{"type":"string","description":"Name of the new organization."}},"required":["name"]},"EmailCodeStartRequest":{"type":"object","properties":{"email":{"type":"string","description":"Address to send the code to. Optional with `invitation_token` (the code goes to the invited address)."},"next":{"type":"string","description":"Same-origin path to land on after sign-in, for example `/cli?code=ABCD-EFGH`. Anything else is ignored. Default `/app`."},"invitation_token":{"type":"string","description":"An invitation token (from `/invite/{token}`): signing in accepts the invitation."}}},"EmailCodeStartResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"redirect_to":{"type":"string","description":"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."}},"required":["ok"]},"EmailCodeVerifyRequest":{"type":"object","properties":{"code":{"type":"string","description":"The 6-digit code from the email. Spaces and dashes are ignored."}},"required":["code"]},"EmailCodesRequest":{"type":"object","properties":{"enabled":{"type":"boolean","description":"`false` turns email sign-in codes off; `true` back on."}},"required":["enabled"]},"EmailCodesResponse":{"type":"object","properties":{"email_codes":{"type":"boolean","description":"Email sign-in codes work for this account now."}},"required":["email_codes"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["not_found","validation","unauthorized","forbidden","rate_limited","conflict","internal","not_implemented","account_suspended","plan_limit_exceeded","upstream_error","unavailable","trusted_domain_not_allowed","confirmation_required"],"description":"Machine-readable error type. The HTTP status always matches it (see each response)."},"message":{"type":"string","description":"Human-readable description."},"param":{"description":"The request field the error is about, when there is one.","type":"string"},"limit_key":{"x-machinemail":true,"description":"`plan_limit_exceeded` only: the plan limit that refused the request.","type":"string","enum":["messages_per_month","messages_per_day","custom_domains","seats","held_messages","held_bytes","storage_bytes","spam_storage_bytes","free_organizations","trusted_domains"]},"limit":{"x-machinemail":true,"description":"`plan_limit_exceeded` only: the value of that limit for this organization.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"used":{"x-machinemail":true,"description":"`plan_limit_exceeded` only: how much of it the organization has used, before this request.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reason":{"x-machinemail":true,"description":"`trusted_domain_not_allowed`: why the entry cannot be trusted (`free_mail`, `privacy_relay`, `shared_platform`, `public_suffix`, `disposable`, `invalid` or `confusable_idn`). `confirmation_required`: `user_content_platform`.","type":"string"},"resets_at":{"x-machinemail":true,"description":"`plan_limit_exceeded` only: when the limit resets (UTC). Absent when waiting does not help: custom domains, seats, trusted domains, or a request larger than the limit itself.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["type","message"]}},"required":["error"],"description":"Every non-2xx JSON response on /v0. The HTTP status matches `error.type`."},"FirstKeyResponse":{"type":"object","properties":{"api_key":{"$ref":"#/components/schemas/OneTimeApiKey"}},"required":["api_key"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]}},"required":["status"]},"InboundRawResponse":{"type":"object","properties":{"count":{"type":"integer","description":"Number of messages stored (one per recipient inbox that accepted it)."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/messages_Message"},"description":"The stored messages, marked `received_via: \"raw\"`."},"errors":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"message":{"type":"string"}},"required":["recipient","message"]},"description":"Recipients that could not be delivered to, when there were several and at least one succeeded."},"held":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"reason":{"type":"string","enum":["monthly","daily","storage","queued"]}},"required":["recipient","reason"]},"x-machinemail":true,"description":"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."}},"required":["count","messages"]},"InvitationPreviewResponse":{"type":"object","properties":{"organization_name":{"type":"string","description":"The organization the invitation is to."},"email":{"type":"string","description":"The invited address, masked (`a••@example.com`)."},"state":{"type":"string","enum":["pending","accepted","expired","revoked"],"description":"Only a `pending` invitation can be accepted."},"expires_at":{"type":"string","format":"date-time","description":"When the invitation expires."}},"required":["organization_name","email","state","expires_at"],"description":"What an invitation link is for, before signing in."},"JsonRpcError":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"]},"id":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]}},"required":["jsonrpc","error","id"],"description":"JSON-RPC 2.0 error response."},"JsonWebKeySet":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","additionalProperties":{},"description":"Public JWK (`kty`, `kid`, `alg`, `use` and the key parameters)."}}},"required":["keys"],"description":"RFC 7517 JWK Set."},"Limit":{"type":"integer","description":"Maximum number of items per page. Default 50, maximum 500; larger values are capped."},"ListAgentRegistrationsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"agent_registrations":{"type":"array","items":{"$ref":"#/components/schemas/AgentRegistration"},"description":"Newest first unless `ascending` is set."}},"required":["count","agent_registrations"]},"ListOAuthGrantsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"oauth_grants":{"type":"array","items":{"$ref":"#/components/schemas/OAuthGrant"},"description":"Newest first unless `ascending` is set."}},"required":["count","oauth_grants"]},"ListPasskeysResponse":{"type":"object","properties":{"passkeys":{"type":"array","items":{"$ref":"#/components/schemas/Passkey"},"description":"The person’s passkeys, oldest first."},"email_codes":{"type":"boolean","description":"Email sign-in codes work for this account. `false` once turned off (with at least one passkey)."},"step_up":{"type":"object","properties":{"recent_until":{"type":"string","format":"date-time","description":"Until when sensitive changes (adding or removing a passkey, turning email codes off) need no confirmation: 10 minutes after signing in or confirming."},"methods":{"type":"array","items":{"$ref":"#/components/schemas/StepUpMethod"},"description":"How this account can confirm once that time has passed."}},"required":["recent_until","methods"],"description":"Confirmation before sensitive changes."},"prompt":{"type":"boolean","description":"Offer to create a passkey (no passkey yet, and the offer was not snoozed or declined)."}},"required":["passkeys","email_codes","step_up","prompt"]},"ListSessionOrganizationsResponse":{"type":"object","properties":{"organizations":{"type":"array","items":{"$ref":"#/components/schemas/MembershipOrganization"},"description":"Every organization the person belongs to, by name."}},"required":["organizations"]},"LoginRequest":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"required":["email","password"]},"MagicLinkRequest":{"type":"object","properties":{"email":{"type":"string","description":"Address to send the sign-in link to."},"org_name":{"type":"string","description":"Organization name, used only when this is the address’s first sign-in."},"next":{"type":"string","description":"Same-origin path to land on after sign-in, for example `/claim?user_code=123456`. Anything else is ignored. Default `/app`."},"organization_name":{"type":"string","description":"Alias of `org_name`."},"organizationName":{"type":"string","description":"Alias of `org_name`.","deprecated":true}},"required":["email"]},"MagicLinkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"McpDescription":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","description":"What the server is for, in one line."},"icons":{"type":"array","items":{"type":"object","properties":{"src":{"type":"string","description":"HTTPS URL of the icon."},"mimeType":{"type":"string"},"sizes":{"type":"array","items":{"type":"string"},"description":"`WxH`, or `any` for SVG."}},"required":["src","mimeType","sizes"]},"description":"The MachineMail mark, for clients and registries that show an icon."},"version":{"type":"string"},"transport":{"type":"string","enum":["streamable-http"]},"url":{"type":"string","description":"The canonical MCP endpoint, `https://mcp.machinemail.dev/mcp`. `https://machinemail.dev/mcp` also works (legacy alias)."},"authentication":{"type":"object","properties":{"type":{"type":"string","enum":["bearer"]},"header":{"type":"string","description":"`Authorization: Bearer <api key or OAuth access token>`."},"resource_metadata":{"type":"string","description":"RFC 9728 protected resource metadata URL of the MCP server (`https://mcp.machinemail.dev/.well-known/oauth-protected-resource/mcp`)."},"oauth":{"type":"object","properties":{"authorization_server":{"type":"string","description":"Issuer of the authorization server (`https://machinemail.dev`); its metadata is at `/.well-known/oauth-authorization-server`."},"resource":{"type":"string","description":"RFC 8707 resource to request: the MCP endpoint (`url`)."}},"required":["authorization_server","resource"],"description":"OAuth sign-in (authorization code with PKCE). MCP clients discover it on their own from the `401`."}},"required":["type","header","resource_metadata","oauth"]},"docs":{"type":"string"}},"required":["name","description","icons","version","transport","url","authentication","docs"],"description":"How to connect to the remote MCP server."},"MembershipOrganization":{"type":"object","properties":{"organization_id":{"type":"string","description":"ID of the organization."},"name":{"type":"string","description":"Name of the organization."},"slug":{"type":"string","description":"URL-safe name of the organization. Fixed when the organization is created; it never changes."},"role":{"type":"string","enum":["owner","admin","member"],"description":"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":{"type":"boolean","description":"The session is signed in to this organization."}},"required":["organization_id","name","slug","role","current"],"description":"An organization the signed-in person belongs to."},"OAuthApproveRequest":{"type":"object","properties":{"request_id":{"type":"string"},"pod_id":{"type":"string","description":"Limit the grant to one pod of the organization. Default: the whole organization."},"inbox_id":{"type":"string","description":"Limit the grant to one inbox (and its pod)."},"organization_id":{"type":"string","description":"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."}},"required":["request_id"]},"OAuthAuthorizationRequest":{"type":"object","properties":{"request_id":{"type":"string"},"client":{"$ref":"#/components/schemas/OAuthClientInfo"},"redirect_uri":{"type":"string","description":"Where the response goes."},"redirect_host":{"type":"string","description":"Host (or scheme, for an app link) of `redirect_uri`, for the human to check."},"redirect_loopback":{"type":"boolean","description":"The response goes to a program on this computer (`http://127.0.0.1`, `localhost`)."},"resource":{"type":"string","description":"What the token will be good for: the MCP server (`https://mcp.machinemail.dev/mcp`, or the legacy `<issuer>/mcp`) or `<issuer>/` (the REST API and MCP)."},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/ScopeDescription"},"description":"What the client asked for."},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time","description":"When the request expires (10 minutes after it was made)."}},"required":["request_id","client","redirect_uri","redirect_host","redirect_loopback","resource","scopes","created_at","expires_at"],"description":"A pending authorization request, as the consent page shows it."},"OAuthClientInfo":{"type":"object","properties":{"client_id":{"type":"string"},"client_name":{"type":["string","null"],"description":"Self-reported by the client."},"client_uri":{"type":["string","null"],"description":"Self-reported; `https` only."},"logo_uri":{"type":["string","null"],"description":"Self-reported; `https` only."},"registration":{"type":"string","enum":["dynamic","metadata_document"],"description":"`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":{"type":["string","null"],"description":"`metadata_document`: the host that serves the document (for example `claude.ai`)."}},"required":["client_id","client_name","client_uri","logo_uri","registration","host"]},"OAuthDecision":{"type":"object","properties":{"status":{"type":"string","enum":["approved","denied"]},"redirect_to":{"type":"string","description":"Send the browser here: `redirect_uri` with `code` (or `error=access_denied`), `state` and `iss`."}},"required":["status","redirect_to"]},"OAuthDenyRequest":{"type":"object","properties":{"request_id":{"type":"string"}},"required":["request_id"]},"OAuthError":{"type":"object","properties":{"error":{"type":"string","description":"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":{"type":"string"},"message":{"type":"string","description":"Same text as `error_description`."},"registration_id":{"type":"string","description":"`interaction_required` only."},"agent_id":{"type":"string","description":"`interaction_required` only."},"registration_type":{"type":"string","enum":["anonymous","service_auth","identity_assertion"],"description":"`interaction_required` only."},"claim_url":{"type":"string","description":"`interaction_required` only."},"claim_token":{"type":"string","description":"`interaction_required` only."},"claim_token_expires":{"type":"string","format":"date-time","description":"`interaction_required` only."},"post_claim_scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"},"description":"`interaction_required` only."},"claim":{"type":"object","properties":{"user_code":{"type":"string","description":"6-digit code the human enters in the dashboard."},"verification_uri":{"type":"string","description":"`https://machinemail.dev/claim?claim_attempt_token=cat_...`: the page to send the human to."},"expires_in":{"type":"integer","description":"Seconds until `user_code` expires."},"interval":{"type":"integer","description":"Minimum seconds between `/oauth2/token` polls."}},"required":["user_code","verification_uri","expires_in","interval"],"description":"`interaction_required` only."},"max_age":{"type":"integer","description":"`login_required` only: the maximum `auth_time` age in seconds."}},"required":["error","error_description","message"],"description":"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."},"OAuthGrant":{"type":"object","properties":{"grant_id":{"type":"string","description":"ID of the grant (`oag_...`)."},"client_id":{"type":"string"},"client_name":{"type":["string","null"],"description":"Self-reported by the client at registration."},"client_uri":{"type":["string","null"]},"logo_uri":{"type":["string","null"]},"registration":{"type":"string","enum":["dynamic","metadata_document"]},"user_id":{"type":"string","description":"Who approved it."},"user_email":{"type":["string","null"]},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"resource":{"type":"string","description":"Audience of its access tokens."},"pod_id":{"type":["string","null"],"description":"Set when the grant is limited to one pod."},"inbox_id":{"type":["string","null"],"description":"Set when the grant is limited to one inbox."},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time","description":"Last token refresh or API call (updated at most once a minute)."},"expires_at":{"type":"string","format":"date-time","description":"When the current refresh token expires unless it is used (30 days after the last refresh)."}},"required":["grant_id","client_id","client_name","client_uri","logo_uri","registration","user_id","user_email","scopes","resource","pod_id","inbox_id","created_at","last_used_at","expires_at"],"description":"An app a person connected with OAuth. Revoking it ends its access and refresh tokens at once."},"OkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"],"description":"Acknowledgement."},"OneTimeApiKey":{"type":"object","properties":{"api_key_id":{"type":"string","description":"ID of the API key."},"api_key":{"type":"string","description":"Plaintext secret (`mm_live_...`). Shown once."},"prefix":{"type":"string","description":"First characters of the key, shown in listings."},"name":{"type":"string","description":"Name of the key."},"created_at":{"type":"string","format":"date-time","description":"When the key was created."}},"required":["api_key_id","api_key","prefix","name","created_at"],"description":"An API key with its plaintext secret, returned once."},"PageToken":{"type":"string","description":"Page token for pagination. Absent on the last page."},"Passkey":{"type":"object","properties":{"passkey_id":{"type":"string","description":"ID of the passkey (`pk_…`)."},"name":{"type":"string","description":"Name shown in Settings (named after its password manager or device when added; up to 64 characters)."},"created_at":{"type":"string","format":"date-time","description":"When the passkey was added."},"last_used_at":{"type":["string","null"],"format":"date-time","description":"When it last signed in or confirmed a change."},"backed_up":{"type":"boolean","description":"Synced by its password manager to the person’s other devices."},"device_type":{"type":"string","enum":["singleDevice","multiDevice"],"description":"`multiDevice`: a synced passkey. `singleDevice`: bound to one device or security key."}},"required":["passkey_id","name","created_at","last_used_at","backed_up"],"description":"A passkey the signed-in person can sign in with."},"PasskeyCredentialRequest":{"type":"object","properties":{"credential":{"type":"object","additionalProperties":{},"description":"The browser’s `AuthenticationResponseJSON`."}},"required":["credential"]},"PasskeyOptionsResponse":{"type":"object","properties":{"options":{"type":"object","additionalProperties":{},"description":"`PublicKeyCredentialRequestOptionsJSON`: pass to `navigator.credentials.get()`."}},"required":["options"]},"PasskeyPromptRequest":{"type":"object","properties":{"action":{"type":"string","enum":["not_now","never"],"description":"`not_now`: ask again in 14 days. `never`: don’t ask again."}},"required":["action"]},"PasskeyRegistrationOptionsResponse":{"type":"object","properties":{"options":{"type":"object","additionalProperties":{},"description":"`PublicKeyCredentialCreationOptionsJSON`: pass to `navigator.credentials.create()`."}},"required":["options"]},"PasskeySignInOptionsRequest":{"type":"object","properties":{"next":{"type":"string","description":"Same-origin path to land on after sign-in. Anything else is ignored. Default `/app`."},"invitation_token":{"type":"string","description":"An invitation token (from `/invite/{token}`): signing in accepts the invitation."}}},"PendingOrganizationRequest":{"type":"object","properties":{"organization_id":{"type":"string","description":"One of the `organizations` from `GET /auth/pending`."}},"required":["organization_id"]},"PendingSignInResponse":{"type":"object","properties":{"step":{"type":"string","enum":["code","organization","verify_email"],"description":"`code`: waiting for the emailed sign-in code. `organization`: pick an organization. `verify_email`: enter the code that verifies the email."},"email":{"type":"string","description":"The address signing in, when known."},"organizations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Organization ID, to send to `POST /auth/pending/organization`."},"name":{"type":"string","description":"Name of the organization."}},"required":["id","name"]},"description":"For `organization`: the organizations to pick from."},"invitation":{"type":"boolean","description":"Signing in accepts an invitation."}},"required":["step","invitation"],"description":"The sign-in in progress in this browser."},"PendingVerifyRequest":{"type":"object","properties":{"code":{"type":"string","description":"The 6-digit code from the email. Spaces and dashes are ignored."}},"required":["code"]},"ProtectedResourceMetadata":{"type":"object","properties":{"resource":{"type":"string","description":"The protected resource: `<issuer>/` (the REST API and MCP), or `<issuer>/<path>` 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, `<issuer>/mcp` is the legacy MCP alias."},"authorization_servers":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"},"description":"`header`."},"resource_name":{"type":"string"},"resource_logo_uri":{"type":"string"},"resource_documentation":{"type":"string","description":"The `/auth.md` document, or the MCP guide for `<issuer>/mcp`."}},"required":["resource","authorization_servers","scopes_supported","bearer_methods_supported","resource_name","resource_logo_uri","resource_documentation"],"description":"RFC 9728 OAuth Protected Resource Metadata."},"ReadyResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ready","unavailable"],"description":"`ready` when storage answers; the HTTP status is then 200, otherwise 503."},"checks":{"type":"object","properties":{"storage":{"type":"boolean","description":"Whether the storage backend answered a ping.","example":true}},"required":["storage"],"description":"The checks behind `status`."}},"required":["status","checks"]},"RegisterPasskeyRequest":{"type":"object","properties":{"credential":{"type":"object","additionalProperties":{},"description":"The browser’s `RegistrationResponseJSON`."},"name":{"type":"string","description":"Name for the passkey (up to 64 characters). Default: its password manager or device, or “Passkey”."}},"required":["credential"]},"RemovePasskeyResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"sessions_ended":{"type":"integer","description":"Sessions the passkey had signed in that were signed out."},"signed_out":{"type":"boolean","description":"This session was one of them: sign in again."}},"required":["ok","sessions_ended","signed_out"]},"RenamePasskeyRequest":{"type":"object","properties":{"name":{"type":"string","description":"New name, 1 to 64 characters."}},"required":["name"]},"RevokeOtherSessionsResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"ended":{"type":"integer","description":"Other sessions signed out."}},"required":["ok","ended"]},"RevokeRequest":{"type":"object","properties":{"token":{"type":"string","description":"An access token, a refresh token or an identity assertion."},"token_type_hint":{"type":"string","description":"`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":{"type":"string","description":"Refresh and access tokens of an app: when given, must be the client the token was issued to, or nothing is revoked."},"client_secret":{"type":"string","description":"A confidential client authenticates as at the token endpoint (`client_secret_post`, or HTTP Basic)."}},"required":["token"]},"Scope":{"type":"string","enum":["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"],"description":"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)."},"ScopeDescription":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/Scope"},"description":{"type":"string"}},"required":["scope","description"]},"SessionResponse":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"organization":{"$ref":"#/components/schemas/organizations_Organization"}},"required":["user","organization"],"description":"The signed-in user and their organization."},"SetError":{"type":"object","properties":{"err":{"type":"string","description":"`invalid_request`, `invalid_issuer`, `invalid_key` or `invalid_audience`."},"description":{"type":"string"}},"required":["err","description"],"description":"RFC 8935 SET delivery error."},"SignInStepResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"signed_in":{"type":"boolean","description":"`true`: the `mm_session` cookie is set. `false`: another step comes first (organization picker, email verification, SSO)."},"redirect_to":{"type":"string","description":"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=<code>`."}},"required":["ok","signed_in","redirect_to"],"description":"The result of a sign-in step."},"SignupRequest":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string","description":"At least 8 characters."},"name":{"type":"string","description":"Display name of the user."},"org_name":{"type":"string","description":"Organization name."},"organization_name":{"type":"string","description":"Alias of `org_name`."},"organizationName":{"type":"string","description":"Alias of `org_name`.","deprecated":true}},"required":["email","password"]},"SignupResponse":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"organization":{"$ref":"#/components/schemas/organizations_Organization"},"api_key":{"$ref":"#/components/schemas/OneTimeApiKey"}},"required":["user","organization","api_key"],"description":"The new user, their organization and the first organization API key (shown once)."},"SocialProvider":{"type":"string","enum":["google","github","apple","microsoft"],"description":"A social sign-in provider."},"StepUpEmailResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"email":{"type":"string","description":"Where the code went, masked."},"expires_at":{"type":"string","format":"date-time","description":"When the code expires (10 minutes)."}},"required":["ok","email","expires_at"]},"StepUpEmailVerifyRequest":{"type":"object","properties":{"code":{"type":"string","description":"The 6-digit code from the email. Spaces and dashes are ignored."}},"required":["code"]},"StepUpMethod":{"type":"string","enum":["passkey","email_code"],"description":"How to confirm it’s you: `passkey`, or `email_code` (a code emailed to your address)."},"StepUpResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"recent_until":{"type":"string","format":"date-time","description":"Until when sensitive changes need no further confirmation."}},"required":["ok","recent_until"]},"SwitchOrganizationRequest":{"type":"object","properties":{"organization_id":{"type":"string","description":"ID of an organization the person belongs to."}},"required":["organization_id"]},"TokenRequest":{"type":"object","properties":{"grant_type":{"type":"string","description":"`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":{"type":"string","description":"authorization_code: the code from the authorization response. Single use; expires after 2 minutes."},"redirect_uri":{"type":"string","description":"authorization_code: the `redirect_uri` of the authorization request, when it had one."},"code_verifier":{"type":"string","description":"authorization_code: the PKCE code verifier (43 to 128 characters)."},"refresh_token":{"type":"string","description":"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":{"type":"string","description":"refresh_token, optional: narrow the new access token to these scopes of the grant."},"device_code":{"type":"string","description":"device_code: the `device_code` from `/auth/cli/device/code`."},"assertion":{"type":"string","description":"jwt-bearer grant: the `identity_assertion`."},"client_id":{"type":"string","description":"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":{"type":"string","description":"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":{"type":"string","description":"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 `<issuer>/`."},"claim_token":{"type":"string","description":"Claim grant: the `claim_token` from registration."}},"required":["grant_type"]},"TokenResponse":{"type":"object","properties":{"access_token":{"type":"string","description":"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 `<issuer>/mcp`) works on the MCP endpoint only (either URL), `<issuer>/` on `/v0` and the MCP endpoint. auth.md tokens work on both."},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer","description":"Lifetime of the access token in seconds."},"scope":{"type":"string","description":"Space-separated `Scope` values."},"refresh_token":{"type":"string","description":"authorization_code and refresh_token grants: the new refresh token (rotated on every use)."},"identity_assertion":{"type":"string","description":"Claim grant only: the post-claim identity assertion."},"assertion_expires":{"type":"string","format":"date-time"}},"required":["access_token","token_type","expires_in","scope"],"description":"auth.md grants issue no refresh_token (exchange the identity_assertion again); the authorization code and refresh grants do."},"TrustLevel":{"type":"string","enum":["verified","known","unknown","suspicious","quarantined"],"description":"Overall verdict, safest first. `quarantined` messages are labelled QUARANTINE and hidden from lists unless asked for."},"TrustReport":{"type":"object","properties":{"level":{"$ref":"#/components/schemas/TrustLevel"},"score":{"type":"number","minimum":0,"maximum":1,"description":"0 to 1, higher is safer. Ranks messages within a level."},"basis":{"type":"string","enum":["trusted_domain"],"description":"`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":{"type":"object","properties":{"spf":{"type":"string","enum":["pass","fail","softfail","neutral","none"]},"dkim":{"type":"string","enum":["pass","fail","none"]},"dmarc":{"type":"string","enum":["pass","fail","none"]},"aligned":{"type":"boolean","description":"Whether the authenticated domain aligns with the From domain."}},"required":["spf","dkim","dmarc","aligned"]},"sender":{"type":"object","properties":{"address":{"type":"string"},"domain":{"type":"string"},"prior_correspondence":{"type":"boolean","description":"An inbox in this organization has sent mail to this address before, or to someone else at its domain when the domain belongs to one organization (never a free mail provider, a privacy relay or a shared domain)."},"on_allow_list":{"type":"boolean"},"on_block_list":{"type":"boolean"},"free_mail_provider":{"type":"boolean"},"trusted_domain":{"type":"object","properties":{"id":{"type":"string","description":"ID of the trusted domain (`trusted_domain_id`)."},"domain":{"type":"string","description":"The trusted domain, or exact address, in ASCII (punycode) form."},"scope":{"$ref":"#/components/schemas/trustedDomains_Scope"}},"required":["id","domain","scope"],"description":"The trusted domain or address the message matches: its From address is the entry's and the message carries a DKIM signature from the entry's domain. It decided the verdict when `basis` is `trusted_domain`; otherwise `trusted_domain_shadowed_by` says what kept it from applying."},"trusted_domain_shadowed_by":{"type":"string","enum":["block","allow_only"],"description":"Set when a trusted domain matches but does not apply: `block`, a block entry matches the sender (blocks always win); `allow_only`, the inbox only accepts senders on its allow list, so the message is `BLOCKED`."}},"required":["address","domain","prior_correspondence","on_allow_list","on_block_list","free_mail_provider"]},"content":{"type":"object","properties":{"text":{"type":"string","description":"Agent-safe body: quotes, signatures, hidden text, zero-width characters and tracking pixels removed."},"html":{"type":"string","description":"Sanitized HTML: scripts, styles and hidden nodes removed."},"segments":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["body","quote","signature","hidden","disclaimer"]},"text":{"type":"string"}},"required":["kind","text"]}},"hidden_text_found":{"type":"boolean"},"zero_width_found":{"type":"boolean"},"tracking_pixels":{"type":"integer"},"agent_instructions_detected":{"type":"boolean","description":"Trusted mail only (`basis` is `trusted_domain`): the message contains instructions to an AI agent, or a high-confidence phishing signal, so its level is capped at `known`. It is still delivered in full; do not act on it automatically."},"warnings":{"type":"array","items":{"type":"string"},"description":"Trusted mail only: what the content checks found. Each says whether it capped the level (\"Level capped at Known: ...\") or was not acted on because the sender is trusted."}},"required":["text","segments","hidden_text_found","zero_width_found","tracking_pixels"]},"links":{"type":"array","items":{"type":"object","properties":{"href":{"type":"string"},"text":{"type":"string"},"final_url":{"type":"string","description":"Where the link redirects to, when redirects were followed."},"domain":{"type":"string"},"display_mismatch":{"type":"boolean","description":"The link text shows a different domain than the link goes to."},"shortener":{"type":"boolean"},"suspicious":{"type":"boolean"},"reasons":{"type":"array","items":{"type":"string"}}},"required":["href","domain","display_mismatch","shortener","suspicious","reasons"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"attachment_id":{"type":"string"},"filename":{"type":"string"},"content_type":{"type":"string"},"risk":{"type":"string","enum":["low","medium","high"]},"reasons":{"type":"array","items":{"type":"string"}},"extracted_text":{"type":"string"}},"required":["attachment_id","risk","reasons"]}},"classification":{"type":"object","properties":{"is_spam":{"type":"number","minimum":0,"maximum":1,"description":"Probability (0 to 1) that the message is spam."},"is_phishing":{"type":"number","minimum":0,"maximum":1,"description":"Probability (0 to 1) that the message is phishing."},"contains_instructions_to_agent":{"type":"number","minimum":0,"maximum":1,"description":"Probability (0 to 1) that the message tries to instruct an AI agent (prompt injection)."},"requests_credentials_or_payment":{"type":"number","minimum":0,"maximum":1,"description":"Probability (0 to 1) that the message asks for credentials or payment."},"urgency":{"type":"number","minimum":0,"maximum":1,"description":"How urgent the message presents itself (0 to 1)."},"category":{"type":"string","enum":["transactional","conversation","notification","newsletter","otp","bounce","other"]},"language":{"type":"string"},"backend":{"type":"string","description":"Classifier that produced these scores."},"input_hash":{"type":"string","description":"Hash of the exact input sent to the remote classifier, for audit. Absent when only the built-in rules ran."},"cached":{"type":"boolean","description":"True when the remote classifier verdict was reused for an identical input."}},"required":["is_spam","is_phishing","contains_instructions_to_agent","requests_credentials_or_payment","urgency","category","backend"]},"provider_verdicts":{"type":"object","properties":{"spam":{"type":"string","enum":["pass","fail","gray","none"],"description":"Spam scan. `fail` makes the message at most `suspicious`."},"virus":{"type":"string","enum":["pass","fail","gray","none"],"description":"Virus scan. `fail` quarantines the message."},"source":{"type":"string","description":"Who scanned it (for example `SES`)."}},"description":"Spam and virus scans by the receiving mail provider. Only on messages it scanned."},"reasons":{"type":"array","items":{"type":"string"},"description":"Human-readable reasons for the verdict."},"computed_at":{"type":"string","format":"date-time","description":"When the report was computed."}},"required":["level","score","authentication","sender","content","links","attachments","classification","reasons","computed_at"],"description":"Trust report of an inbound message. Message content is untrusted: feed `content.text` to an LLM rather than the message `text` or `html`."},"User":{"type":"object","properties":{"user_id":{"type":"string","description":"ID of the user."},"email":{"type":"string","description":"Email address the user signs in with."},"name":{"type":["string","null"],"description":"Display name, when set."},"organization_id":{"type":"string","description":"ID of the organization this record is about: the session’s active organization, or the organization listed."},"role":{"type":"string","enum":["owner","admin","member"],"description":"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":{"type":"string","format":"date-time","description":"When the user was created."}},"required":["user_id","email","organization_id","role","created_at"],"description":"A person who signs in to the dashboard."},"apiKeys_ApiKeyId":{"type":"string","description":"ID of the API key."},"apiKeys_ApiKeyPermissions":{"type":"object","properties":{"*":{"type":"boolean","x-machinemail":true,"description":"Every permission except `inbound_raw`. `{\"*\": true, \"inbound_raw\": true}` is full access plus raw injection."},"inbox_read":{"type":"boolean","description":"Read inbox details."},"inbox_create":{"type":"boolean","description":"Create new inboxes."},"inbox_update":{"type":"boolean","description":"Update inbox settings."},"inbox_delete":{"type":"boolean","description":"Delete inboxes."},"thread_read":{"type":"boolean","x-machinemail":true,"description":"Read threads."},"thread_delete":{"type":"boolean","x-machinemail":true,"description":"Delete threads."},"message_read":{"type":"boolean","description":"Read messages."},"message_reply":{"type":"boolean","description":"Reply and reply-all. `message_send` allows them too."},"message_send":{"type":"boolean","description":"Send messages (and reply, reply-all, forward)."},"message_update":{"type":"boolean","description":"Update message labels. Also required to update threads."},"message_delete":{"type":"boolean","description":"Delete messages."},"label_spam_read":{"type":"boolean","description":"Access messages labeled spam."},"label_blocked_read":{"type":"boolean","description":"Access messages labeled blocked."},"label_unauthenticated_read":{"type":"boolean","description":"Access messages labeled unauthenticated."},"label_trash_read":{"type":"boolean","description":"Access messages labeled trash."},"draft_read":{"type":"boolean","description":"Read drafts."},"draft_create":{"type":"boolean","description":"Create drafts."},"draft_update":{"type":"boolean","description":"Update drafts."},"draft_delete":{"type":"boolean","description":"Delete drafts."},"draft_send":{"type":"boolean","description":"Send drafts."},"webhook_read":{"type":"boolean","description":"Read webhook configurations."},"webhook_create":{"type":"boolean","description":"Create webhooks."},"webhook_update":{"type":"boolean","description":"Update webhooks."},"webhook_delete":{"type":"boolean","description":"Delete webhooks."},"domain_read":{"type":"boolean","description":"Read domain details."},"domain_create":{"type":"boolean","description":"Create domains."},"domain_update":{"type":"boolean","description":"Update domains."},"domain_delete":{"type":"boolean","description":"Delete domains."},"list_entry_read":{"type":"boolean","description":"Read list entries and suppressions."},"list_entry_create":{"type":"boolean","description":"Create list entries and suppressions."},"list_entry_delete":{"type":"boolean","description":"Delete list entries and suppressions."},"trusted_domain_read":{"type":"boolean","x-machinemail":true,"description":"Read trusted domains and preview new ones."},"trusted_domain_create":{"type":"boolean","x-machinemail":true,"description":"Add trusted domains. Organization API keys and the dashboard only: pod and inbox keys get `403` even with it."},"trusted_domain_update":{"type":"boolean","x-machinemail":true,"description":"Change trusted domains. Organization API keys and the dashboard only, as for `trusted_domain_create`."},"trusted_domain_delete":{"type":"boolean","x-machinemail":true,"description":"Remove trusted domains."},"metrics_read":{"type":"boolean","description":"Read metrics and events."},"api_key_read":{"type":"boolean","description":"Read API keys."},"api_key_create":{"type":"boolean","description":"Create API keys."},"api_key_update":{"type":"boolean","description":"Update API keys."},"api_key_delete":{"type":"boolean","description":"Delete API keys."},"pod_read":{"type":"boolean","description":"Read pods."},"pod_create":{"type":"boolean","description":"Create pods."},"pod_update":{"type":"boolean","description":"Update pods."},"pod_delete":{"type":"boolean","description":"Delete pods."},"inbound_raw":{"type":"boolean","x-machinemail":true,"description":"Inject raw mail with `POST /inbound/raw`. Never implied by an unrestricted key or `*`: it must be granted by name."}},"additionalProperties":{"type":"boolean"},"description":"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`."},"apiKeys_BearerApiKey":{"type":"object","properties":{"type":{"type":"string","enum":["bearer"],"description":"Always `bearer`: MachineMail has no public-key credentials."},"api_key_id":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"prefix":{"type":"string","description":"First 12 characters of the key (`mm_live_` and 4 more), safe to display."},"name":{"type":"string","description":"Name of the key."},"pod_id":{"type":"string","description":"Pod the key is scoped to: it can only access resources in this pod."},"inbox_id":{"type":"string","description":"Inbox the key is scoped to: it can only access this inbox."},"permissions":{"$ref":"#/components/schemas/apiKeys_ApiKeyPermissions"},"created_at":{"type":"string","format":"date-time","description":"Time at which the key was created."},"expires_at":{"type":"string","format":"date-time","description":"Time at which the key expires: requests with it then get `401`. Absent when it does not expire."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"used_at":{"type":"string","format":"date-time","description":"Time at which the key was last used."},"revoked_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the key was deleted (revoked). Revoked keys are not listed but can still be fetched by ID."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the name, permissions or revocation last changed. Use does not change it."}},"required":["type","api_key_id","prefix","name","created_at","organization_id","updated_at"],"description":"An API key presented as a bearer token in the `Authorization` header."},"apiKeys_CreateApiKeyResponse":{"type":"object","properties":{"api_key_id":{"$ref":"#/components/schemas/apiKeys_ApiKeyId"},"prefix":{"type":"string","description":"First 12 characters of the key (`mm_live_` and 4 more), safe to display."},"name":{"type":"string","description":"Name of the key."},"pod_id":{"type":"string","description":"Pod the key is scoped to: it can only access resources in this pod."},"inbox_id":{"type":"string","description":"Inbox the key is scoped to: it can only access this inbox."},"permissions":{"$ref":"#/components/schemas/apiKeys_ApiKeyPermissions"},"created_at":{"type":"string","format":"date-time","description":"Time at which the key was created."},"expires_at":{"type":"string","format":"date-time","description":"Time at which the key expires: requests with it then get `401`. Absent when it does not expire."},"api_key":{"type":"string","description":"The key itself (`mm_live_` and 32 characters). Returned once; only a hash is stored."}},"required":["api_key_id","prefix","name","created_at","api_key"]},"apiKeys_CreateBearerApiKeyRequest":{"type":"object","properties":{"name":{"type":"string","description":"Name of the key. Default `API key`."},"permissions":{"type":["object","null"],"properties":{"*":{"type":"boolean","x-machinemail":true,"description":"Every permission except `inbound_raw`. `{\"*\": true, \"inbound_raw\": true}` is full access plus raw injection."},"inbox_read":{"type":"boolean","description":"Read inbox details."},"inbox_create":{"type":"boolean","description":"Create new inboxes."},"inbox_update":{"type":"boolean","description":"Update inbox settings."},"inbox_delete":{"type":"boolean","description":"Delete inboxes."},"thread_read":{"type":"boolean","x-machinemail":true,"description":"Read threads."},"thread_delete":{"type":"boolean","x-machinemail":true,"description":"Delete threads."},"message_read":{"type":"boolean","description":"Read messages."},"message_reply":{"type":"boolean","description":"Reply and reply-all. `message_send` allows them too."},"message_send":{"type":"boolean","description":"Send messages (and reply, reply-all, forward)."},"message_update":{"type":"boolean","description":"Update message labels. Also required to update threads."},"message_delete":{"type":"boolean","description":"Delete messages."},"label_spam_read":{"type":"boolean","description":"Access messages labeled spam."},"label_blocked_read":{"type":"boolean","description":"Access messages labeled blocked."},"label_unauthenticated_read":{"type":"boolean","description":"Access messages labeled unauthenticated."},"label_trash_read":{"type":"boolean","description":"Access messages labeled trash."},"draft_read":{"type":"boolean","description":"Read drafts."},"draft_create":{"type":"boolean","description":"Create drafts."},"draft_update":{"type":"boolean","description":"Update drafts."},"draft_delete":{"type":"boolean","description":"Delete drafts."},"draft_send":{"type":"boolean","description":"Send drafts."},"webhook_read":{"type":"boolean","description":"Read webhook configurations."},"webhook_create":{"type":"boolean","description":"Create webhooks."},"webhook_update":{"type":"boolean","description":"Update webhooks."},"webhook_delete":{"type":"boolean","description":"Delete webhooks."},"domain_read":{"type":"boolean","description":"Read domain details."},"domain_create":{"type":"boolean","description":"Create domains."},"domain_update":{"type":"boolean","description":"Update domains."},"domain_delete":{"type":"boolean","description":"Delete domains."},"list_entry_read":{"type":"boolean","description":"Read list entries and suppressions."},"list_entry_create":{"type":"boolean","description":"Create list entries and suppressions."},"list_entry_delete":{"type":"boolean","description":"Delete list entries and suppressions."},"trusted_domain_read":{"type":"boolean","x-machinemail":true,"description":"Read trusted domains and preview new ones."},"trusted_domain_create":{"type":"boolean","x-machinemail":true,"description":"Add trusted domains. Organization API keys and the dashboard only: pod and inbox keys get `403` even with it."},"trusted_domain_update":{"type":"boolean","x-machinemail":true,"description":"Change trusted domains. Organization API keys and the dashboard only, as for `trusted_domain_create`."},"trusted_domain_delete":{"type":"boolean","x-machinemail":true,"description":"Remove trusted domains."},"metrics_read":{"type":"boolean","description":"Read metrics and events."},"api_key_read":{"type":"boolean","description":"Read API keys."},"api_key_create":{"type":"boolean","description":"Create API keys."},"api_key_update":{"type":"boolean","description":"Update API keys."},"api_key_delete":{"type":"boolean","description":"Delete API keys."},"pod_read":{"type":"boolean","description":"Read pods."},"pod_create":{"type":"boolean","description":"Create pods."},"pod_update":{"type":"boolean","description":"Update pods."},"pod_delete":{"type":"boolean","description":"Delete pods."},"inbound_raw":{"type":"boolean","x-machinemail":true,"description":"Inject raw mail with `POST /inbound/raw`. Never implied by an unrestricted key or `*`: it must be granted by name."}},"additionalProperties":{"type":"boolean"},"description":"Permissions of the new key. Omitted or `null`: full access for the key scope (`inbound_raw` excepted)."},"expires_at":{"type":["string","null"],"format":"date-time","description":"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."}},"description":"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."},"apiKeys_ListApiKeysResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"type":"integer","x-machinemail":true,"description":"Page size used."},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"api_keys":{"type":"array","items":{"$ref":"#/components/schemas/apiKeys_BearerApiKey"},"description":"Keys in the route scope that are not revoked, ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","limit","api_keys"]},"apiKeys_UpdateApiKeyRequest":{"type":"object","properties":{"name":{"type":"string","description":"New name. A blank name is ignored."},"permissions":{"type":"object","properties":{"*":{"type":"boolean","x-machinemail":true,"description":"Every permission except `inbound_raw`. `{\"*\": true, \"inbound_raw\": true}` is full access plus raw injection."},"inbox_read":{"type":"boolean","description":"Read inbox details."},"inbox_create":{"type":"boolean","description":"Create new inboxes."},"inbox_update":{"type":"boolean","description":"Update inbox settings."},"inbox_delete":{"type":"boolean","description":"Delete inboxes."},"thread_read":{"type":"boolean","x-machinemail":true,"description":"Read threads."},"thread_delete":{"type":"boolean","x-machinemail":true,"description":"Delete threads."},"message_read":{"type":"boolean","description":"Read messages."},"message_reply":{"type":"boolean","description":"Reply and reply-all. `message_send` allows them too."},"message_send":{"type":"boolean","description":"Send messages (and reply, reply-all, forward)."},"message_update":{"type":"boolean","description":"Update message labels. Also required to update threads."},"message_delete":{"type":"boolean","description":"Delete messages."},"label_spam_read":{"type":"boolean","description":"Access messages labeled spam."},"label_blocked_read":{"type":"boolean","description":"Access messages labeled blocked."},"label_unauthenticated_read":{"type":"boolean","description":"Access messages labeled unauthenticated."},"label_trash_read":{"type":"boolean","description":"Access messages labeled trash."},"draft_read":{"type":"boolean","description":"Read drafts."},"draft_create":{"type":"boolean","description":"Create drafts."},"draft_update":{"type":"boolean","description":"Update drafts."},"draft_delete":{"type":"boolean","description":"Delete drafts."},"draft_send":{"type":"boolean","description":"Send drafts."},"webhook_read":{"type":"boolean","description":"Read webhook configurations."},"webhook_create":{"type":"boolean","description":"Create webhooks."},"webhook_update":{"type":"boolean","description":"Update webhooks."},"webhook_delete":{"type":"boolean","description":"Delete webhooks."},"domain_read":{"type":"boolean","description":"Read domain details."},"domain_create":{"type":"boolean","description":"Create domains."},"domain_update":{"type":"boolean","description":"Update domains."},"domain_delete":{"type":"boolean","description":"Delete domains."},"list_entry_read":{"type":"boolean","description":"Read list entries and suppressions."},"list_entry_create":{"type":"boolean","description":"Create list entries and suppressions."},"list_entry_delete":{"type":"boolean","description":"Delete list entries and suppressions."},"trusted_domain_read":{"type":"boolean","x-machinemail":true,"description":"Read trusted domains and preview new ones."},"trusted_domain_create":{"type":"boolean","x-machinemail":true,"description":"Add trusted domains. Organization API keys and the dashboard only: pod and inbox keys get `403` even with it."},"trusted_domain_update":{"type":"boolean","x-machinemail":true,"description":"Change trusted domains. Organization API keys and the dashboard only, as for `trusted_domain_create`."},"trusted_domain_delete":{"type":"boolean","x-machinemail":true,"description":"Remove trusted domains."},"metrics_read":{"type":"boolean","description":"Read metrics and events."},"api_key_read":{"type":"boolean","description":"Read API keys."},"api_key_create":{"type":"boolean","description":"Create API keys."},"api_key_update":{"type":"boolean","description":"Update API keys."},"api_key_delete":{"type":"boolean","description":"Delete API keys."},"pod_read":{"type":"boolean","description":"Read pods."},"pod_create":{"type":"boolean","description":"Create pods."},"pod_update":{"type":"boolean","description":"Update pods."},"pod_delete":{"type":"boolean","description":"Delete pods."},"inbound_raw":{"type":"boolean","x-machinemail":true,"description":"Inject raw mail with `POST /inbound/raw`. Never implied by an unrestricted key or `*`: it must be granted by name."}},"additionalProperties":{"type":"boolean"},"description":"New permissions; replaces the permission object in full."}},"description":"Fields you omit are unchanged. `permissions` replaces the permission object in full. Scope and expiry cannot be changed."},"attachments_Attachment":{"type":"object","properties":{"attachment_id":{"$ref":"#/components/schemas/attachments_AttachmentId"},"filename":{"type":"string","description":"Filename of the attachment."},"size":{"type":"integer","description":"Size of the attachment in bytes."},"content_type":{"type":"string","description":"Content type of the attachment."},"content_disposition":{"type":"string","description":"Content disposition of the attachment (`inline` or `attachment`)."},"content_id":{"type":"string","description":"Content ID of the attachment."}},"required":["attachment_id","size"]},"attachments_AttachmentId":{"type":"string","description":"ID of the attachment."},"attachments_AttachmentResponse":{"type":"object","properties":{"attachment_id":{"$ref":"#/components/schemas/attachments_AttachmentId"},"filename":{"type":"string","description":"Filename of the attachment."},"size":{"type":"integer","description":"Size of the attachment in bytes."},"content_type":{"type":"string","description":"Content type of the attachment."},"content_disposition":{"type":"string","description":"Content disposition of the attachment (`inline` or `attachment`)."},"content_id":{"type":"string","description":"Content ID of the attachment."},"download_url":{"type":"string","description":"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":{"type":"string","format":"date-time","description":"When `download_url` expires: one hour from the request unless the signed URL sets its own expiry."}},"required":["attachment_id","size","download_url","expires_at"]},"attachments_SendAttachment":{"type":"object","properties":{"filename":{"type":"string","description":"Filename of the attachment. Defaults to the last segment of `url`."},"content_type":{"type":"string","description":"Content type of the attachment. Defaults to the `Content-Type` of the `url` response."},"content_disposition":{"type":"string","enum":["inline","attachment"],"description":"Content disposition of the attachment."},"content_id":{"type":"string","description":"Content ID, for inline images referenced as `cid:` in the HTML body."},"content":{"type":"string","description":"Base64 encoded content of the attachment."},"url":{"type":"string","description":"URL the API downloads the attachment from: public http(s) only, no redirects, at most 10 MB, 20 second timeout."}},"description":"Provide either `content` or `url` for each attachment."},"auth_Identity":{"type":"object","properties":{"scope_type":{"$ref":"#/components/schemas/auth_ScopeType"},"scope_id":{"type":"string","description":"ID of the most specific scope: `inbox_id` for an inbox credential, `pod_id` for a pod credential, otherwise `organization_id`."},"organization_id":{"type":"string","description":"ID of the organization."},"pod_id":{"type":"string","description":"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":{"type":"string","description":"ID of the inbox the credential is scoped to. Present when `scope_type` is `inbox`."},"api_key_id":{"type":"string","description":"ID of the API key used. Absent for dashboard sessions and agent access tokens."},"api_key_expires_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the API key used expires. Absent when it does not expire, and for other credentials."},"user":{"type":"object","properties":{"user_id":{"type":"string","description":"ID of the user."},"email":{"type":"string","description":"Email address the user signs in with."},"name":{"type":["string","null"],"description":"Display name, when set."},"organization_id":{"type":"string","description":"ID of the organization this record is about: the session’s active organization, or the organization listed."},"role":{"type":"string","enum":["owner","admin","member"],"description":"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":{"type":"string","format":"date-time","description":"When the user was created."}},"required":["user_id","email","organization_id","role","created_at"],"description":"The signed-in user, for a dashboard session.","x-machinemail":true}},"required":["scope_type","scope_id","organization_id"],"description":"Identity and scope of the credential."},"auth_ScopeType":{"type":"string","enum":["organization","pod","inbox"],"description":"The scope tier the credential is bound to."},"domains_CreateDomainRequest":{"type":"object","properties":{"domain":{"type":"string","description":"The domain name, for example `example.com`. Cannot be the shared domain or a domain another organization registered."},"feedback_enabled":{"type":"boolean","description":"Stored and returned; has no effect. Default `false`."},"inbound_enabled":{"type":"boolean","description":"Receive email for this domain. Default `true`. `false` makes it send-only (the inbound MX record is not required)."},"client_id":{"type":"string","x-machinemail":true,"description":"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":{"type":"string","x-machinemail":true,"description":"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":{"type":"boolean","x-machinemail":true,"description":"Create an inbox for any address at the domain that receives mail. Default `false`."},"catch_all_ttl_seconds":{"type":["integer","null"],"exclusiveMinimum":0,"x-machinemail":true,"description":"Make inboxes created by catch-all ephemeral with this TTL. `null` or absent: permanent."}},"required":["domain"]},"domains_Domain":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the domain belongs to."},"domain_id":{"$ref":"#/components/schemas/domains_DomainId"},"domain":{"type":"string","description":"The domain name (for example `example.com`), lowercased."},"feedback_enabled":{"type":"boolean","description":"Stored as given. MachineMail does not send bounce and complaint notifications to inboxes; use the `message.bounced` and `message.complained` events."},"inbound_enabled":{"type":"boolean","description":"Receive email for this domain. `false` makes it send-only: the inbound MX record is not required."},"subdomains_enabled":{"type":"boolean","description":"Always `false`: inboxes on subdomains are not supported."},"tracking_enabled":{"type":"boolean","description":"Always `false`: open tracking is not supported."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the domain was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the domain was created."},"status":{"$ref":"#/components/schemas/domains_VerificationStatus"},"reason":{"type":"string","description":"Why the domain is not verified yet: what to do next, or which records are missing or invalid. Absent once `VERIFIED`."},"records":{"type":"array","items":{"$ref":"#/components/schemas/domains_VerificationRecord"},"description":"DNS records to publish."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"catch_all":{"type":"boolean","x-machinemail":true,"description":"Mail to any address at the domain without an inbox creates one (`created_by: catch_all`)."},"catch_all_ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of inboxes created by catch-all; absent means they are permanent."},"nameservers":{"type":"array","items":{"type":"string"},"x-machinemail":true,"description":"Authoritative nameservers, detected on create and verify."},"dns_provider":{"type":"string","enum":["cloudflare","route53","google","vercel","namecheap","godaddy","digitalocean","hetzner","porkbun","other"],"x-machinemail":true,"description":"DNS host the nameservers belong to."},"dns_provider_url":{"type":"string","x-machinemail":true,"description":"Link to the DNS host console."},"domain_connect":{"type":"object","properties":{"supported":{"type":"boolean","description":"The zone DNS provider supports Domain Connect and has the MachineMail template."},"provider_name":{"type":"string","description":"Display name of the DNS provider."},"apply_url":{"type":"string","description":"Signed link that opens the provider with the outstanding records prefilled. Absent when nothing is left to add."}},"required":["supported"],"x-machinemail":true,"description":"One-click DNS setup (Domain Connect), from the last discovery. See Get Domain Connect Setup."},"verified_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the domain became `VERIFIED`."},"last_checked_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the DNS records were last checked."}},"required":["pod_id","domain_id","domain","feedback_enabled","inbound_enabled","subdomains_enabled","tracking_enabled","updated_at","created_at","status","records","organization_id","catch_all"]},"domains_DomainConnect":{"type":"object","properties":{"supported":{"type":"boolean","description":"The zone DNS provider supports Domain Connect and has the MachineMail template."},"provider_name":{"type":"string","description":"Display name of the DNS provider."},"apply_url":{"type":"string","description":"Signed link that opens the provider with the outstanding records prefilled. Absent when nothing is left to add."},"provider_id":{"type":"string","description":"Domain Connect provider ID."},"url_sync_ux":{"type":"string","description":"Base URL of the provider synchronous flow."},"width":{"type":"integer","description":"Suggested popup width, in pixels."},"height":{"type":"integer","description":"Suggested popup height, in pixels."},"reason":{"type":"string","enum":["no_domain_connect","provider_error","no_sync_flow","template_not_supported","records_not_templatable","already_configured","not_configured"],"description":"Why one-click setup is not available, or `already_configured` when nothing is left to add."},"checked_at":{"type":"string","format":"date-time","description":"When discovery last ran."}},"required":["supported","checked_at"]},"domains_DomainId":{"type":"string","description":"ID of the domain."},"domains_DomainItem":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the domain belongs to."},"domain_id":{"$ref":"#/components/schemas/domains_DomainId"},"domain":{"type":"string","description":"The domain name (for example `example.com`), lowercased."},"feedback_enabled":{"type":"boolean","description":"Stored as given. MachineMail does not send bounce and complaint notifications to inboxes; use the `message.bounced` and `message.complained` events."},"inbound_enabled":{"type":"boolean","description":"Receive email for this domain. `false` makes it send-only: the inbound MX record is not required."},"subdomains_enabled":{"type":"boolean","description":"Always `false`: inboxes on subdomains are not supported."},"tracking_enabled":{"type":"boolean","description":"Always `false`: open tracking is not supported."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the domain was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the domain was created."},"status":{"type":"string","enum":["NOT_STARTED","PENDING","INVALID","FAILED","VERIFYING","VERIFIED"],"x-machinemail":true,"description":"Verification status, as on Domain."},"reason":{"type":"string","description":"Why the domain is not verified yet, as on Domain.","x-machinemail":true},"records":{"type":"array","items":{"$ref":"#/components/schemas/domains_VerificationRecord"},"description":"DNS records to publish, as on Domain.","x-machinemail":true},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"catch_all":{"type":"boolean","x-machinemail":true,"description":"Mail to any address at the domain without an inbox creates one (`created_by: catch_all`)."},"catch_all_ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of inboxes created by catch-all; absent means they are permanent."},"nameservers":{"type":"array","items":{"type":"string"},"x-machinemail":true,"description":"Authoritative nameservers, detected on create and verify."},"dns_provider":{"type":"string","enum":["cloudflare","route53","google","vercel","namecheap","godaddy","digitalocean","hetzner","porkbun","other"],"x-machinemail":true,"description":"DNS host the nameservers belong to."},"dns_provider_url":{"type":"string","x-machinemail":true,"description":"Link to the DNS host console."},"domain_connect":{"type":"object","properties":{"supported":{"type":"boolean","description":"The zone DNS provider supports Domain Connect and has the MachineMail template."},"provider_name":{"type":"string","description":"Display name of the DNS provider."},"apply_url":{"type":"string","description":"Signed link that opens the provider with the outstanding records prefilled. Absent when nothing is left to add."}},"required":["supported"],"x-machinemail":true,"description":"One-click DNS setup (Domain Connect), from the last discovery. See Get Domain Connect Setup."},"verified_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the domain became `VERIFIED`."},"last_checked_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the DNS records were last checked."}},"required":["pod_id","domain_id","domain","feedback_enabled","inbound_enabled","subdomains_enabled","tracking_enabled","updated_at","created_at","status","records","organization_id","catch_all"]},"domains_ListDomainsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/domains_DomainItem"},"description":"Ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","domains"]},"domains_RecordStatus":{"type":"string","enum":["MISSING","INVALID","VALID"],"description":"`MISSING`: not published yet. `INVALID`: published with the wrong value."},"domains_RecordType":{"type":"string","enum":["TXT","CNAME","MX"]},"domains_UpdateDomainRequest":{"type":"object","properties":{"feedback_enabled":{"type":"boolean","description":"Stored and returned; has no effect."},"inbound_enabled":{"type":"boolean","description":"Receive email for this domain. `false` makes the inbound MX record optional and re-evaluates the status."},"catch_all":{"type":"boolean","x-machinemail":true,"description":"Create an inbox for any address at the domain that receives mail."},"catch_all_ttl_seconds":{"type":["integer","null"],"exclusiveMinimum":0,"x-machinemail":true,"description":"TTL of inboxes created by catch-all from now on. `null` makes them permanent."}}},"domains_VerificationRecord":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/domains_RecordType"},"name":{"type":"string","description":"Name (host) of the record."},"value":{"type":"string","description":"Value of the record."},"status":{"$ref":"#/components/schemas/domains_RecordStatus"},"priority":{"type":"integer","description":"Priority of an MX record."},"reason":{"type":"string","description":"Why an `INVALID` record is invalid: `Found: <values seen>`."},"purpose":{"type":"string","enum":["inbound","spf","dkim","dmarc","provider"],"x-machinemail":true,"description":"What the record is for. `provider` records come from the sending provider."},"required":{"type":"boolean","x-machinemail":true,"description":"Whether the record must be valid for the domain to verify. The inbound MX record is not required when `inbound_enabled` is false."}},"required":["type","name","value","status","purpose","required"]},"domains_VerificationStatus":{"type":"string","enum":["NOT_STARTED","PENDING","INVALID","FAILED","VERIFYING","VERIFIED"],"description":"`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)."},"drafts_CreateDraftRequest":{"type":"object","properties":{"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the draft."},"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Reply-to addresses: one address or a list."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Recipient addresses: one address or a list."},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"CC addresses: one address or a list."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"BCC addresses: one address or a list."},"subject":{"type":"string","description":"Subject."},"text":{"type":"string","description":"Plain text body."},"html":{"type":"string","description":"HTML body."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_SendAttachment"},"description":"Attachments, sent with the draft. Each needs `content` or `url`; a `url` is fetched when the draft is sent."},"in_reply_to":{"type":"string","description":"ID of a message in this inbox to reply to: the sent message gets its `In-Reply-To` and `References` headers."},"send_at":{"type":["string","null"],"format":"date-time","description":"Schedule the draft: it is sent automatically at this time (`send_status: scheduled`). `null` or absent: not scheduled."},"client_id":{"type":"string","description":"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."}}},"drafts_Draft":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"draft_id":{"$ref":"#/components/schemas/drafts_DraftId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the draft. The sent message gets them."},"to":{"type":"array","items":{"type":"string"},"description":"Recipient addresses."},"cc":{"type":"array","items":{"type":"string"},"description":"CC addresses."},"bcc":{"type":"array","items":{"type":"string"},"description":"BCC addresses."},"subject":{"type":"string","description":"Subject of the draft."},"preview":{"type":"string","description":"Text preview of the draft."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"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":{"type":"string","description":"ID of the message being replied to."},"send_status":{"$ref":"#/components/schemas/drafts_DraftSendStatus"},"send_at":{"type":"string","format":"date-time","description":"Time at which the draft is sent automatically."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the draft was last updated."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"reply_to":{"type":"array","items":{"type":"string"},"description":"Reply-to addresses."},"text":{"type":"string","description":"Plain text body."},"html":{"type":"string","description":"HTML body."},"references":{"type":"array","items":{"type":"string"},"description":"Message IDs the draft references (set from `in_reply_to`)."},"created_at":{"type":"string","format":"date-time","description":"Time at which the draft was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."}},"required":["inbox_id","draft_id","labels","updated_at","created_at","pod_id"]},"drafts_DraftId":{"type":"string","description":"ID of the draft."},"drafts_DraftItem":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"draft_id":{"$ref":"#/components/schemas/drafts_DraftId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the draft. The sent message gets them."},"to":{"type":"array","items":{"type":"string"},"description":"Recipient addresses."},"cc":{"type":"array","items":{"type":"string"},"description":"CC addresses."},"bcc":{"type":"array","items":{"type":"string"},"description":"BCC addresses."},"subject":{"type":"string","description":"Subject of the draft."},"preview":{"type":"string","description":"Text preview of the draft."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"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":{"type":"string","description":"ID of the message being replied to."},"send_status":{"$ref":"#/components/schemas/drafts_DraftSendStatus"},"send_at":{"type":"string","format":"date-time","description":"Time at which the draft is sent automatically."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the draft was last updated."},"client_id":{"type":"string","description":"Client ID given at creation.","x-machinemail":true},"reply_to":{"type":"array","items":{"type":"string"},"description":"Reply-to addresses.","x-machinemail":true},"text":{"type":"string","description":"Plain text body.","x-machinemail":true},"html":{"type":"string","description":"HTML body.","x-machinemail":true},"references":{"type":"array","items":{"type":"string"},"description":"Message IDs the draft references.","x-machinemail":true},"created_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"Time at which the draft was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."}},"required":["inbox_id","draft_id","labels","updated_at","created_at","pod_id"]},"drafts_DraftSendStatus":{"type":"string","enum":["scheduled","sending","failed"],"description":"`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`."},"drafts_ListDraftsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"drafts":{"type":"array","items":{"$ref":"#/components/schemas/drafts_DraftItem"},"description":"Ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","drafts"]},"drafts_UpdateDraftRequest":{"type":"object","properties":{"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Reply-to addresses. `null` clears them."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Recipient addresses. `null` clears them."},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"CC addresses. `null` clears them."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"BCC addresses. `null` clears them."},"subject":{"type":["string","null"],"description":"Subject. `null` clears it."},"text":{"type":["string","null"],"description":"Plain text body. `null` clears it."},"html":{"type":["string","null"],"description":"HTML body. `null` clears it."},"add_attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_SendAttachment"},"description":"Attachments to add. Each needs `content` or `url`."},"remove_attachments":{"type":"array","items":{"type":"string"},"description":"IDs of attachments to remove. Unknown IDs are ignored."},"add_labels":{"type":"array","items":{"type":"string"},"description":"Labels to add."},"remove_labels":{"type":"array","items":{"type":"string"},"description":"Labels to remove (applied after `add_labels`)."},"send_at":{"type":["string","null"],"format":"date-time","description":"Schedule (or reschedule) the draft. `null` unschedules it."}}},"events_Bounce":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"type":"string","description":"ID of the message."},"timestamp":{"type":"string","format":"date-time","description":"When it happened."},"type":{"type":"string","description":"Bounce type: `Permanent` or `Transient` (or the provider type)."},"sub_type":{"type":"string","description":"Bounce sub-type, `General` when the provider gives none."},"recipients":{"type":"array","items":{"$ref":"#/components/schemas/events_Recipient"},"description":"Bounced recipients. Permanent bounces are added to the suppression list."}},"required":["inbox_id","thread_id","message_id","timestamp","type","sub_type","recipients"]},"events_Complaint":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"type":"string","description":"ID of the message."},"timestamp":{"type":"string","format":"date-time","description":"When it happened."},"type":{"type":"string","description":"Complaint type, `complaint` when the provider gives none."},"sub_type":{"type":"string","description":"Complaint sub-type, `abuse` when the provider gives none."},"recipients":{"type":"array","items":{"$ref":"#/components/schemas/events_Recipient"},"description":"Complaining recipients, as `{address, status}` objects (AgentMail documents plain strings). They are added to the suppression list."}},"required":["inbox_id","thread_id","message_id","timestamp","type","sub_type","recipients"]},"events_Delivery":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"type":"string","description":"ID of the message."},"timestamp":{"type":"string","format":"date-time","description":"When it happened."},"recipients":{"type":"array","items":{"type":"string"},"description":"Delivered recipients."}},"required":["inbox_id","thread_id","message_id","timestamp","recipients"]},"events_DomainUpdatedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["domain.updated"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/domains_Domain"}},"required":["domain"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"domain":{"$ref":"#/components/schemas/domains_Domain"}},"required":["type","event_id","event_type","timestamp","data","domain"],"description":"A DNS check changed the domain `status` or a `records[].status` (verification progress). The change to `VERIFIED` also sends `domain.verified`. Sent only to webhooks whose `event_types` list it (an empty list does not include it)."},"events_DomainVerifiedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["domain.verified"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/domains_Domain"}},"required":["domain"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"domain":{"$ref":"#/components/schemas/domains_Domain"}},"required":["type","event_id","event_type","timestamp","data","domain"],"description":"A domain became `VERIFIED`."},"events_DraftSentEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["draft.sent"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"draft_id":{"type":"string","description":"ID of the sent (and now deleted) draft."},"inbox_id":{"type":"string","description":"ID of the inbox."},"send":{"type":"object","properties":{"message_id":{"type":"string","description":"ID of the message."},"thread_id":{"type":"string","description":"ID of the thread."},"timestamp":{"type":"string","format":"date-time","description":"When the message was sent."}},"required":["message_id","thread_id","timestamp"]}},"required":["draft_id","inbox_id","send"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"draft_id":{"type":"string","description":"ID of the sent (and now deleted) draft."},"inbox_id":{"type":"string","description":"ID of the inbox."},"send":{"type":"object","properties":{"message_id":{"type":"string","description":"ID of the message."},"thread_id":{"type":"string","description":"ID of the thread."},"timestamp":{"type":"string","format":"date-time","description":"When the message was sent."}},"required":["message_id","thread_id","timestamp"]}},"required":["type","event_id","event_type","timestamp","data","draft_id","inbox_id","send"],"description":"A draft was sent, explicitly or at its `send_at`. A `message.sent` event is emitted too."},"events_Event":{"type":"object","properties":{"event_id":{"type":"string","description":"ID of the event (`evt_...`). Sorts by creation time."},"event_type":{"type":"string","enum":["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"],"description":"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":{"type":"string","description":"ID of the organization."},"pod_id":{"type":"string","description":"ID of the pod. Absent for organization-level events."},"inbox_id":{"type":"string","description":"ID of the inbox. Absent for events without an inbox (for example `domain.verified`)."},"data":{"type":"object","additionalProperties":{},"description":"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":{"type":"string","format":"date-time","description":"When the event happened (same as `created_at`)."},"created_at":{"type":"string","format":"date-time","description":"When the event was stored."}},"required":["event_id","event_type","organization_id","data","timestamp","created_at"],"description":"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)."},"events_EventType":{"type":"string","enum":["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"],"description":"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."},"events_InboxCreatedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["inbox.created"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"inbox":{"$ref":"#/components/schemas/inboxes_Inbox"},"import_source":{"type":"string","enum":["agentmail"],"x-machinemail":true,"description":"Set when an importer copied the inbox from another provider (`import_source` on Create Inbox). Such events are recorded and streamed but never sent to webhooks."}},"required":["inbox"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"inbox":{"$ref":"#/components/schemas/inboxes_Inbox"},"import_source":{"type":"string","enum":["agentmail"],"x-machinemail":true,"description":"Set when an importer copied the inbox from another provider (`import_source` on Create Inbox). Such events are recorded and streamed but never sent to webhooks."}},"required":["type","event_id","event_type","timestamp","data","inbox"],"description":"An inbox was created (API, dashboard, catch-all, agent registration or an import)."},"events_InboxExpiredEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["inbox.expired"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"inbox":{"$ref":"#/components/schemas/inboxes_Inbox"},"deleted_messages":{"type":"integer","description":"Number of messages deleted with it."}},"required":["inbox","deleted_messages"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"inbox":{"$ref":"#/components/schemas/inboxes_Inbox"},"deleted_messages":{"type":"integer","description":"Number of messages deleted with it."}},"required":["type","event_id","event_type","timestamp","data","inbox","deleted_messages"],"description":"An ephemeral inbox expired and was deleted with its mail."},"events_ListEventsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"events":{"type":"array","items":{"$ref":"#/components/schemas/events_Event"},"description":"Newest first; oldest first when `after` is set or `ascending` is true."}},"required":["count","events"]},"events_MessageBouncedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.bounced"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"bounce":{"$ref":"#/components/schemas/events_Bounce"}},"required":["bounce"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"bounce":{"$ref":"#/components/schemas/events_Bounce"}},"required":["type","event_id","event_type","timestamp","data","bounce"],"description":"A sent message bounced."},"events_MessageComplainedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.complained"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"complaint":{"$ref":"#/components/schemas/events_Complaint"}},"required":["complaint"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"complaint":{"$ref":"#/components/schemas/events_Complaint"}},"required":["type","event_id","event_type","timestamp","data","complaint"],"description":"A recipient marked a sent message as spam."},"events_MessageDeliveredEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.delivered"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"delivery":{"$ref":"#/components/schemas/events_Delivery"}},"required":["delivery"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"delivery":{"$ref":"#/components/schemas/events_Delivery"}},"required":["type","event_id","event_type","timestamp","data","delivery"],"description":"The receiving server accepted a sent message."},"events_MessageReceivedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.received","message.received.spam","message.received.quarantined","message.received.unauthenticated","message.received.blocked"],"description":"Which inbox folder the message landed in: `message.received` (inbox), `.spam`, `.quarantined`, `.unauthenticated` or `.blocked`."},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/messages_Message"},"thread":{"$ref":"#/components/schemas/threads_ThreadItem"}},"required":["message","thread"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"message":{"$ref":"#/components/schemas/messages_Message"},"thread":{"$ref":"#/components/schemas/threads_ThreadItem"}},"required":["type","event_id","event_type","timestamp","data","message","thread"],"description":"A message was received and stored. The sub-types use the same payload."},"events_MessageRejectedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.rejected"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"reject":{"$ref":"#/components/schemas/events_Reject"}},"required":["reject"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"reject":{"$ref":"#/components/schemas/events_Reject"}},"required":["type","event_id","event_type","timestamp","data","reject"],"description":"An incoming message was refused and not stored."},"events_MessageSentEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["message.sent"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"send":{"$ref":"#/components/schemas/events_Send"},"message":{"$ref":"#/components/schemas/messages_Message","x-machinemail":true,"description":"The sent message."},"thread":{"$ref":"#/components/schemas/threads_ThreadItem","x-machinemail":true,"description":"Its thread."}},"required":["send","message","thread"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"send":{"$ref":"#/components/schemas/events_Send"},"message":{"$ref":"#/components/schemas/messages_Message","x-machinemail":true,"description":"The sent message."},"thread":{"$ref":"#/components/schemas/threads_ThreadItem","x-machinemail":true,"description":"Its thread."}},"required":["type","event_id","event_type","timestamp","data","send","message","thread"],"description":"A message was sent (send, reply, forward or draft)."},"events_Recipient":{"type":"object","properties":{"address":{"type":"string","description":"Recipient address."},"status":{"type":"string","description":"`bounced` or `complained`."}},"required":["address","status"]},"events_Reject":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"null","description":"Always `null`: nothing was stored."},"message_id":{"type":"null","description":"Always `null`: nothing was stored."},"timestamp":{"type":"string","format":"date-time","description":"When it happened."},"reason":{"type":"string","enum":["inbox_paused","plan_limit","plan_limit_expired"],"description":"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":{"type":"string","x-machinemail":true,"description":"Sender of the rejected message."},"subject":{"type":"string","x-machinemail":true,"description":"Subject of the rejected message."}},"required":["inbox_id","thread_id","message_id","timestamp","reason","from"]},"events_Send":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"type":"string","description":"ID of the message."},"timestamp":{"type":"string","format":"date-time","description":"When it happened."},"recipients":{"type":"array","items":{"type":"string"},"description":"Every recipient (to, cc and bcc)."}},"required":["inbox_id","thread_id","message_id","timestamp","recipients"]},"events_TrustedDomainCreatedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["trusted_domain.created"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["trusted_domain"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["type","event_id","event_type","timestamp","data","trusted_domain"],"description":"A trusted domain was created (MachineMail): the entry as it is now. Sent only to webhooks whose `event_types` list it (an empty list does not include it)."},"events_TrustedDomainDeletedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["trusted_domain.deleted"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["trusted_domain"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["type","event_id","event_type","timestamp","data","trusted_domain"],"description":"A trusted domain was deleted (MachineMail): the entry as it was. Sent only to webhooks whose `event_types` list it (an empty list does not include it)."},"events_TrustedDomainUpdatedEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["trusted_domain.updated"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["trusted_domain"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"trusted_domain":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"}},"required":["type","event_id","event_type","timestamp","data","trusted_domain"],"description":"A trusted domain was updated (MachineMail): the entry as it is now. Sent only to webhooks whose `event_types` list it (an empty list does not include it)."},"events_WebhookTestEvent":{"type":"object","properties":{"type":{"type":"string","enum":["event"]},"event_id":{"type":"string","description":"ID of the event (`evt_...`), as in `GET /v0/events`."},"event_type":{"type":"string","enum":["webhook.test"]},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the event happened."},"data":{"type":"object","properties":{"webhook_id":{"type":"string","description":"ID of the tested webhook."},"message":{"type":"string","description":"`This is a test event from MachineMail.`"}},"required":["webhook_id","message"],"x-machinemail":true,"description":"The payload: the same keys as at the top level."},"webhook_id":{"type":"string","description":"ID of the tested webhook."},"message":{"type":"string","description":"`This is a test event from MachineMail.`"}},"required":["type","event_id","event_type","timestamp","data","webhook_id","message"],"description":"Sent by `POST /v0/webhooks/{webhook_id}/test` to that webhook only, whatever its `event_types`."},"inboxes_CreateInboxRequest":{"type":"object","properties":{"username":{"type":"string","description":"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":{"type":"string","description":"Domain of the address: a domain verified by this organization. Defaults to the shared domain."},"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"client_id":{"type":"string","description":"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":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"$ref":"#/components/schemas/inboxes_Metadata"},"pod_id":{"type":"string","x-machinemail":true,"description":"Pod to create the inbox in. Defaults to the credential pod or the organization default pod."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"`true` without `ttl_seconds` creates an ephemeral inbox with a one hour TTL (3600 seconds)."},"ttl_seconds":{"type":["integer","null"],"exclusiveMinimum":0,"x-machinemail":true,"description":"Creates an ephemeral inbox that expires `ttl_seconds` after creation, extended by each inbound message."},"import_source":{"type":"string","enum":["agentmail"],"x-machinemail":true,"description":"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."}}},"inboxes_Inbox":{"type":"object","properties":{"pod_id":{"type":"string","description":"ID of the pod the inbox belongs to."},"inbox_id":{"$ref":"#/components/schemas/inboxes_InboxId"},"email":{"type":"string","description":"Email address of the inbox."},"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"status":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"$ref":"#/components/schemas/inboxes_Metadata"},"updated_at":{"type":"string","format":"date-time","description":"Time at which the inbox was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the inbox was created."},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"Whether the inbox expires (see `ttl_seconds`)."},"ttl_seconds":{"type":"integer","x-machinemail":true,"description":"TTL of an ephemeral inbox. Each inbound message pushes `expires_at` to now + `ttl_seconds`."},"expires_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"When an ephemeral inbox and its mail are deleted."},"created_by":{"type":"string","enum":["api","catch_all","dashboard","agent"],"x-machinemail":true,"description":"What created the inbox: the API, a catch-all domain, the dashboard or an agent registration."}},"required":["pod_id","inbox_id","email","status","updated_at","created_at","organization_id","ephemeral","created_by"]},"inboxes_InboxAvailability":{"type":"object","properties":{"available":{"type":"boolean"},"email":{"type":"string","description":"The address that was checked (lowercased)."},"reason":{"type":"string","enum":["invalid_username","domain_not_found","taken"],"description":"Why the address is not available."},"message":{"type":"string","description":"Human-readable reason."}},"required":["available","email"]},"inboxes_InboxId":{"type":"string","description":"ID of the inbox: its email address, as in AgentMail (`inbox_id == email`)."},"inboxes_InboxStatus":{"type":"string","enum":["active","paused"],"description":"Whether the inbox sends and receives mail. `paused` stops both: sends return `403` (`Inbox <inbox_id> 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."},"inboxes_ListInboxesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"inboxes":{"type":"array","items":{"$ref":"#/components/schemas/inboxes_Inbox"},"description":"Ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","inboxes"]},"inboxes_Metadata":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/inboxes_MetadataValue"},"description":"Custom key-value pairs attached to the inbox."},"inboxes_MetadataValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}],"description":"A metadata value: a string, number or boolean."},"inboxes_SearchInboxesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"inboxes":{"type":"array","items":{"$ref":"#/components/schemas/inboxes_Inbox"},"description":"Matching inboxes, newest first."},"truncated":{"type":"boolean","enum":[true],"x-machinemail":true,"description":"Present when the organization has more than 500 inboxes in scope: only the newest 500 were searched."}},"required":["count","inboxes"]},"inboxes_UpdateInboxRequest":{"type":"object","properties":{"display_name":{"type":"string","description":"Display name: `Display Name <username@domain.com>`."},"status":{"$ref":"#/components/schemas/inboxes_InboxStatus"},"metadata":{"type":["object","null"],"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}],"description":"A metadata value, or null to remove the key."},"description":"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":{"type":["integer","null"],"exclusiveMinimum":0,"x-machinemail":true,"description":"Make the inbox ephemeral with this TTL (`expires_at` restarts from now), or `null` to make it permanent."},"ephemeral":{"type":"boolean","x-machinemail":true,"description":"`false` makes the inbox permanent (same as `ttl_seconds: null`). `true` alone has no effect; send `ttl_seconds`."}}},"lists_CreateListEntryRequest":{"type":"object","properties":{"entry":{"type":"string","minLength":1,"description":"Email address or domain to add."},"reason":{"type":"string","description":"Reason for adding the entry."}},"required":["entry"]},"lists_Direction":{"type":"string","enum":["send","receive","reply"],"description":"`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."},"lists_EntryType":{"type":"string","enum":["email","domain"],"description":"Whether the entry is an email address or a domain."},"lists_ListEntry":{"type":"object","properties":{"entry":{"type":"string","description":"Email address or domain (lowercased)."},"organization_id":{"type":"string","description":"ID of the organization."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod, for pod-scoped entries."},"inbox_id":{"type":"string","x-machinemail":true,"description":"ID of the inbox, for inbox-scoped entries."},"reason":{"type":"string","description":"Reason given when the entry was added."},"direction":{"$ref":"#/components/schemas/lists_Direction"},"list_type":{"$ref":"#/components/schemas/lists_ListType"},"entry_type":{"$ref":"#/components/schemas/lists_EntryType"},"read_only":{"type":"boolean","description":"Always `false`: every entry can be deleted through the API."},"created_at":{"type":"string","format":"date-time","description":"Time at which the entry was created."}},"required":["entry","organization_id","direction","list_type","entry_type","read_only","created_at"],"description":"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."},"lists_ListListEntriesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/lists_ListEntry"},"description":"Ordered by `entry`, ascending unless `ascending` is false."}},"required":["count","entries"]},"lists_ListType":{"type":"string","enum":["allow","block"],"description":"`block` refuses matching addresses. `allow` makes the list exclusive: once it has an entry, only matching addresses pass."},"messages_BatchGetMessagesRequest":{"type":"object","properties":{"message_ids":{"type":"array","items":{"type":"string"},"description":"IDs of the messages to fetch. Only the first 100 distinct IDs are read."}},"required":["message_ids"]},"messages_BatchGetMessagesResponse":{"type":"object","properties":{"limit":{"type":"integer","description":"Number of IDs in the request."},"count":{"type":"integer","description":"Number of messages returned."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/messages_Message"},"description":"Found messages, in request order. IDs not found in the inbox are omitted."}},"required":["limit","count","messages"]},"messages_BatchUpdateMessagesRequest":{"type":"object","properties":{"message_ids":{"type":"array","items":{"type":"string"},"description":"IDs of the messages to update. Only the first 100 distinct IDs are updated."},"add_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to add to every message."},"remove_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to remove from every message."}},"required":["message_ids"]},"messages_BatchUpdateMessagesResponse":{"type":"object","properties":{"limit":{"type":"integer","description":"Number of IDs in the request."},"count":{"type":"integer","description":"Number of messages updated."},"updates":{"type":"array","items":{"$ref":"#/components/schemas/messages_UpdateMessageResponse"},"description":"Updated messages with their new labels, in request order. IDs not found are omitted."}},"required":["limit","count","updates"]},"messages_ListMessagesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/messages_MessageItem"},"description":"Ordered by `timestamp`, newest first unless `ascending` is set."}},"required":["count","messages"]},"messages_Message":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"$ref":"#/components/schemas/messages_MessageId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the message."},"timestamp":{"type":"string","format":"date-time","description":"Time at which the message was sent or received."},"from":{"type":"string","description":"Address of the sender. In format `username@domain.com` or `Display Name <username@domain.com>`."},"to":{"type":"array","items":{"type":"string"},"description":"Addresses of the recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"cc":{"type":"array","items":{"type":"string"},"description":"Addresses of the CC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"bcc":{"type":"array","items":{"type":"string"},"description":"Addresses of the BCC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"subject":{"type":"string","description":"Subject of the message."},"preview":{"type":"string","description":"Text preview of the message."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"Attachments of the message."},"in_reply_to":{"type":"string","description":"ID of the message being replied to."},"references":{"type":"array","items":{"type":"string"},"description":"IDs of previous messages in the thread."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers of the message."},"authentication_results":{"$ref":"#/components/schemas/messages_MessageAuthenticationResults"},"size":{"type":"integer","description":"Size of the message in bytes."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the message was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the message was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."},"direction":{"type":"string","enum":["inbound","outbound"],"x-machinemail":true,"description":"Whether the message was received or sent."},"delivery_status":{"type":"string","enum":["sent","delivered","bounced","complained"],"x-machinemail":true,"description":"Outbound only: last delivery state reported by the transport."},"trust_level":{"$ref":"#/components/schemas/TrustLevel","x-machinemail":true,"description":"Inbound only: `trust.level`, for list badges."},"reply_to":{"type":"array","items":{"type":"string"},"description":"Reply-to addresses. In format `username@domain.com` or `Display Name <username@domain.com>`."},"text":{"type":"string","description":"Plain text body. Untrusted: agents should read `trust.content.text` or `extracted_text`."},"html":{"type":"string","description":"HTML body. Untrusted."},"extracted_text":{"type":"string","description":"New text content, without quoted replies."},"extracted_html":{"type":"string","description":"New HTML content, without quoted replies."},"received_via":{"type":"string","enum":["raw"],"x-machinemail":true,"description":"`raw` when the message was injected with `POST /inbound/raw` (authentication not verified)."},"held_at":{"type":"string","format":"date-time","x-machinemail":true,"description":"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":{"$ref":"#/components/schemas/TrustReport","x-machinemail":true,"description":"Trust report of an inbound message."}},"required":["inbox_id","thread_id","message_id","labels","timestamp","from","to","size","updated_at","created_at","pod_id","direction"]},"messages_MessageAuthenticationDomain":{"type":"string","description":"Lowercase domain an authentication verdict is about. Present only beside its verdict."},"messages_MessageAuthenticationResults":{"type":"object","properties":{"spf":{"$ref":"#/components/schemas/messages_MessageAuthenticationVerdict"},"dkim":{"$ref":"#/components/schemas/messages_MessageAuthenticationVerdict"},"dmarc":{"$ref":"#/components/schemas/messages_MessageAuthenticationVerdict"},"spf_domain":{"$ref":"#/components/schemas/messages_MessageAuthenticationDomain","description":"Envelope sender (MAIL FROM) domain the `spf` verdict is about (`smtp.mailfrom`, or the HELO name when the envelope sender was empty)."},"dkim_domain":{"$ref":"#/components/schemas/messages_MessageAuthenticationDomain","description":"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":{"$ref":"#/components/schemas/messages_MessageAuthenticationDomain","description":"From domain the `dmarc` verdict is about (`header.from`)."},"arc_sealer":{"$ref":"#/components/schemas/messages_MessageAuthenticationDomain","description":"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."}},"description":"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.\n\nAs 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.\n\nUnlike 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."},"messages_MessageAuthenticationVerdict":{"type":"string","enum":["pass","fail","none","neutral","softfail","temperror","permerror"],"description":"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."},"messages_MessageId":{"type":"string","description":"ID of the message."},"messages_MessageItem":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"type":"string","description":"ID of the thread."},"message_id":{"$ref":"#/components/schemas/messages_MessageId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the message."},"timestamp":{"type":"string","format":"date-time","description":"Time at which the message was sent or received."},"from":{"type":"string","description":"Address of the sender. In format `username@domain.com` or `Display Name <username@domain.com>`."},"to":{"type":"array","items":{"type":"string"},"description":"Addresses of the recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"cc":{"type":"array","items":{"type":"string"},"description":"Addresses of the CC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"bcc":{"type":"array","items":{"type":"string"},"description":"Addresses of the BCC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`."},"subject":{"type":"string","description":"Subject of the message."},"preview":{"type":"string","description":"Text preview of the message."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"Attachments of the message."},"in_reply_to":{"type":"string","description":"ID of the message being replied to."},"references":{"type":"array","items":{"type":"string"},"description":"IDs of previous messages in the thread."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers of the message."},"authentication_results":{"$ref":"#/components/schemas/messages_MessageAuthenticationResults"},"size":{"type":"integer","description":"Size of the message in bytes."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the message was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the message was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."},"direction":{"type":"string","enum":["inbound","outbound"],"x-machinemail":true,"description":"Whether the message was received or sent."},"delivery_status":{"type":"string","enum":["sent","delivered","bounced","complained"],"x-machinemail":true,"description":"Outbound only: last delivery state reported by the transport."},"trust_level":{"$ref":"#/components/schemas/TrustLevel","x-machinemail":true,"description":"Inbound only: `trust.level`, for list badges."}},"required":["inbox_id","thread_id","message_id","labels","timestamp","from","to","size","updated_at","created_at","pod_id","direction"],"description":"A message without its bodies, as in lists."},"messages_ReplyAllMessageRequest":{"type":"object","properties":{"labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Labels of the message. `SENT` is always added."},"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Reply-to address or addresses."},"text":{"type":"string","description":"Plain text body."},"html":{"type":"string","description":"HTML body."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_SendAttachment"},"description":"Attachments to include."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers to include. `In-Reply-To` and `References` also thread the message."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"x-machinemail":true,"description":"More recipients, added to the sender and recipients of the original."},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"x-machinemail":true,"description":"More CC recipients, added to the CC recipients of the original."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"x-machinemail":true,"description":"BCC recipient address or addresses."},"subject":{"type":"string","x-machinemail":true,"description":"Subject of the reply. Defaults to the original subject with `Re: ` in front."}}},"messages_ReplyToMessageRequest":{"type":"object","properties":{"labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Labels of the message. `SENT` is always added."},"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Reply-to address or addresses."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Recipient address or addresses. Defaults to the sender of the original (its reply-to addresses if any); for an outbound original, its recipients."},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"CC recipient address or addresses."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"BCC recipient address or addresses."},"reply_all":{"type":"boolean","description":"`true` replies to all recipients of the original, as Reply All Message does; `to` and `cc` are then added to them."},"text":{"type":"string","description":"Plain text body."},"html":{"type":"string","description":"HTML body."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_SendAttachment"},"description":"Attachments to include."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers to include. `In-Reply-To` and `References` also thread the message."},"subject":{"type":"string","x-machinemail":true,"description":"Subject of the reply. Defaults to the original subject with `Re: ` in front."}}},"messages_SearchMessagesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/messages_MessageItem"},"description":"Matching messages, newest first unless `ascending` is set."}},"required":["count","messages"]},"messages_SendMessageRequest":{"type":"object","properties":{"labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Labels of the message. `SENT` is always added."},"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Reply-to address or addresses."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Recipient address or addresses."},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"CC recipient address or addresses."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"BCC recipient address or addresses."},"subject":{"type":"string","description":"Subject of the message."},"text":{"type":"string","description":"Plain text body."},"html":{"type":"string","description":"HTML body."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_SendAttachment"},"description":"Attachments to include."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers to include. `In-Reply-To` and `References` also thread the message."}}},"messages_SendMessageResponse":{"type":"object","properties":{"message_id":{"$ref":"#/components/schemas/messages_MessageId"},"thread_id":{"type":"string","description":"ID of the thread."},"timestamp":{"type":"string","format":"date-time","x-machinemail":true,"description":"When the message was sent."}},"required":["message_id","thread_id","timestamp"]},"messages_UpdateMessageRequest":{"type":"object","properties":{"add_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to add."},"remove_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to remove."}}},"messages_UpdateMessageResponse":{"type":"object","properties":{"message_id":{"$ref":"#/components/schemas/messages_MessageId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the message after the update."}},"required":["message_id","labels"]},"metrics_MetricBucket":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the bucket."},"count":{"type":"integer","description":"Number of events in the bucket."}},"required":["timestamp","count"]},"metrics_QueryMetricsResponse":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/metrics_MetricBucket"}},"description":"One series per requested event type, keyed by event type. Every bucket in the range is present, with a zero count when nothing happened."},"metrics_QueryRatesResponse":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/metrics_RatePoint"}},"description":"One series per requested rate type."},"metrics_QueryUsageResponse":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/metrics_UsagePoint"}},"description":"One series per requested usage type. Usage history is not kept: each series has one point, the current value, at `end`."},"metrics_RatePoint":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"End of the window the point covers; the window is the `window` seconds before it."},"rate":{"type":"number","description":"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":{"type":"integer","description":"Messages sent in the window."}},"required":["timestamp","sent"]},"metrics_UsagePoint":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Time of the value (`end`)."},"value":{"type":"integer","description":"Value of the usage metric now."}},"required":["timestamp","value"]},"organizations_CreateInvitationRequest":{"type":"object","properties":{"email":{"type":"string","description":"Address to invite."},"role":{"type":"string","enum":["owner","admin","member"],"description":"Role on joining. Default `member`. Only owners can invite owners."}},"required":["email"]},"organizations_DeleteOrganizationRequest":{"type":"object","properties":{"code":{"type":"string","description":"The 6-digit code from the email.","example":"123456"}},"required":["code"]},"organizations_DeleteOrganizationResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"organization_id":{"type":"string","description":"ID of the deleted organization."}},"required":["ok","organization_id"],"description":"The organization is deleted."},"organizations_Invitation":{"type":"object","properties":{"invitation_id":{"type":"string","description":"ID of the invitation."},"organization_id":{"type":"string","description":"ID of the organization the invitee joins."},"email":{"type":"string","description":"Address the invitation was sent to. Only this address can accept it."},"role":{"type":"string","enum":["owner","admin","member"],"description":"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":{"type":"string","enum":["pending","accepted","expired","revoked"],"description":"State of the invitation."},"invited_by_user_id":{"type":"string","description":"ID of the member who sent it, when known."},"expires_at":{"type":"string","format":"date-time","description":"When the invitation stops working (7 days after it was sent)."},"created_at":{"type":"string","format":"date-time","description":"When the invitation was sent."}},"required":["invitation_id","organization_id","email","role","state","expires_at","created_at"],"description":"An invitation to join the organization."},"organizations_ListInvitationsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"invitations":{"type":"array","items":{"$ref":"#/components/schemas/organizations_Invitation"},"description":"Pending invitations, newest first."}},"required":["count","invitations"]},"organizations_ListMembersResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"members":{"type":"array","items":{"$ref":"#/components/schemas/organizations_Member"},"description":"Oldest first unless `ascending=false`."}},"required":["count","members"]},"organizations_Member":{"type":"object","properties":{"user_id":{"type":"string","description":"ID of the user."},"email":{"type":"string","description":"Email address the user signs in with."},"name":{"type":["string","null"],"description":"Display name, when set."},"organization_id":{"type":"string","description":"ID of the organization this record is about: the session’s active organization, or the organization listed."},"role":{"type":"string","enum":["owner","admin","member"],"description":"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":{"type":"string","format":"date-time","description":"When the user was created."},"sign_in_methods":{"type":"array","items":{"$ref":"#/components/schemas/organizations_SignInMethod"},"description":"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":{"type":["string","null"],"enum":["email","password","google","github","apple","microsoft","sso","passkey",null],"description":"How the member last signed in to this organization. `null` until their first sign-in after this was recorded."}},"required":["user_id","email","organization_id","role","created_at","sign_in_methods","last_sign_in_method"],"description":"A person in the organization, with their role there and how they sign in."},"organizations_Organization":{"type":"object","properties":{"organization_id":{"type":"string","description":"ID of the organization."},"name":{"type":"string","x-machinemail":true,"description":"Name of the organization."},"slug":{"type":"string","x-machinemail":true,"description":"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":{"type":"string","enum":["free","pro","team","scale"],"description":"Plan of the organization.","x-machinemail":true},"inbox_count":{"type":"integer","description":"Number of inboxes in the credential scope."},"domain_count":{"type":"integer","description":"Number of domains in the organization."},"domain_limit":{"type":"integer","description":"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":{"type":"object","properties":{"message_count":{"type":"integer","description":"Messages stored in the organization."},"storage_bytes":{"type":"integer","description":"Bytes of stored messages."},"messages_received_30d":{"type":"integer","description":"Messages received in the last 30 days."},"messages_sent_30d":{"type":"integer","description":"Messages sent in the last 30 days."}},"required":["message_count","storage_bytes","messages_received_30d","messages_sent_30d"],"description":"Usage. Always present on `GET /v0/organizations` and `PATCH /v0/organizations`.","x-machinemail":true},"shared_domain":{"type":"string","x-machinemail":true,"description":"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":{"type":"boolean","example":true,"x-machinemail":true,"description":"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":{"type":["string","null"],"example":"acme@machinemail.dev","x-machinemail":true,"description":"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":{"type":"string","format":"date-time","description":"Time at which the organization was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the organization was created."}},"required":["organization_id","name","slug","plan","inbox_count","domain_count","undo_send","default_inbox_id","updated_at","created_at"],"description":"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."},"organizations_OrganizationDeletionStarted":{"type":"object","properties":{"email":{"type":"string","description":"Where the code was sent: your own address, partly hidden."},"expires_at":{"type":"string","format":"date-time","description":"When the code stops working (10 minutes after it was sent)."}},"required":["email","expires_at"],"description":"A confirmation code was emailed to you."},"organizations_PlanLimits":{"type":"object","properties":{"messages_per_month":{"type":["integer","null"],"description":"Inbound messages and outbound recipients together per calendar month (UTC). `null`: no combined cap (paid plans)."},"messages_per_day":{"type":["integer","null"],"description":"The same, per UTC day. `null`: no daily cap."},"inbound_per_month":{"type":["integer","null"],"description":"Inbound messages included per month on paid plans (more is billed as overage). `null` on Free."},"outbound_per_month":{"type":["integer","null"],"description":"Outbound recipients included per month on paid plans (more is billed as overage). `null` on Free."},"storage_bytes":{"type":"integer","description":"Storage included, in bytes (1 GB = 1,000,000,000 bytes)."},"custom_domains":{"type":"integer","description":"Custom domains included."},"seats":{"type":["integer","null"],"description":"Members (including pending invitations). `null`: unlimited."},"overage":{"type":"boolean","description":"`true`: usage past an allowance is billed, never blocked. `false` (Free): inbound past it is held and sending is refused until the reset."}},"required":["messages_per_month","messages_per_day","inbound_per_month","outbound_per_month","storage_bytes","custom_domains","seats","overage"],"description":"The allowances that apply to the organization."},"organizations_PlanUsage":{"type":"object","properties":{"plan":{"type":"string","enum":["free","pro","team","scale"],"description":"Plan of the organization: `free`, `pro`, `team` or `scale`."},"period":{"type":"object","properties":{"start":{"type":"string","format":"date-time","description":"Start of the current billing period (first instant of the calendar month, UTC)."},"resets_at":{"type":"string","format":"date-time","description":"When the monthly allowances reset (first instant of the next calendar month, UTC)."},"day_resets_at":{"type":"string","format":"date-time","description":"When the daily cap resets (next midnight, UTC)."}},"required":["start","resets_at","day_resets_at"]},"limits":{"$ref":"#/components/schemas/organizations_PlanLimits"},"usage":{"type":"object","properties":{"inbound":{"type":"integer","description":"Inbound messages counted this period (spam and quarantined mail never count)."},"outbound":{"type":"integer","description":"Outbound recipients counted this period (each recipient of a message counts once)."},"messages":{"type":"integer","description":"`inbound` + `outbound`."},"messages_today":{"type":"integer","description":"Inbound messages delivered (or released from held) and outbound recipients counted today (UTC)."},"storage_bytes":{"type":"integer","description":"Bytes stored now: messages (spam and quarantined mail excluded), drafts and held mail."},"custom_domains":{"type":"integer","description":"Custom domains of the organization."},"seats":{"type":"integer","description":"Members plus pending invitations."}},"required":["inbound","outbound","messages","messages_today","storage_bytes","custom_domains","seats"]},"held":{"type":"object","properties":{"count":{"type":"integer","description":"Inbound messages held because the organization reached a Free plan limit. They are delivered (oldest first) when the allowance resets or after an upgrade."},"bytes":{"type":"integer","description":"Size of the held messages."},"oldest_at":{"type":["string","null"],"format":"date-time","description":"When the oldest held message arrived."}},"required":["count","bytes","oldest_at"]},"enforcement":{"type":"string","enum":["enforce","shadow","off","exempt"],"description":"`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)."}},"required":["plan","period","limits","usage","held","enforcement"],"description":"Plan allowances and usage of the organization in the current period."},"organizations_SignInMethod":{"type":"string","enum":["email","password","google","github","apple","microsoft","sso","passkey"],"description":"How a person signed in: `email` (an emailed code or link), `password`, a social provider (`google`, `github`, `apple`, `microsoft`), `sso` (single sign-on) or `passkey`."},"organizations_StartOrganizationDeletionRequest":{"type":"object","properties":{"confirm_name":{"type":"string","description":"The name of the organization, exactly as it is shown (case and spaces included)."}},"required":["confirm_name"]},"organizations_UpdateMemberRequest":{"type":"object","properties":{"role":{"type":"string","enum":["owner","admin","member"],"description":"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."}},"required":["role"]},"organizations_UpdateOrganizationRequest":{"type":"object","properties":{"name":{"type":"string","description":"New name. Must not be blank."},"slug":{"type":"string","x-machinemail":true,"description":"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":{"type":"boolean","example":true,"x-machinemail":true,"description":"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":{"type":["string","null"],"example":"acme@machinemail.dev","x-machinemail":true,"description":"Make this inbox (an `inbox_id` of the organization) the default inbox, or `null` to have none. An unknown inbox is a `404`."}}},"pods_CreatePodRequest":{"type":"object","properties":{"name":{"type":"string","description":"Name of the pod. Default `Untitled pod`."},"client_id":{"type":"string","description":"Idempotency key: a create with a `client_id` already used in the organization returns that pod with `200`."}}},"pods_ListPodsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"pods":{"type":"array","items":{"$ref":"#/components/schemas/pods_Pod"},"description":"Ordered by `created_at`, newest first unless `ascending` is set. A pod credential sees only its pod."}},"required":["count","pods"]},"pods_Pod":{"type":"object","properties":{"pod_id":{"$ref":"#/components/schemas/pods_PodId"},"organization_id":{"type":"string","x-machinemail":true,"description":"ID of the organization."},"name":{"type":"string","description":"Name of the pod."},"is_default":{"type":"boolean","x-machinemail":true,"description":"Whether this is the default pod, where inboxes go when no pod is given. It cannot be deleted."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the pod was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the pod was created."}},"required":["pod_id","organization_id","name","is_default","updated_at","created_at"]},"pods_PodId":{"type":"string","description":"ID of the pod."},"pods_UpdatePodRequest":{"type":"object","properties":{"name":{"type":"string","description":"New name. Must not be blank."}}},"suppressions_CreateSuppressionRequest":{"type":"object","properties":{"email":{"type":"string","description":"Address to suppress."},"detail":{"type":"string","description":"Note stored as `detail`."},"reason":{"type":"string","deprecated":true,"description":"Old name of `detail` (it is stored as `detail`; the suppression `reason` is always `manual`). Ignored when `detail` is set."}},"required":["email"]},"suppressions_ListSuppressionsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"suppressions":{"type":"array","items":{"$ref":"#/components/schemas/suppressions_Suppression"},"description":"Newest first unless `ascending` is set."}},"required":["count","suppressions"]},"suppressions_Suppression":{"type":"object","properties":{"email":{"type":"string","description":"The suppressed address (lowercased)."},"organization_id":{"type":"string","description":"ID of the organization."},"reason":{"$ref":"#/components/schemas/suppressions_SuppressionReason"},"detail":{"type":"string","description":"Free text: the bounce diagnostic, or the note given when the address was added manually."},"source_message_id":{"type":"string","description":"Message whose bounce or complaint caused the suppression."},"created_at":{"type":"string","format":"date-time","description":"When the address was suppressed."}},"required":["email","organization_id","reason","created_at"],"description":"An address MachineMail will not send to. Suppressions apply to the whole organization."},"suppressions_SuppressionReason":{"type":"string","enum":["bounce","complaint","manual"],"description":"`bounce`: a permanent bounce. `complaint`: the recipient reported spam; only MachineMail support can remove it. `manual`: added with `POST /v0/suppressions`."},"threads_ListThreadsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"threads":{"type":"array","items":{"$ref":"#/components/schemas/threads_ThreadItem"},"description":"Ordered by `timestamp`, newest first unless `ascending` is set."},"truncated":{"type":"boolean","enum":[true],"x-machinemail":true,"description":"Present when `q` matched more than 500 messages: only the threads of the newest 500 matching messages were considered."}},"required":["count","threads"]},"threads_SearchThreadsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"threads":{"type":"array","items":{"$ref":"#/components/schemas/threads_ThreadItem"},"description":"Matching threads, ordered by `timestamp`, newest first unless `ascending` is set."},"truncated":{"type":"boolean","enum":[true],"x-machinemail":true,"description":"Present when `q` matched more than 500 messages: only the threads of the newest 500 matching messages were considered."}},"required":["count","threads"]},"threads_Thread":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"$ref":"#/components/schemas/threads_ThreadId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the thread: the union of the labels of its messages."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last sent or received message."},"received_timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last received message."},"sent_timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last sent message."},"senders":{"type":"array","items":{"type":"string"},"description":"Senders in the thread. In format `username@domain.com`."},"recipients":{"type":"array","items":{"type":"string"},"description":"Recipients (to and cc) in the thread. In format `username@domain.com`."},"subject":{"type":"string","description":"Subject of the thread."},"preview":{"type":"string","description":"Text preview of the last message in the thread."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"Attachments in the thread."},"last_message_id":{"type":"string","description":"ID of the last message in the thread."},"message_count":{"type":"integer","description":"Number of messages in the thread."},"size":{"type":"integer","description":"Size of the thread in bytes."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the thread was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the thread was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."},"count":{"type":"integer","description":"Number of messages in this page."},"limit":{"type":"integer","description":"Maximum number of messages requested for this page."},"next_page_token":{"type":"string","description":"Token for the next, older page of messages. Absent when this page completes the thread."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/messages_Message"},"description":"Messages in this page, oldest first. The first page has the newest messages; follow `next_page_token` for older ones."}},"required":["inbox_id","thread_id","labels","timestamp","senders","recipients","last_message_id","message_count","size","updated_at","created_at","pod_id","count","messages"]},"threads_ThreadId":{"type":"string","description":"ID of the thread."},"threads_ThreadItem":{"type":"object","properties":{"inbox_id":{"type":"string","description":"ID of the inbox."},"thread_id":{"$ref":"#/components/schemas/threads_ThreadId"},"labels":{"type":"array","items":{"type":"string"},"description":"Labels of the thread: the union of the labels of its messages."},"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last sent or received message."},"received_timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last received message."},"sent_timestamp":{"type":"string","format":"date-time","description":"Timestamp of the last sent message."},"senders":{"type":"array","items":{"type":"string"},"description":"Senders in the thread. In format `username@domain.com`."},"recipients":{"type":"array","items":{"type":"string"},"description":"Recipients (to and cc) in the thread. In format `username@domain.com`."},"subject":{"type":"string","description":"Subject of the thread."},"preview":{"type":"string","description":"Text preview of the last message in the thread."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/attachments_Attachment"},"description":"Attachments in the thread."},"last_message_id":{"type":"string","description":"ID of the last message in the thread."},"message_count":{"type":"integer","description":"Number of messages in the thread."},"size":{"type":"integer","description":"Size of the thread in bytes."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the thread was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the thread was created."},"pod_id":{"type":"string","x-machinemail":true,"description":"ID of the pod."}},"required":["inbox_id","thread_id","labels","timestamp","senders","recipients","last_message_id","message_count","size","updated_at","created_at","pod_id"]},"threads_UpdateThreadRequest":{"type":"object","properties":{"add_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to add to every message in the thread."},"remove_labels":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Label or labels to remove from every message in the thread. Applied after `add_labels`."}}},"trustedDomains_CreateTrustedDomainRequest":{"type":"object","properties":{"domain":{"type":"string","minLength":1,"maxLength":320,"description":"A domain (`example.com`) or an exact address (`invoices@example.com`). Unicode names are accepted and stored in ASCII (punycode) form."},"include_subdomains":{"type":"boolean","description":"Also trust mail signed by subdomains. Default `false`. Not allowed for an address."},"reason":{"type":"string","maxLength":500,"description":"Why you trust it, for people reading the list. Never included in a message’s trust report."},"expires_at":{"type":"string","format":"date-time","description":"When the entry stops applying. Must be in the future. Omit for never."},"confirm":{"type":"boolean","description":"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":{"type":"string","description":"Idempotency key: a create with a `client_id` already used in the organization returns that entry (200)."}},"required":["domain"]},"trustedDomains_CreatedTrustedDomain":{"type":"object","properties":{"trusted_domain_id":{"type":"string","description":"ID of the entry (`td_...`)."},"entry_type":{"$ref":"#/components/schemas/trustedDomains_EntryType"},"domain":{"type":"string","description":"The domain, or for `entry_type: \"email\"` the address, lowercased, with the domain in its ASCII (punycode) form."},"domain_unicode":{"type":"string","description":"The same, with the domain in its Unicode form. Equal to `domain` for ASCII names."},"include_subdomains":{"type":"boolean","description":"Also trust mail signed by subdomains (`billing.example.com` for `example.com`). Always `false` for addresses."},"scope":{"$ref":"#/components/schemas/trustedDomains_Scope"},"pod_id":{"type":["string","null"],"description":"The pod, for pod- and inbox-scoped entries."},"inbox_id":{"type":["string","null"],"description":"The inbox, for inbox-scoped entries."},"reason":{"type":["string","null"],"description":"Why it was added, for people reading the list. Never included in a message’s trust report."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the entry stops applying. `null`: never."},"created_by":{"$ref":"#/components/schemas/trustedDomains_Creator"},"match_count":{"type":"integer","description":"Messages this entry has marked trusted."},"last_matched_at":{"type":["string","null"],"format":"date-time","description":"When this entry last marked a message trusted. `null`: never."},"created_at":{"type":"string","format":"date-time","description":"When the entry was added."},"updated_at":{"type":"string","format":"date-time","description":"When the entry last changed."},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/trustedDomains_Warning"},"description":"Conflicts with block entries or allow-only scopes. Empty when there are none."}},"required":["trusted_domain_id","entry_type","domain","domain_unicode","include_subdomains","scope","pod_id","inbox_id","reason","expires_at","created_by","match_count","last_matched_at","created_at","updated_at","warnings"],"description":"The entry, with any warnings about mail that stays blocked."},"trustedDomains_Creator":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["user","api_key"],"description":"`user`: a person in the dashboard. `api_key`: an organization API key."},"id":{"type":"string","description":"The user ID or API key ID."}},"required":["type","id"],"description":"Who added the entry."},"trustedDomains_EntryType":{"type":"string","enum":["domain","email"],"description":"`domain`: every address at the domain (and its subdomains with `include_subdomains`). `email`: exactly one address."},"trustedDomains_ListTrustedDomainsResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"trusted_domains":{"type":"array","items":{"$ref":"#/components/schemas/trustedDomains_TrustedDomain"},"description":"Entries stored at exactly this level (organization, pod or inbox), newest first unless `ascending` is set."}},"required":["count","trusted_domains"]},"trustedDomains_PreviewTrustedDomainRequest":{"type":"object","properties":{"domain":{"type":"string","minLength":1,"maxLength":320,"description":"A domain (`example.com`) or an exact address (`invoices@example.com`). Unicode names are accepted and stored in ASCII (punycode) form."},"include_subdomains":{"type":"boolean","description":"As for create."}},"required":["domain"]},"trustedDomains_PreviewTrustedDomainResponse":{"type":"object","properties":{"domain":{"type":["string","null"],"description":"The entry as it would be stored (ASCII form). `null` when it is not a domain or address."},"domain_unicode":{"type":["string","null"],"description":"The same in Unicode form."},"entry_type":{"allOf":[{"$ref":"#/components/schemas/trustedDomains_EntryType"},{"type":["string","null"]}]},"allowed":{"type":"boolean","description":"Whether a create would be accepted (with `confirm: true` when `confirmation_required`), plan limit aside."},"refusal":{"type":["string","null"],"enum":["free_mail","privacy_relay","shared_platform","public_suffix","disposable","invalid","confusable_idn",null],"description":"Why it cannot be trusted. `null` when it can."},"message":{"type":["string","null"],"description":"The refusal or confirmation, in one sentence. `null` when there is neither."},"confirmation_required":{"type":"boolean","description":"A platform where anyone can write the content, or a relay address: a create needs `confirm: true`."},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/trustedDomains_Warning"},"description":"Conflicts with block entries or allow-only scopes, as a create would report them."},"would_release":{"type":["object","null"],"properties":{"count":{"type":"integer","description":"Held messages `apply_to_existing` would release."}},"required":["count"],"description":"Not computed yet: always `null`."},"suggestions":{"type":["array","null"],"items":{"type":"string"},"description":"Narrower entries to consider (an exact address). Not computed yet: always `null`."}},"required":["domain","domain_unicode","entry_type","allowed","refusal","message","confirmation_required","warnings","would_release","suggestions"],"description":"What a create would do, without saving anything."},"trustedDomains_Scope":{"type":"string","enum":["org","pod","inbox"],"description":"Where an entry applies: the whole organization, one pod, or one inbox."},"trustedDomains_TrustedDomain":{"type":"object","properties":{"trusted_domain_id":{"type":"string","description":"ID of the entry (`td_...`)."},"entry_type":{"$ref":"#/components/schemas/trustedDomains_EntryType"},"domain":{"type":"string","description":"The domain, or for `entry_type: \"email\"` the address, lowercased, with the domain in its ASCII (punycode) form."},"domain_unicode":{"type":"string","description":"The same, with the domain in its Unicode form. Equal to `domain` for ASCII names."},"include_subdomains":{"type":"boolean","description":"Also trust mail signed by subdomains (`billing.example.com` for `example.com`). Always `false` for addresses."},"scope":{"$ref":"#/components/schemas/trustedDomains_Scope"},"pod_id":{"type":["string","null"],"description":"The pod, for pod- and inbox-scoped entries."},"inbox_id":{"type":["string","null"],"description":"The inbox, for inbox-scoped entries."},"reason":{"type":["string","null"],"description":"Why it was added, for people reading the list. Never included in a message’s trust report."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the entry stops applying. `null`: never."},"created_by":{"$ref":"#/components/schemas/trustedDomains_Creator"},"match_count":{"type":"integer","description":"Messages this entry has marked trusted."},"last_matched_at":{"type":["string","null"],"format":"date-time","description":"When this entry last marked a message trusted. `null`: never."},"created_at":{"type":"string","format":"date-time","description":"When the entry was added."},"updated_at":{"type":"string","format":"date-time","description":"When the entry last changed."}},"required":["trusted_domain_id","entry_type","domain","domain_unicode","include_subdomains","scope","pod_id","inbox_id","reason","expires_at","created_by","match_count","last_matched_at","created_at","updated_at"],"description":"A trusted domain or address."},"trustedDomains_UpdateTrustedDomainRequest":{"type":"object","properties":{"include_subdomains":{"type":"boolean","description":"Also trust mail signed by subdomains. Not allowed for an address."},"confirm":{"type":"boolean","description":"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":{"type":["string","null"],"maxLength":500,"description":"New reason; `null` clears it."},"expires_at":{"type":["string","null"],"format":"date-time","description":"New expiry, in the future; `null` removes it."}}},"trustedDomains_Warning":{"type":"object","properties":{"code":{"type":"string","enum":["shadowed_by_block","shadowed_by_allow_only"],"description":"`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":{"$ref":"#/components/schemas/trustedDomains_Scope"},"pod_id":{"type":"string","description":"The pod of the list, for pod and inbox scopes."},"inbox_id":{"type":"string","description":"The inbox of the list, for the inbox scope."},"entry":{"type":"object","properties":{"entry":{"type":"string","description":"The list entry (address or domain)."},"entry_type":{"type":"string","enum":["email","domain"],"description":"Whether the list entry is an address or a domain."}},"required":["entry","entry_type"],"description":"`shadowed_by_block` only: the block entry. Left out for credentials without `list_entry_read`."},"message":{"type":"string","description":"What the warning means, in one sentence."}},"required":["code","scope","message"],"description":"A conflict that does not stop the entry from being saved, but means some of its mail is still blocked."},"webhooks_CreateWebhookRequest":{"type":"object","properties":{"url":{"type":"string","description":"Endpoint URL: a public http(s) URL (private and loopback addresses are rejected, and re-checked before every delivery)."},"event_types":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"},"description":"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":{"type":"string","description":"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":{"type":"array","items":{"type":"string"},"description":"Only deliver events of these inboxes."},"pod_ids":{"type":"array","items":{"type":"string"},"description":"Only deliver events of these pods."},"headers":{"$ref":"#/components/schemas/webhooks_WebhookHeaders"}},"required":["url"]},"webhooks_ListDeliveriesResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/webhooks_WebhookDelivery"},"description":"Ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","deliveries"]},"webhooks_ListWebhooksResponse":{"type":"object","properties":{"count":{"$ref":"#/components/schemas/Count"},"limit":{"$ref":"#/components/schemas/Limit"},"next_page_token":{"$ref":"#/components/schemas/PageToken"},"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/webhooks_Webhook"},"description":"Ordered by `created_at`, newest first unless `ascending` is set."}},"required":["count","webhooks"]},"webhooks_UpdateWebhookHeadersRequest":{"type":"object","properties":{"headers":{"$ref":"#/components/schemas/webhooks_WebhookHeaders"},"remove_headers":{"type":"array","items":{"type":"string"},"description":"Names of custom headers to remove (any case). Names that are not set are ignored."}},"description":"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."},"webhooks_UpdateWebhookRequest":{"type":"object","properties":{"event_types":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"},"description":"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":{"type":"boolean","description":"`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":{"type":"array","items":{"type":"string"},"description":"Inboxes to add to `inbox_ids`."},"remove_inbox_ids":{"type":"array","items":{"type":"string"},"description":"Inboxes to remove from `inbox_ids`."},"add_pod_ids":{"type":"array","items":{"type":"string"},"description":"Pods to add to `pod_ids`."},"remove_pod_ids":{"type":"array","items":{"type":"string"},"description":"Pods to remove from `pod_ids`."},"url":{"type":"string","x-machinemail":true,"description":"New endpoint URL: a public http(s) URL."},"headers":{"type":["object","null"],"additionalProperties":{"type":"string"},"x-machinemail":true,"description":"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."}}},"webhooks_Webhook":{"type":"object","properties":{"webhook_id":{"$ref":"#/components/schemas/webhooks_WebhookId"},"url":{"type":"string","description":"URL of the webhook endpoint."},"event_types":{"type":"array","items":{"$ref":"#/components/schemas/events_EventType"},"description":"Event types the webhook receives. Empty: every event type except `domain.updated` and `trusted_domain.*`, which are sent only when listed."},"pod_ids":{"type":"array","items":{"type":"string"},"description":"Only events of these pods. Absent: every pod in scope."},"inbox_ids":{"type":"array","items":{"type":"string"},"description":"Only events of these inboxes. Absent: every inbox in scope."},"pod_id":{"type":"string","description":"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":{"type":"string","description":"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":{"type":"string","description":"Signing secret (`whsec_...`) for `X-MachineMail-Signature`. Returned on every read."},"enabled":{"type":"boolean","description":"Whether new events are delivered. Webhooks are never disabled automatically."},"updated_at":{"type":"string","format":"date-time","description":"Time at which the webhook was last updated."},"created_at":{"type":"string","format":"date-time","description":"Time at which the webhook was created."},"client_id":{"type":"string","description":"Client ID given at creation (idempotency key)."},"status":{"type":"string","enum":["active","disabled"],"x-machinemail":true,"description":"`active` or `disabled`; mirrors `enabled`."},"header_names":{"type":"array","items":{"type":"string"},"x-machinemail":true,"description":"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":{"type":"string","format":"date-time","description":"When the custom headers were last set or changed. Absent when they never were.","x-machinemail":true}},"required":["webhook_id","url","event_types","secret","enabled","updated_at","created_at","status","header_names"]},"webhooks_WebhookDelivery":{"type":"object","properties":{"delivery_id":{"type":"string","description":"ID of the delivery (`X-MachineMail-Delivery-Id`)."},"webhook_id":{"type":"string","description":"ID of the webhook."},"event_id":{"type":"string","description":"ID of the event (`X-MachineMail-Event-Id`)."},"event_type":{"$ref":"#/components/schemas/events_EventType"},"attempt":{"type":"integer","description":"Number of attempts so far."},"status":{"type":"string","enum":["pending","delivered","failed"],"description":"`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":{"type":"integer","description":"HTTP status of the last attempt."},"response_body":{"type":"string","description":"First 1024 bytes of the last response body."},"next_attempt_at":{"type":"string","format":"date-time","description":"When the next attempt is due, while `pending`."},"last_error":{"type":"string","description":"Error of the last failed attempt (`HTTP 500`, a network error)."},"delivered_at":{"type":"string","format":"date-time","description":"When the delivery succeeded."},"created_at":{"type":"string","format":"date-time","description":"When the delivery was queued."},"updated_at":{"type":"string","format":"date-time","description":"Last change to the delivery."}},"required":["delivery_id","webhook_id","event_id","event_type","attempt","status","created_at","updated_at"]},"webhooks_WebhookHeaderNamesResponse":{"type":"object","properties":{"header_names":{"type":"array","items":{"type":"string"},"description":"Names of the custom delivery headers of this webhook, as they were set. Values are never returned."},"headers_updated_at":{"type":"string","format":"date-time","description":"When the custom headers were last set or changed. Absent when they never were.","x-machinemail":true}},"required":["header_names"]},"webhooks_WebhookHeaders":{"type":"object","additionalProperties":{"type":"string"},"description":"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 <token>\"}` 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."},"webhooks_WebhookId":{"type":"string","description":"ID of the webhook."}},"securitySchemes":{"Bearer":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer <token>`. The token is an API key (`mm_live_` followed by 32 base62 characters) or an auth.md agent access token (a JWT from `POST /oauth2/token`, see `/auth.md`)."},"QueryToken":{"type":"apiKey","in":"query","name":"token","description":"API key as `?token=`, for WebSocket and SSE clients that cannot set headers. Only `GET /v0/ws` and `GET /v0/events/stream` accept it."},"SessionCookie":{"type":"apiKey","in":"cookie","name":"mm_session","description":"Dashboard session cookie, set by `GET /auth/magic` (the magic sign-in link). Accepted on every `/v0` route; integrations should use API keys."}}}}