Docs

API reference

Every REST endpoint and object, generated from the OpenAPI file.

View as Markdown

Generated from openapi/openapi.yaml (version 0.1.0) at build time. Base URL: https://api.mueslimail.com. The API also serves the file itself at https://api.mueslimail.com/openapi.yaml.

Every operation answers on /v1, the current version, and on the deprecated /v0 alias with the same bodies and status codes. See Versions and SDKs for the deprecation headers, the policy and the official clients. The paths below show the /v0 prefix used by the file; replace it with /v1 and nothing else changes.

Endpoints

GET/v0/auth/me

Caller summary (kept for older clients; same body as GET /v0/me)

Responses

  • 200 OK: Me
  • 401 Error envelope: Error

GET/v0/me

The authenticated caller, a person's session or an API key

Responses

  • 200 OK: Me
  • 401 Error envelope: Error

GET/v0/auth/providers

Which sign in methods this deployment can complete (public)

Responses

  • 200 OK: object

POST/v0/auth/magic-link

Email a single use sign in link (public)

Body

NameTypeNotes
emailstring (email)required
redirect_afterstringPath on the site, for example /console/

Responses

  • 202 Sent (or accepted when the address has no account: same answer)
  • 303 A form post is redirected back to the login page with sent=1
  • 400 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error
  • 502 Error envelope: Error

POST/v0/auth/password/login

Sign in with an email address and a password (public)

Body

NameTypeNotes
emailstring (email)required
passwordstringrequired
redirect_afterstring

Responses

  • 200 Session, or the second factor step (MFAStep): Session
  • 303 A form post goes to the login page with the session in the fragment, or with ?error=<code>
  • 401 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/auth/password/signup

Create an account with an email address and a password (public)

Body

NameTypeNotes
emailstring (email)required
passwordstringrequired, max length 128
redirect_afterstring

Responses

  • 202 Confirmation link sent (same answer for an existing account)
  • 303 A form post is redirected back to the sign up page with sent=confirm
  • 400 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error
  • 502 Error envelope: Error

GET/v0/auth/password

Whether the person signed in has a password

Responses

  • 200 OK: object
  • 403 Error envelope: Error

PUT/v0/auth/password

Set or change the password of the person signed in

Body

NameTypeNotes
current_passwordstring
new_passwordstringrequired, max length 128

Responses

  • 200 OK: object
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 403 Error envelope: Error

GET/v0/auth/callback

Finish a sign in, with a magic link token or an OAuth code (public)

Parameters

NameTypeNotes
tokenstringin query, Magic link token
codestringin query, OAuth authorization code
statestringin query, OAuth state, single use, 10 minutes

Responses

  • 200 Session, or the second factor step (MFAStep) when a factor is still to be proved: Session
  • 303 A browser goes to the login page with the session in the fragment, or with ?error=<code>
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 403 Error envelope: Error
  • 502 Error envelope: Error

GET/v0/auth/oauth/{provider}/start

Start Google, Microsoft or GitHub sign in with PKCE (public)

Parameters

NameTypeNotes
providergoogle | microsoft | githubin path, required
redirect1in query, Send the browser to the provider instead of returning JSON
redirect_afterstringin query, Path on the site to return to

Responses

  • 200 OK: OAuthStart
  • 302 The browser goes to the provider
  • 400 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/auth/refresh

Rotate a refresh token into a new session (public)

Body

NameTypeNotes
refresh_tokenstringrequired

Responses

  • 200 Session: Session
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/auth/logout

End a session (public)

Body

NameTypeNotes
refresh_tokenstring

Responses

  • 204 Ended (also when the token was already invalid)
  • 400 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/inboxes

List inboxes, newest first

Parameters

NameTypeNotes
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query

Responses

  • 200 OK: InboxList

POST/v0/inboxes

Create an inbox (repeat client_id to get the same inbox)

Body (CreateInbox)

NameTypeNotes
usernamestringpattern ^[a-z0-9]([a-z0-9._-]{0,62}[a-z0-9])?$
domainstring
display_namestringmax length 200
client_idstringpattern ^[A-Za-z0-9._~-]{1,256}$

Responses

  • 200 Existing inbox for this client_id: Inbox
  • 201 Created: Inbox
  • 403 Error envelope: Error
  • 409 Error envelope: Error

GET/v0/inboxes/{inbox}

Get an inbox

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 200 OK: Inbox
  • 404 Error envelope: Error

PATCH/v0/inboxes/{inbox}

Update the display name, the signature, or the support intake of an inbox

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body

NameTypeNotes
display_namestringmax length 200
ticket_intakebooleanNew threads on this inbox become tickets in the support queue.
signature_htmlstringHTML signature of this address. Empty string removes it., max length 20000

Responses

  • 200 OK: Inbox

DELETE/v0/inboxes/{inbox}

Delete an inbox and all its mail

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 204 Deleted
  • 404 Error envelope: Error

GET/v0/inboxes/{inbox}/threads

List threads of an inbox

Parameters

NameTypeNotes
inboxstring (email)in path, required
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query
labelstringin query
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: ThreadList

GET/v0/threads

List threads across the organization

Parameters

NameTypeNotes
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query
labelstringin query
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: ThreadList

GET/v0/threads/{thread}

Get a thread with the messages the caller may see, oldest first

Parameters

NameTypeNotes
threadstring (uuid)in path, required
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: Thread

GET/v0/inboxes/{inbox}/messages

List message metadata (no bodies)

Parameters

NameTypeNotes
inboxstring (email)in path, required
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query
labelstringin query
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: MessageList

POST/v0/inboxes/{inbox}/messages/send

Send a new message (new thread)

Parameters

NameTypeNotes
inboxstring (email)in path, required
Idempotency-Keystringin header, max length 256

Body (Send)

NameTypeNotes
tostring (email)[]required, at least 1 item
ccstring (email)[]
bccstring (email)[]
subjectstring
textstring
htmlstring
labelsstring[]
attachmentsAttachment[]

Responses

  • 200 Accepted by the transport, or queued when the install has no transport: SendResult
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 422 Error envelope: Error
  • 429 Error envelope: Error
  • 502 email_delivery_failed: the transport did not accept the message, with delivery_error_code and delivery_error: Error
  • 503 Error envelope: Error

GET/v0/inboxes/{inbox}/messages/{message}

Get a message with bodies, extracted_text, authentication results and gatekeeper verdict

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: Message
  • 403 Error envelope: Error
  • 404 Error envelope: Error

PATCH/v0/inboxes/{inbox}/messages/{message}

Add or remove custom labels

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)

Body

NameTypeNotes
add_labelsstring[]
remove_labelsstring[]

Responses

  • 200 OK: Message

GET/v0/inboxes/{inbox}/messages/{message}/raw

Raw RFC 822 message

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 OK: message/rfc822

POST/v0/inboxes/{inbox}/messages/{message}/reply

Reply in the same thread

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)
Idempotency-Keystringin header, max length 256

Body (Reply)

NameTypeNotes
textstring
htmlstring
reply_allboolean
labelsstring[]
attachmentsAttachment[]

Responses

  • 200 Accepted by the transport, or queued when the install has no transport: SendResult
  • 403 Error envelope: Error
  • 422 Error envelope: Error
  • 429 Error envelope: Error
  • 502 email_delivery_failed: the transport did not accept the reply, with delivery_error_code and delivery_error: Error
  • 503 Error envelope: Error

POST/v0/inboxes/{inbox}/messages/{message}/release

Release a message held for review (needs message_release, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)

Responses

  • 200 Released: Message
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

GET/v0/inboxes/{inbox}/messages/{message}/attachments/{attachment}

Download an attachment

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)
attachmentstring (uuid)in path, required
include_reviewbooleanin query, Also return messages held for security review; needs message_review, default false

Responses

  • 200 Attachment bytes with its content type

GET/v0/inboxes/{inbox}/drafts

List drafts, newest first (needs message_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query

Responses

  • 200 OK: DraftList

POST/v0/inboxes/{inbox}/drafts

Create a draft (needs message_send)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body (CreateDraft)

NameTypeNotes
tostring (email)[]
ccstring (email)[]
bccstring (email)[]
subjectstring
textstring
htmlstring
labelsstring[]
attachmentsAttachment[]
in_reply_tostringMessage UUID or RFC Message-ID to reply to
reply_allbooleanWith in_reply_to: copy the other recipients
send_atstring (date-time)Send automatically at this time (future, within 365 days)

Responses

  • 201 Created: Draft
  • 400 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/inboxes/{inbox}/drafts/{draft}

Get a draft (needs message_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required
draftstring (uuid)in path, required

Responses

  • 200 OK: Draft
  • 404 Error envelope: Error

PATCH/v0/inboxes/{inbox}/drafts/{draft}

Update a draft (needs message_send)

Parameters

NameTypeNotes
inboxstring (email)in path, required
draftstring (uuid)in path, required

Body (UpdateDraft)

NameTypeNotes
tostring (email)[]
ccstring (email)[]
bccstring (email)[]
subjectstring
textstring
htmlstring
labelsstring[]
attachmentsAttachment[]
send_atstring,null (date-time)null cancels a scheduled send

Responses

  • 200 OK: Draft
  • 400 Error envelope: Error
  • 404 Error envelope: Error

DELETE/v0/inboxes/{inbox}/drafts/{draft}

Delete a draft (needs message_send)

Parameters

NameTypeNotes
inboxstring (email)in path, required
draftstring (uuid)in path, required

Responses

  • 204 Deleted

POST/v0/inboxes/{inbox}/drafts/{draft}/send

Send a draft now and delete it (needs message_send)

Parameters

NameTypeNotes
inboxstring (email)in path, required
draftstring (uuid)in path, required
Idempotency-Keystringin header, max length 256

Responses

  • 200 Accepted by the transport, or queued when the install has no transport: SendResult
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error
  • 429 Error envelope: Error
  • 502 email_delivery_failed: the transport did not accept the message, with delivery_error_code and delivery_error: Error

GET/v0/events/stream

Live events as Server Sent Events (needs message_read)

Parameters

NameTypeNotes
typesstringin query, Comma separated event types; all when absent
inboxstring (email)in query, Only events of this inbox
Last-Event-IDintegerin header, Resume after this event id, min 0
last_event_idintegerin query, Same as Last-Event-ID, for clients that cannot set headers, min 0

Responses

  • 200 Event stream: string
  • 400 Error envelope: Error
  • 404 Error envelope: Error
  • 429 Error envelope: Error

GET/v0/domains

List own and shared domains

Responses

  • 200 OK

POST/v0/domains

Add a custom domain; returns the DNS records to publish

Body

NameTypeNotes
domainstringrequired

Responses

  • 201 Created: Domain
  • 403 Error envelope: Error
  • 409 Error envelope: Error

GET/v0/domains/{domain}

Get a domain with record status

Parameters

NameTypeNotes
domainstringin path, required

Responses

  • 200 OK: Domain

PATCH/v0/domains/{domain}

Move a domain into a group (or out of one), and nominate its catch-all inbox

Parameters

NameTypeNotes
domainstringin path, required

Body

NameTypeNotes
groupstring (uuid)The group id, or null to leave the group
catch_all_inboxstring (email)The inbox that receives unknown local parts of this domain, or null to turn the catch-all off

Responses

  • 200 OK: Domain
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 422 Error envelope: Error

DELETE/v0/domains/{domain}

Delete a domain without inboxes

Parameters

NameTypeNotes
domainstringin path, required

Responses

  • 204 Deleted
  • 409 Error envelope: Error

POST/v0/domains/{domain}/verify

Check DNS now (the scheduler also checks every 5 minutes for 7 days)

Parameters

NameTypeNotes
domainstringin path, required

Responses

  • 200 OK: Domain

GET/v0/api-keys

List active keys (requires api_key_read)

Responses

  • 200 OK

POST/v0/api-keys

Create a key with at most the caller's permissions (key shown once)

Body

NameTypeNotes
namestringmax length 100
permissionsPermission[]omit to copy the caller's permissions
expires_atstring (date-time)
scopeKeyScopeInput

Responses

  • 201 Created: ApiKey
  • 403 Error envelope: Error

DELETE/v0/api-keys/{key}

Revoke a key immediately (requires api_key_write, no escalation)

Parameters

NameTypeNotes
keystring (uuid)in path, required

Responses

  • 204 Revoked

GET/v0/audit-logs

Security relevant actions of the organization (requires audit_read)

Parameters

NameTypeNotes
limitintegerin query, min 1, max 200, default 50
actor_typeuser | agent | operator | systemin query
actor_key_idstring (uuid)in query

Responses

  • 200 OK: object
  • 400 Error envelope: Error
  • 403 Error envelope: Error

GET/v0/webhooks

List webhooks

Responses

  • 200 OK

POST/v0/webhooks

Create a webhook (secret is returned once)

Body

NameTypeNotes
urlstring (uri)required
event_typesEventType[]required, at least 1 item
inbox_idsstring (email)[]Inboxes the caller can see (404 otherwise). A webhook keeps the scope of the caller who created it: events of inboxes outside that scope are never delivered, whatever inbox_ids says, and a scoped webhook receives events without an inbox only when its creator is an owner or admin., at most 10 items

Responses

  • 201 Created: Webhook
  • 404 Error envelope: Error

DELETE/v0/webhooks/{webhook}

Delete a webhook

Parameters

NameTypeNotes
webhookstring (uuid)in path, required

Responses

  • 204 Deleted

GET/v0/billing

Plan and Stripe subscription state (requires billing_read)

Responses

  • 200 OK: Billing
  • 403 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/billing/checkout

Start a Stripe Checkout for a paid plan (requires billing_write, audited)

Body (Checkout)

NameTypeNotes
planbuilder | growth | teamrequired
intervalmonthly | yearlydefault monthly
success_urlstring (uri)Defaults to the deployment's MAI_BILLING_RETURN_URL
cancel_urlstring (uri)Defaults to the deployment's MAI_BILLING_RETURN_URL

Responses

  • 200 OK: BillingSession
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 501 Error envelope: Error
  • 502 Error envelope: Error

POST/v0/billing/portal

Open the Stripe customer portal (requires billing_write, audited)

Body

NameTypeNotes
return_urlstring (uri)

Responses

  • 200 OK: BillingSession
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 501 Error envelope: Error
  • 502 Error envelope: Error

GET/v0/export

Export the organization's own data (requires data_export, audited)

Responses

  • 200 OK: OrgExport
  • 403 Error envelope: Error

POST/v0/organizations

Create the organization of a signed in person (self service sign up)

Body

NameTypeNotes
namestringrequired, The organization name, trimmed, max length 80

Responses

  • 201 Created: NewOrganization
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 429 Error envelope: Error

GET/v0/organization

The organization and the state of its outbound mail

Responses

  • 200 OK: Organization
  • 401 Error envelope: Error
  • 403 Error envelope: Error

PATCH/v0/organization

Change the second factor policy or the retention windows (session or key holding member_write)

Body

NameTypeNotes
require_mfaboolean
retentionRetentionPolicy

Responses

  • 200 OK: object
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 422 Error envelope: Error

DELETE/v0/organization

Delete the organization and all its data (requires data_delete, audited)

Body

NameTypeNotes
confirmstringrequired, The organization name, verbatim

Responses

  • 200 Deleted; body carries the export taken before deletion: object
  • 400 Error envelope: Error
  • 403 Error envelope: Error

GET/v0/tickets

List tickets, newest activity first

Parameters

NameTypeNotes
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query
stateTicketStatein query
priorityTicketPriorityin query
assigneestringin query, user id, API key id, or none
inboxstringin query, inbox address
qstringin query, case insensitive over subject and requester

Responses

  • 200 OK: TicketList

POST/v0/tickets

Open a ticket on an existing thread (requires ticket_write, audited)

Body (CreateTicket)

NameTypeNotes
thread_idstringrequired, The conversation to open the ticket on. A thread whose previous ticket is resolved or closed accepts a new ticket, with a new number.
priorityTicketPriority
tagsstring[]
assignee_userstring
assignee_keystring

Responses

  • 201 Created: Ticket
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

GET/v0/tickets/stats

Queue counters and median first reply

Responses

  • 200 OK: TicketStats

GET/v0/tickets/{ticket}

Read one ticket with its timeline and internal notes

Parameters

NameTypeNotes
ticketstringin path, required

Responses

  • 200 OK: TicketDetail
  • 404 Error envelope: Error

PATCH/v0/tickets/{ticket}

Change state, priority, tags or assignment (requires ticket_write, audited)

Parameters

NameTypeNotes
ticketstringin path, required

Body (UpdateTicket)

NameTypeNotes
stateTicketState
priorityTicketPriority
tagsstring[]
assignee_userstring
assignee_keystring

Responses

  • 200 OK: Ticket
  • 400 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

POST/v0/tickets/{ticket}/notes

Add an internal note (requires ticket_write, audited)

Parameters

NameTypeNotes
ticketstringin path, required

Body

NameTypeNotes
bodystringrequired

Responses

  • 201 Created: TicketNote
  • 400 Error envelope: Error
  • 404 Error envelope: Error

POST/v0/tickets/{ticket}/reply

Reply to the customer on the ticket thread (requires message_send, audited)

Parameters

NameTypeNotes
ticketstringin path, required

Body (Reply)

NameTypeNotes
textstring
htmlstring
reply_allboolean
labelsstring[]
attachmentsAttachment[]

Responses

  • 200 Sent: SendResult
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

GET/v0/ticket-views

List the saved views of the queue (requires ticket_read)

Responses

  • 200 OK: TicketViewList
  • 403 Error envelope: Error

POST/v0/ticket-views

Save the current queue filter under a name (requires ticket_write, audited)

Body (CreateTicketView)

NameTypeNotes
namestringrequired, Up to 60 characters, unique among the views the caller can see
sharedbooleanSave it for the whole organization; an owner or an admin only
filtersTicketViewFiltersrequired

Responses

  • 201 Created: TicketView
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error

DELETE/v0/ticket-views/{view}

Delete a saved view (requires ticket_write, audited)

Parameters

NameTypeNotes
viewstringin path, required

Responses

  • 204 Deleted
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/ticket-sla

Read the SLA policy of the organization (requires ticket_read)

Responses

  • 200 OK: TicketSLA
  • 403 Error envelope: Error

PATCH/v0/ticket-sla

Change the SLA policy (owner or admin, audited)

Body (UpdateTicketSLA)

NameTypeNotes
windowsTicketSLAWindow[]
targetsTicketSLATargets
auto_close_daysintegermin 0, max 365

Responses

  • 200 OK: TicketSLA
  • 400 Error envelope: Error
  • 403 Error envelope: Error

GET/v0/push/subscriptions

List the devices the caller registered (requires notification_write)

Responses

  • 200 OK: PushSubscriptionList
  • 403 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/push/subscriptions

Register a browser for web push (requires notification_write, audited)

Body (PushSubscribe)

NameTypeNotes
endpointstring (uri)required, The device at its push service. A capability: never logged, never returned
keysobjectrequired
expiration_timeintegerMilliseconds since the epoch, or null
user_agentstringThe browser that subscribed, for the device label, max length 512

Responses

  • 201 Created (or updated): PushSubscription
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 422 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error

DELETE/v0/push/subscriptions

Drop a device by endpoint (requires notification_write, audited)

Body (PushUnsubscribe)

NameTypeNotes
endpointstring (uri)required, The endpoint the browser is dropping

Responses

  • 204 No content, the device is off
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 501 Error envelope: Error

DELETE/v0/push/subscriptions/{subscription}

Drop a device by id (requires notification_write, audited)

Parameters

NameTypeNotes
subscriptionstring (uuid)in path, required

Responses

  • 204 No content, the device is off
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/members

List the team (requires member_read)

Responses

  • 200 OK: MemberList
  • 403 Error envelope: Error

POST/v0/members

Invite somebody by email (requires member_write, audited)

Body

NameTypeNotes
emailstring (email)required
roleadmin | memberdefault member

Responses

  • 201 Created; the invitation with its one time token: CreatedInvitation
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error
  • 429 Error envelope: Error

PATCH/v0/members/{user}

Change a role (requires member_write, audited)

Parameters

NameTypeNotes
userstring (uuid)in path, required

Body

NameTypeNotes
roleadmin | memberrequired

Responses

  • 200 OK: Member
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

DELETE/v0/members/{user}

Remove somebody (requires member_write, audited)

Parameters

NameTypeNotes
userstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/members/invitations

List pending invitations (requires member_read)

Responses

  • 200 OK: InvitationList
  • 403 Error envelope: Error

POST/v0/members/invitations

Invite somebody by email (alias of POST /v0/members)

Body

NameTypeNotes
emailstring (email)required
roleadmin | memberdefault member

Responses

  • 201 Created: CreatedInvitation
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 429 Error envelope: Error

DELETE/v0/members/invitations/{invitation}

Cancel an invitation (requires member_write, audited)

Parameters

NameTypeNotes
invitationstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/invitations/{token}

Preview an invitation (public)

Parameters

NameTypeNotes
tokenstringin path, required

Responses

  • 200 OK: InvitationPreview
  • 404 Error envelope: Error
  • 410 Error envelope: Error

POST/v0/invitations/{token}/accept

Accept an invitation (public)

Parameters

NameTypeNotes
tokenstringin path, required

Responses

  • 200 Accepted; the session and the role: object
  • 404 Error envelope: Error
  • 409 Error envelope: Error
  • 410 Error envelope: Error

GET/v0/groups

List groups (requires group_read)

Responses

  • 200 OK: GroupList
  • 403 Error envelope: Error

POST/v0/groups

Create a group (requires group_write, audited)

Body

NameTypeNotes
namestringrequired, max length 60
colorstringOne of the eight palette tokens; a free form colour is refused

Responses

  • 201 Created: Group
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error

PATCH/v0/groups/{group}

Rename or recolour a group (requires group_write, audited)

Parameters

NameTypeNotes
groupstring (uuid)in path, required

Body

NameTypeNotes
namestringmax length 60
colorstring

Responses

  • 200 OK: Group
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error

DELETE/v0/groups/{group}

Delete a group (requires group_write, audited)

Parameters

NameTypeNotes
groupstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/inboxes/{inbox}/grants

Who can see this inbox (requires member_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 200 OK: GrantList
  • 403 Error envelope: Error
  • 404 Error envelope: Error

PUT/v0/inboxes/{inbox}/grants

Grant somebody access to this inbox (requires member_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body

NameTypeNotes
user_idstring (uuid)required
rightsviewer | responderrequired

Responses

  • 200 OK: Grant
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error

DELETE/v0/inboxes/{inbox}/grants/{user}

Revoke access to this inbox (requires member_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required
userstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/domains/{domain}/grants

Who can see this domain (requires member_read)

Parameters

NameTypeNotes
domainstringin path, required

Responses

  • 200 OK: GrantList
  • 403 Error envelope: Error
  • 404 Error envelope: Error

PUT/v0/domains/{domain}/grants

Grant somebody access to this domain (requires member_write, audited)

Parameters

NameTypeNotes
domainstringin path, required

Body

NameTypeNotes
user_idstring (uuid)required
rightsviewer | responderrequired

Responses

  • 200 OK: Grant
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error

DELETE/v0/domains/{domain}/grants/{user}

Revoke access to this domain (requires member_write, audited)

Parameters

NameTypeNotes
domainstringin path, required
userstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error

POST/stripe/webhook

Stripe webhook endpoint (public, Stripe-Signature verified)

Parameters

NameTypeNotes
Stripe-Signaturestringin header, required

Responses

  • 200 Received; outcome is applied, duplicate, stale or ignored
  • 400 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/webhooks/{webhook}/events

Events delivered to this webhook, newest first, each with its last attempt (requires webhook_read)

Parameters

NameTypeNotes
webhookstring (uuid)in path, required
statuspending | succeeded | failedin query, Filter on the delivery state
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query

Responses

  • 200 OK: WebhookEventList
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/webhooks/{webhook}/events/{event}/attempts

Every attempt of one event, oldest first (requires webhook_read)

Parameters

NameTypeNotes
webhookstring (uuid)in path, required
eventstring (uuid)in path, required

Responses

  • 200 OK: WebhookAttemptList
  • 403 Error envelope: Error
  • 404 Error envelope: Error

POST/v0/webhooks/{webhook}/events/{event}/replay

Queue the event again for this webhook, also when it succeeded (requires webhook_write, audited)

Parameters

NameTypeNotes
webhookstring (uuid)in path, required
eventstring (uuid)in path, required

Responses

  • 202 Queued: WebhookReplay
  • 403 Error envelope: Error
  • 404 Error envelope: Error

POST/v0/webhooks/{webhook}/rotate-secret

Issue a new signing secret; the previous one verifies for 24 more hours (requires webhook_write, audited)

Parameters

NameTypeNotes
webhookstring (uuid)in path, required

Responses

  • 200 OK: RotateSecret
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/auth/mfa

This person's second factor and the policy that applies to it

Responses

  • 200 OK: MFAStatus
  • 403 Error envelope: Error

POST/v0/auth/mfa/enroll

Start a second factor for the caller (secret, otpauth URL, ten recovery codes)

Body

NameTypeNotes
challenge_tokenstring

Responses

  • 201 Created: MFAEnrollment
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error

POST/v0/auth/mfa/verify

Confirm a pending second factor with a code from the authenticator

Body

NameTypeNotes
codestringrequired, max length 6
challenge_tokenstring

Responses

  • 200 OK: MFAVerify
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error

POST/v0/auth/mfa/disable

Remove the caller's second factor (needs a code)

Body

NameTypeNotes
codestring
recovery_codestring

Responses

  • 204 No content
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 403 Error envelope: Error
  • 409 Error envelope: Error

POST/v0/auth/mfa/challenge

Second step of a sign in, with a code or a recovery code (public)

Body

NameTypeNotes
challenge_tokenstringrequired
codestring
recovery_codestring

Responses

  • 200 Session: Session
  • 303 A browser goes to the login page with the session in the fragment
  • 400 Error envelope: Error
  • 401 Error envelope: Error
  • 409 Error envelope: Error
  • 429 Error envelope: Error

POST/v0/inboxes/{inbox}/messages/{message}/forward

Forward a message with its original attachments and an optional comment

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)
Idempotency-Keystringin header, max length 256

Body (Forward)

NameTypeNotes
tostring (email)[]required, at least 1 item
ccstring (email)[]
bccstring (email)[]
commentstringOptional text above the quoted message, below the signature
labelsstring[]

Responses

  • 200 Accepted by the transport, held by the undo window, or queued when the install has no transport: SendResult
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 429 Error envelope: Error
  • 502 email_delivery_failed: the transport refused the forward, with delivery_error_code and delivery_error: Error

POST/v0/inboxes/{inbox}/messages/{message}/cancel

Cancel a held send inside its undo window (needs message_send)

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)

Responses

  • 200 Cancelled: Message
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error

POST/v0/messages/batch

Apply one action to up to 1.000 messages, with one outcome per id (requires message_update, or data_delete for a delete)

Body

NameTypeNotes
idsstring[]required, Message UUIDs or RFC Message-IDs, at most 1.000; a repeated id is answered once per occurrence and applied once, at least 1 item, at most 1000 items
actionadd_labels | remove_labels | archive | mark_read | mark_unread | deleterequired
labelsstring[]Required by add_labels and remove_labels, refused by the other four

Responses

  • 200 One outcome per id, whatever they were: BatchResult
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 422 Error envelope: Error

GET/v0/rules

List the rules of the organization (requires rule_read)

Parameters

NameTypeNotes
targetinbox | domain | orgin query, Only rules of this kind
target_idstring (uuid)in query, Only rules of this inbox or domain
enabledbooleanin query

Responses

  • 200 OK: object
  • 403 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/rules

Create a rule (requires rule_write, audited)

Body (RuleInput)

NameTypeNotes
namestringrequired, max length 100
targetRuleTarget
priorityintegermin 0, max 100000, default 100
enabledbooleandefault true
include_spambooleandefault false
conditionsRuleConditionsrequired
actionsRuleAction[]required, at least 1 item, at most 20 items

Responses

  • 201 Created: Rule
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 422 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/rules/{rule}

Read one rule (requires rule_read)

Parameters

NameTypeNotes
rulestring (uuid)in path, required

Responses

  • 200 OK: Rule
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

PATCH/v0/rules/{rule}

Change a rule, or switch it off (requires rule_write, audited)

Parameters

NameTypeNotes
rulestring (uuid)in path, required

Body (RulePatch)

NameTypeNotes
namestringmax length 100
targetRuleTarget
priorityintegermin 0, max 100000
enabledboolean
include_spamboolean
conditionsRuleConditions
actionsRuleAction[]at least 1 item, at most 20 items

Responses

  • 200 OK: Rule
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 422 Error envelope: Error
  • 501 Error envelope: Error

DELETE/v0/rules/{rule}

Delete a rule and any apply job queued for it (requires rule_write, audited)

Parameters

NameTypeNotes
rulestring (uuid)in path, required

Responses

  • 204 Deleted
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/inboxes/{inbox}/agent

The inbox agent of one inbox, its actions and its state (requires inbox_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 200 OK: AgentConfig
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

PATCH/v0/inboxes/{inbox}/agent

Configure the inbox agent, replacing the action set and patching the rest (requires inbox_write)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body (AgentConfigRequest)

NameTypeNotes
instructionsstring1 to 4000 characters, or null to clear, max length 4000
allowed_actionsdraft_reply | draft_forward | add_labels | assign_thread | mark_spam | archive_thread | move_to_trash[]The whole set; an empty array turns the agent off, one of draft_reply, draft_forward, add_labels, assign_thread, mark_spam, archive_thread, move_to_trash
toneconcise_professional | concise_casual | expanded_professional | expanded_casual
enabledboolean

Responses

  • 200 OK: AgentConfig
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 422 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/rules/{rule}/apply

Apply a rule to the messages that already exist (requires rule_write, audited)

Parameters

NameTypeNotes
rulestring (uuid)in path, required

Responses

  • 202 Queued: RuleApplyReport
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 409 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/rules/applies/{apply}

The state of one apply job (requires rule_read)

Parameters

NameTypeNotes
applystring (uuid)in path, required

Responses

  • 200 OK: RuleApplyReport
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/inboxes/{inbox}/auto-reply

The automatic answer of one inbox and whether it is inside its window (requires rule_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 200 OK: AutoReply
  • 403 Error envelope: Error
  • 404 Error envelope: Error

PUT/v0/inboxes/{inbox}/auto-reply

Set the automatic answer of one inbox (requires rule_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body (AutoReplyInput)

NameTypeNotes
modefixed | daily | weekly | monthly | permanentrequired
timezonestringrequired, IANA zone, for example Europe/Rome; required, never derived from the server
startstringRFC 3339 for fixed, HH:MM for daily, weekly and monthly; absent for permanent
endstringRFC 3339 for fixed, HH:MM for daily, weekly and monthly; absent for permanent
daysstring[]Weekday tokens for weekly, day-of-month numbers for monthly, absent otherwise, at most 31 items
subjectstringrequired, max length 256
body_textstringrequired, max length 4000
body_htmlstring
restrict_to_domainbooleandefault false

Responses

  • 200 OK: AutoReply
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error

DELETE/v0/inboxes/{inbox}/auto-reply

Remove the automatic answer of one inbox and the rule that carried it (requires rule_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 204 Removed
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/inboxes/{inbox}/blocklist

The block and allow list of one inbox (requires inbox_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Responses

  • 200 OK: object
  • 403 Error envelope: Error
  • 404 Error envelope: Error

POST/v0/inboxes/{inbox}/blocklist

Add an entry to the block or allow list of one inbox (requires inbox_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required

Body (BlocklistInput)

NameTypeNotes
list_kindblock | allowdefault block
kindsender | domainrequired
valuestringrequired, An address for kind sender, a domain for kind domain; never one as the other, max length 320

Responses

  • 201 Created: BlocklistEntry
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 429 Error envelope: Error

DELETE/v0/inboxes/{inbox}/blocklist

Remove an entry of the list of one inbox, named in the query string (requires inbox_write, audited)

Parameters

NameTypeNotes
inboxstring (email)in path, required
kindsender | domainin query, required
valuestringin query, required
list_kindblock | allowin query, default block

Responses

  • 204 Removed
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/organization/blocklist

The organization wide block and allow list (requires org_blocklist_write)

Responses

  • 200 OK: object
  • 403 Error envelope: Error

POST/v0/organization/blocklist

Add an entry to the organization wide list (requires org_blocklist_write, audited)

Body (BlocklistInput)

NameTypeNotes
list_kindblock | allowdefault block
kindsender | domainrequired
valuestringrequired, An address for kind sender, a domain for kind domain; never one as the other, max length 320

Responses

  • 201 Created: BlocklistEntry
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 429 Error envelope: Error

DELETE/v0/organization/blocklist

Remove an entry of the organization wide list (requires org_blocklist_write, audited)

Parameters

NameTypeNotes
kindsender | domainin query, required
valuestringin query, required
list_kindblock | allowin query, default block

Responses

  • 204 Removed
  • 400 Error envelope: Error

GET/v0/inboxes/{inbox}/messages/{message}/timeline

The delivery states of one message, oldest first, with the source of each (requires message_read)

Parameters

NameTypeNotes
inboxstring (email)in path, required
messagestringin path, required, Message UUID or RFC Message-ID (URL encoded)

Responses

  • 200 OK: MessageTimeline
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/domains/{domain}/reputation

Bounce and complaint reputation of a domain, measured like the sending breaker (requires domain_read)

Parameters

NameTypeNotes
domainstringin path, required

Responses

  • 200 OK: DomainReputation
  • 403 Error envelope: Error
  • 404 Error envelope: Error

GET/v0/oauth/authorize

Authorize a third party app for the signed in person (session; creates the grant, audited)

Parameters

NameTypeNotes
client_idstringin query, required
redirect_uristring (uri)in query, required
response_typecodein query, required
scopestringin query
statestringin query, max length 512
code_challengestringin query, required
code_challenge_methodS256in query, required
resourcestringin query

Responses

  • 200 OK: OAuthAuthorizeResult
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/oauth/token

Exchange an authorization code, or a refresh token, for an access token (public)

Body

NameTypeNotes
grant_typeauthorization_code | refresh_tokenrequired
codestring
redirect_uristring (uri)
client_idstring
code_verifierstring
refresh_tokenstring

Responses

  • 200 OK: OAuthToken
  • 400 invalid_request, invalid_grant, invalid_client, unsupported_grant_type (RFC 6749 body): object
  • 501 oauth_disabled: object

POST/v0/oauth/register

Register a client dynamically (public; public clients only, PKCE, rate limited per address)

Body (OAuthClientInput)

NameTypeNotes
client_namestringrequired, max length 100
client_uristring (uri)Where a person can read about the app
redirect_urisstring (uri)[]required, https, or http on a loopback host; no fragment, at least 1 item, at most 10 items
scopemessages:send | full_accessThe most this client may ever ask for, default messages:send

Responses

  • 201 Created: OAuthClient
  • 400 Error envelope: Error
  • 429 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/oauth/grants

The apps this person connected (session; a key is refused with session_required)

Responses

  • 200 OK: OAuthGrantList
  • 403 Error envelope: Error
  • 501 Error envelope: Error

POST/v0/oauth/grants/{grant}/revoke

Revoke one grant, immediately on every token it issued (session; audited)

Parameters

NameTypeNotes
grantstring (uuid)in path, required

Responses

  • 204 No content
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/logs

Redacted API request log of the organization, newest first (requires audit_read)

Parameters

NameTypeNotes
limitintegerin query, min 1, max 200, default 50
key_idstring (uuid)in query
methodstringin query
statusintegerin query, min 100, max 599
sdkgo | node | python | php | ruby | javain query
afterstring (date-time)in query
beforestring (date-time)in query

Responses

  • 200 OK: object
  • 400 Error envelope: Error
  • 403 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/logs/{log}

One API request with its redacted request and response body (requires audit_read)

Parameters

NameTypeNotes
logstring (uuid)in path, required

Responses

  • 200 OK: RequestLog
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/logs/{log}/export

The same request as a markdown block a person can paste into an assistant (requires audit_read)

Parameters

NameTypeNotes
logstring (uuid)in path, required

Responses

  • 200 OK: string
  • 403 Error envelope: Error
  • 404 Error envelope: Error
  • 501 Error envelope: Error

GET/v0/suppressions

The suppression list of the organization (requires suppression_write)

Parameters

NameTypeNotes
originbounce | complaint | manualin query
limitintegerin query, min 1, max 100, default 20
page_tokenstringin query

Responses

    GET/v0/roles

    List custom roles (requires member_read)

    Responses

    • 200 OK: CustomRoleList
    • 403 Error envelope: Error

    POST/v0/roles

    Create a custom role (requires member_write, audited)

    Body (CustomRoleRequest)

    NameTypeNotes
    namestringmax length 60
    descriptionstringmax length 200
    permissionsPermission[]Required on create. An unknown name is 422 unknown_permission; a name the caller does not hold is 403 permission_escalation.

    Responses

    • 201 Created: CustomRole
    • 400 Error envelope: Error
    • 403 Error envelope: Error
    • 409 Error envelope: Error
    • 422 Error envelope: Error

    GET/v0/suppressions/export

    The whole list as CSV (requires suppression_write, audited)

    Responses

    • 200 OK: string
    • 403 Error envelope: Error

    POST/v0/suppressions/import

    Import a CSV of addresses (requires suppression_write, audited)

    Responses

    • 201 Created: SuppressionResult
    • 400 Error envelope: Error
    • 403 Error envelope: Error
    • 413 Error envelope: Error

    GET/v0/unsubscribe/{token}

    The unsubscribe page of a one-click link (public)

    Parameters

    NameTypeNotes
    tokenstringin path, required

    Responses

    • 200 OK: string
    • 404 The link is not valid: string
    • 501 unsubscribe_disabled: this deployment has no signing secret or no public base URL

    POST/v0/unsubscribe/{token}

    One-click unsubscribe (public, RFC 8058)

    Parameters

    NameTypeNotes
    tokenstringin path, required

    Responses

    • 200 OK: string
    • 404 The link is not valid: string
    • 501 unsubscribe_disabled: this deployment has no signing secret or no public base URL

    PATCH/v0/roles/{role}

    Change a role's name, description or permission set (requires member_write, audited)

    Parameters

    NameTypeNotes
    rolestring (uuid)in path, required

    Body (CustomRoleRequest)

    NameTypeNotes
    namestringmax length 60
    descriptionstringmax length 200
    permissionsPermission[]Required on create. An unknown name is 422 unknown_permission; a name the caller does not hold is 403 permission_escalation.

    Responses

    • 200 OK: CustomRole
    • 400 Error envelope: Error
    • 403 Error envelope: Error
    • 404 Error envelope: Error
    • 409 Error envelope: Error
    • 422 Error envelope: Error

    DELETE/v0/roles/{role}

    Delete a custom role (requires member_write, audited)

    Parameters

    NameTypeNotes
    rolestring (uuid)in path, required

    Responses

    • 204 Deleted, assignments revoked
    • 403 Error envelope: Error
    • 404 Error envelope: Error

    PUT/v0/members/{user}/roles

    Replace the custom roles of a person (requires member_write, audited)

    Parameters

    NameTypeNotes
    userstring (uuid)in path, required

    Body (RoleAssignmentRequest)

    NameTypeNotes
    role_idsstring (uuid)[]required, The whole set the subject should hold. An empty array revokes every custom role from the subject; that is a revocation, not a mistake., at most 20 items

    Responses

    • 200 OK: RoleAssignmentChange
    • 400 Error envelope: Error
    • 403 Error envelope: Error
    • 404 Error envelope: Error

    PUT/v0/groups/{group}/roles

    Replace the custom roles of a group (requires member_write, audited)

    Parameters

    NameTypeNotes
    groupstring (uuid)in path, required

    Body (RoleAssignmentRequest)

    NameTypeNotes
    role_idsstring (uuid)[]required, The whole set the subject should hold. An empty array revokes every custom role from the subject; that is a revocation, not a mistake., at most 20 items

    Responses

    • 200 OK: RoleAssignmentChange
    • 400 Error envelope: Error
    • 403 Error envelope: Error
    • 404 Error envelope: Error

    GET/v0/export/{export}

    The state of one export job (requires data_export)

    Parameters

    NameTypeNotes
    exportstring (uuid)in path, required

    Responses

    • 200 OK: ExportJob
    • 403 Error envelope: Error
    • 404 Error envelope: Error

    GET/v0/export/{export}/download

    The document of a finished export job (requires data_export)

    Parameters

    NameTypeNotes
    exportstring (uuid)in path, required

    Responses

    • 200 OK: OrgExport
    • 403 Error envelope: Error
    • 404 Error envelope: Error
    • 409 Error envelope: Error

    GET/v0/organization/features

    The feature switches of the caller's organization (read only)

    Responses

    • 200 OK: object
    • 401 Error envelope: Error

    Objects

    User object

    NameTypeNotes
    user_idstring (uuid)
    emailstring (email)
    namestring
    providermagic_link | google | microsoft | githubIdentity that first proved this address
    roleowner | admin | member
    created_atstring (date-time)
    last_login_atstring (date-time)

    Session object

    NameTypeNotes
    access_tokenstringSigned JWT, send as Authorization: Bearer, 15 minutes
    refresh_tokenstringSingle use, 30 days, rotate it at POST /v0/auth/refresh
    token_typeBearer
    expires_inintegerSeconds until the access token expires
    expires_atstring (date-time)
    refresh_expires_atstring (date-time)
    roleowner | admin | member
    userUser
    organizationOrg

    OAuthStart object

    NameTypeNotes
    providergoogle | github
    authorize_urlstringProvider URL, with state and the S256 PKCE challenge
    statestringSingle use, 10 minutes
    expires_atstring (date-time)

    Me object

    NameTypeNotes
    authapi_key | session
    organization_idstring (uuid)Empty when a session has no organization yet
    namestring
    planfree | builder | growth | team
    screen_before_notifyboolean
    roleowner | admin | memberOnly for a session; null while it has no organization
    needs_organizationbooleanTrue for a session that signed in and has not named an organization yet; only GET /v0/auth/me and POST /v0/organizations answer until then
    api_key_idstring (uuid)Only for an API key
    userobjectOnly for a session
    organizationOrg
    permissionsstring[]
    expires_atstring (date-time)
    featuresOrganizationFeatures

    Org object

    NameTypeNotes
    organization_idstring (uuid)
    namestring
    planfree | builder | growth | team
    screen_before_notifybooleanHold inbound mail until screened (operator setting: mai admin org-screening)

    Organization object

    NameTypeNotes
    organization_idstring (uuid)
    namestring
    planfree | builder | growth | team
    screen_before_notifyboolean
    retentionRetentionPolicy
    sendingOrgSending

    OrgSending object

    NameTypeNotes
    stateok | degraded | blockeddegraded: the last three sends in a row were refused by the transport. blocked: every attempt of the last 24 hours was refused for an authorization reason, so nothing can be delivered until the provider allows this server or the credentials are fixed.
    reason_codeunauthorized_ip | auth_failed | relay_unreachable | connection_refused | tls_failed | unknownThe fault code of the newest refused attempt; null while state is ok.
    sincestring (date-time)When the current state began; null while state is ok.

    NewOrganization object

    NameTypeNotes
    organization_idstring (uuid)
    namestring
    planfree | builder | growth | teamFree: self service sign up needs no card
    roleowner | admin | memberThe caller's role in the new organization: owner

    CreateInbox object

    NameTypeNotes
    usernamestringpattern ^[a-z0-9]([a-z0-9._-]{0,62}[a-z0-9])?$
    domainstring
    display_namestringmax length 200
    client_idstringpattern ^[A-Za-z0-9._~-]{1,256}$

    Inbox object

    NameTypeNotes
    idstring (uuid)
    inbox_idstring (email)
    emailstring (email)
    display_namestring
    client_idstring
    ticket_intakebooleanNew threads on this inbox become tickets.
    sending_paused_atstring (date-time)Set when the breaker paused sending for this inbox; null when only the organization is paused, which sending_health reports in paused_scope. An operator resumes it.
    sending_paused_reasonstring
    sending_healthSendingHealth
    signature_htmlstringThe signature of this address, HTML, applied to every message composed after it was written. Changing it never rewrites a draft that already exists (the rule of Proton): a draft keeps the signature of its own moment.
    groupGroupRef
    grants_countintegerHow many people hold access directly on this inbox. Null unless the caller is the owner or an admin.
    created_atstring (date-time)
    updated_atstring (date-time)

    SendingHealth object

    NameTypeNotes
    stateok | pausedpaused means sending from this inbox is refused with 403 sending_paused.
    paused_scopestringWhat paused sending: inbox, organization, or empty while state is ok. A send is refused by both scopes, so this is what tells them apart. Not an enum because the empty string is a value, and a validator that rejected it would fail on every healthy inbox.
    paused_atstring (date-time)When the breaker paused the inbox or its organization; null while state is ok.
    paused_reasonstringThe same sentence the 403 sending_paused carries, naming the window and the limit that was crossed, and the counts at the moment of the pause.
    window_hoursintegerLength of the rolling window the counts cover.
    sendsintegerMessages that reached a final outcome (accepted or rejected) in the window.
    hard_bouncesintegerPermanent rejections at send time plus bounces reported later by a delivery status notification.
    complaintsintegerSpam complaints reported through the feedback loop.
    bounce_ratenumberhard_bounces divided by sends, 0 when sends is 0.
    complaint_ratenumbercomplaints divided by sends, 0 when sends is 0.
    thresholdsSendingThresholds

    InboxList object

    NameTypeNotes
    countinteger
    next_page_tokenstring
    inboxesInbox[]

    Thread object

    NameTypeNotes
    thread_idstring (uuid)
    inbox_idstring
    subjectstring
    previewstring
    labelsstring[]
    message_countinteger
    timestampstring (date-time)
    messagesMessage[]
    retention_purged_atstring (date-time)Set when retention deleted the last message of the thread. A thread with no messages answers 200 with this and retention_notice, instead of 404, because a ticket may point at it.
    retention_noticestringThe sentence in place of a body the retention window removed.

    ThreadList object

    NameTypeNotes
    countinteger
    next_page_tokenstring
    threadsThread[]

    Message object

    NameTypeNotes
    idstring (uuid)
    message_idstringRFC 5322 Message-ID with angle brackets
    thread_idstring (uuid)
    inbox_idstring
    directionin | out
    fromstring
    tostring[]
    ccstring[]
    subjectstring
    textstring
    htmlstring
    extracted_textstringNew text without quoted history (set by the gatekeeper)
    previewstring
    snippetstringExcerpt around the match. Only in search results, and empty for a key holding message_metadata without message_read
    labelsstring[]
    in_reply_tostring
    referencesstring[]
    statusreceived | queued | sending | sent | failed | held | cancelled
    delivery_error_codeunauthorized_ip | auth_failed | relay_unreachable | connection_refused | tls_failed | unknownWhy an outbound message did not leave. Set when a delivery attempt was refused, absent otherwise; with status failed, the message is not delivered and the console says so.
    delivery_errorstringWhat the mail server said when it refused the message, one line, at most 500 characters, never a credential.
    last_errorstringThe last reason a message did not leave, from the transport or from the platform: a send held by undo send whose window closed while sending was paused fails with the reason of the pause here, and no delivery_error, because no mail server refused it.
    cancel_window_ends_atstring (date-time)End of the undo window of a send born held. Before it, POST .../cancel withdraws the message; after it, the message is on its way and cancel answers 409 invalid_state. Absent on a message that never had a window.
    authentication_resultsobjectWhat the SMTP edge verified for inbound mail: dkim, spf, dmarc, dmarc_policy, antivirus, spam_score, spam_action. Mail failing DMARC is labelled dmarc-fail, and spam under p=quarantine or p=reject.
    gatekeeperobject
    screeningreview | allowed | releasedHold state under screen before notify; absent when the message was not held. Pending messages are never returned.
    attachmentsobject[]
    created_atstring (date-time)

    MessageList object

    NameTypeNotes
    countinteger
    next_page_tokenstring
    messagesMessage[]

    Attachment object

    NameTypeNotes
    filenamestring
    content_typestring
    contentstring (base64)required

    Send object

    NameTypeNotes
    tostring (email)[]required, at least 1 item
    ccstring (email)[]
    bccstring (email)[]
    subjectstring
    textstring
    htmlstring
    labelsstring[]
    attachmentsAttachment[]

    Reply object

    NameTypeNotes
    textstring
    htmlstring
    reply_allboolean
    labelsstring[]
    attachmentsAttachment[]

    SendResult object

    NameTypeNotes
    message_idstring
    thread_idstring (uuid)
    statusqueued | held | sent | suppressedState of the row the request created. held means the undo window is open: nothing has been attempted yet, and cancel may still withdraw it. suppressed means every recipient is on the suppression list: no message exists because there was nobody to write to.
    cancel_window_ends_atstring (date-time)Deadline of POST .../cancel, present when status is held.
    recipientsRecipientOutcome[]One entry per recipient of the request, in the order it named them. A suppressed recipient is reported here and not hidden: the message is never written for it.

    CreateDraft object

    NameTypeNotes
    tostring (email)[]
    ccstring (email)[]
    bccstring (email)[]
    subjectstring
    textstring
    htmlstring
    labelsstring[]
    attachmentsAttachment[]
    in_reply_tostringMessage UUID or RFC Message-ID to reply to
    reply_allbooleanWith in_reply_to: copy the other recipients
    send_atstring (date-time)Send automatically at this time (future, within 365 days)

    UpdateDraft object

    NameTypeNotes
    tostring (email)[]
    ccstring (email)[]
    bccstring (email)[]
    subjectstring
    textstring
    htmlstring
    labelsstring[]
    attachmentsAttachment[]
    send_atstring,null (date-time)null cancels a scheduled send

    Draft object

    NameTypeNotes
    draft_idstring (uuid)
    inbox_idstring (email)
    thread_idstring (uuid)Set for a reply draft
    in_reply_tostringRFC Message-ID of the message replied to
    referencesstring[]
    tostring[]
    ccstring[]
    bccstring[]
    subjectstring
    textstring
    htmlstring
    labelsstring[]
    attachmentsobject[]
    send_atstring (date-time)
    statusdraft | scheduled | failed
    last_errorstringWhy a scheduled send was refused
    created_atstring (date-time)
    updated_atstring (date-time)

    DraftList object

    NameTypeNotes
    countinteger
    next_page_tokenstring
    draftsDraft[]

    Webhook object

    NameTypeNotes
    webhook_idstring (uuid)
    urlstring
    event_typesEventType[]
    inbox_idsstring[]
    enabledboolean
    secretstringwhsec_..., returned only on create

    Domain object

    NameTypeNotes
    domain_idstring (uuid)
    domainstring
    sharedboolean
    statuspending | verified
    recordsobject[]
    last_checked_atstring (date-time)
    verified_atstring (date-time)
    catch_all_inboxstring (email)The inbox that receives mail addressed to a local part nobody created on this domain, or null for no catch-all (D5)

    PushSubscribe object

    NameTypeNotes
    endpointstring (uri)required, The device at its push service. A capability: never logged, never returned
    keysobjectrequired
    expiration_timeintegerMilliseconds since the epoch, or null
    user_agentstringThe browser that subscribed, for the device label, max length 512

    PushUnsubscribe object

    NameTypeNotes
    endpointstring (uri)required, The endpoint the browser is dropping

    PushSubscription object

    NameTypeNotes
    push_subscription_idstring (uuid)
    devicestringLabel derived from the user agent, for example iPhone
    user_agentstring
    created_atstring (date-time)
    last_used_atstring (date-time)

    PushSubscriptionList object

    NameTypeNotes
    countinteger
    push_subscriptionsPushSubscription[]

    Ticket object

    NameTypeNotes
    idstring
    numberinteger
    inbox_idstring
    thread_idstring
    subjectstring
    requesterstring
    stateTicketState
    priorityTicketPriority
    assignee_userstring
    assignee_keystring
    sla_policystring
    due_first_replystring (date-time)
    due_resolutionstring (date-time)
    first_reply_atstring (date-time)
    resolved_atstring (date-time)
    closed_atstring (date-time)
    tagsstring[]
    created_atstring (date-time)
    updated_atstring (date-time)
    body_availablebooleanWhether the thread still has messages. False after retention emptied it; the ticket stays readable and retention_notice says why. Present on a single ticket read.
    retention_noticestringThe sentence explaining that retention deleted the conversation.

    TicketList object

    NameTypeNotes
    countinteger
    next_page_tokenstring
    ticketsTicket[]

    TicketEvent object

    NameTypeNotes
    idinteger
    kindstring
    actorstring
    detailobject
    created_atstring (date-time)

    TicketNote object

    NameTypeNotes
    idstring
    authorstring
    bodystring
    created_atstring (date-time)

    TicketDetail object

    NameTypeNotes
    ticketTicket
    eventsTicketEvent[]
    notesTicketNote[]

    TicketStats object

    NameTypeNotes
    by_stateobject
    openinteger
    breachinginteger
    unassignedinteger
    median_first_reply_secondsinteger

    CreateTicket object

    NameTypeNotes
    thread_idstringrequired, The conversation to open the ticket on. A thread whose previous ticket is resolved or closed accepts a new ticket, with a new number.
    priorityTicketPriority
    tagsstring[]
    assignee_userstring
    assignee_keystring

    UpdateTicket object

    NameTypeNotes
    stateTicketState
    priorityTicketPriority
    tagsstring[]
    assignee_userstring
    assignee_keystring

    TicketViewFilters object

    NameTypeNotes
    stateTicketState
    priorityTicketPriority
    assigneestringuser id, API key id, or none for unassigned
    inboxstringinbox address
    qstringcase insensitive over subject and requester

    TicketView object

    NameTypeNotes
    view_idstring
    namestring
    sharedbooleantrue when the whole organization sees it
    owner_user_idstringThe person the view belongs to; absent on a shared view
    filtersTicketViewFilters
    created_atstring (date-time)

    TicketViewList object

    NameTypeNotes
    countinteger
    ticket_viewsTicketView[]

    CreateTicketView object

    NameTypeNotes
    namestringrequired, Up to 60 characters, unique among the views the caller can see
    sharedbooleanSave it for the whole organization; an owner or an admin only
    filtersTicketViewFiltersrequired

    TicketSLAWindow object

    NameTypeNotes
    weekdayintegerrequired, ISO weekday: 1 is Monday, 7 is Sunday, min 1, max 7
    startstringrequired, HH:MM in the window timezone
    endstringrequired, HH:MM, after start; a window never crosses midnight
    timezonestringrequired, A real IANA zone, for example Europe/Berlin

    TicketSLATargets object

    NameTypeNotes
    first_replyobject
    resolutionobject

    TicketSLA object

    NameTypeNotes
    windowsTicketSLAWindow[]
    targetsTicketSLATargets
    auto_close_daysintegerDays a resolved ticket may stay silent before it closes; 0 disables
    sourcedefault | organizationdefault means the plan table, untouched
    updated_bystring
    updated_atstring (date-time)
    notestringThe sentence that says a change is not retroactive

    UpdateTicketSLA object

    NameTypeNotes
    windowsTicketSLAWindow[]
    targetsTicketSLATargets
    auto_close_daysintegermin 0, max 365

    Checkout object

    NameTypeNotes
    planbuilder | growth | teamrequired
    intervalmonthly | yearlydefault monthly
    success_urlstring (uri)Defaults to the deployment's MAI_BILLING_RETURN_URL
    cancel_urlstring (uri)Defaults to the deployment's MAI_BILLING_RETURN_URL

    BillingSession object

    NameTypeNotes
    session_idstring
    urlstring (uri)

    Billing object

    NameTypeNotes
    planfree | builder | growth | team
    statusnone | incomplete | incomplete_expired | trialing | active | past_due | unpaid | canceled | paused
    intervalmonthly | yearly
    current_period_endstring (date-time)
    cancel_at_period_endboolean
    past_due_sincestring (date-time)
    grace_period_ends_atstring (date-time)Set while past_due or unpaid; the plan drops to free after it

    Member object

    NameTypeNotes
    user_idstring (uuid)
    emailstring (email)
    namestring
    roleowner | admin | member
    last_login_atstring (date-time)
    created_atstring (date-time)
    inbox_countintegerHow many inboxes this person can see
    invited_atstring (date-time)
    accepted_atstring (date-time)

    MemberList object

    NameTypeNotes
    countinteger
    membersMember[]

    Invitation object

    NameTypeNotes
    invitation_idstring (uuid)
    emailstring (email)
    roleadmin | member
    invited_bystring
    expires_atstring (date-time)
    created_atstring (date-time)

    InvitationList object

    NameTypeNotes
    countinteger
    invitationsInvitation[]

    InvitationPreview object

    NameTypeNotes
    organizationstring
    emailstring (email)
    roleadmin | member
    expires_atstring (date-time)

    Group object

    NameTypeNotes
    group_idstring (uuid)
    namestring
    slugstring
    colorstring
    inbox_countinteger
    domain_countinteger
    created_atstring (date-time)

    KeyScopeInput object

    NameTypeNotes
    kindorg | domain | userDefaults to org for the owner and an admin, to user for a member. A member may only ask for user.
    idstring (uuid)The domain, when kind is domain

    ApiKey object

    NameTypeNotes
    api_key_idstring (uuid)
    api_keystringThe secret, returned once on create
    prefixstring
    namestring
    permissionsPermission[]Null means every permission the role allows
    scopeobject
    expires_atstring (date-time)
    last_used_atstring (date-time)
    created_atstring (date-time)
    request_countintegerRequests this key has authenticated
    inactive_sincestring (date-time)The last use, or the creation of a key never used
    stalebooleanTrue when the key has not been used for 30 days. The operator command mai admin keys-stale applies the same rule and can revoke such keys.

    GroupRef object

    NameTypeNotes
    group_idstring (uuid)
    namestring
    colorstring

    GroupList object

    NameTypeNotes
    countinteger
    groupsGroup[]

    Grant object

    NameTypeNotes
    user_idstring (uuid)
    emailstring (email)
    namestring
    rightsviewer | responder
    created_atstring (date-time)

    GrantList object

    NameTypeNotes
    countinteger
    grantsGrant[]

    OrgExport object

    NameTypeNotes
    formatstring
    generated_atstring (date-time)
    organizationOrg
    inboxesobject[]
    domainsobject[]
    webhooksobject[]
    api_keysobject[]Metadata only; the key and its hash are never exported.
    countsobject
    audit_logobject[]
    noticestringWhat this export deliberately leaves out, in plain language

    SendingThresholds object

    NameTypeNotes
    max_bounce_ratenumberHard bounce rate above which sending pauses.
    max_complaint_ratenumberComplaint rate above which sending pauses, once min_complaint_sends is reached.
    min_sendsintegerSends needed in the window before the bounce rate applies.
    min_complaint_sendsintegerSends needed before the complaint rate applies; below it the limit is a count.
    small_sender_complaintsintegerComplaints in the window that pause sending below min_complaint_sends.

    WebhookEvent object

    NameTypeNotes
    event_idstring (uuid)
    event_typestring
    statuspending | succeeded | failedDelivery state
    attemptsintegerAttempts claimed so far
    last_attempt_statussucceeded | failed
    last_status_codeinteger
    last_latency_msinteger
    last_attempt_atstring (date-time)
    created_atstring (date-time)

    WebhookEventList object

    NameTypeNotes
    countinteger
    eventsWebhookEvent[]
    next_page_tokenstring

    WebhookAttempt object

    NameTypeNotes
    attempt_nointeger
    statussucceeded | failed
    status_codeintegerNull when the connection failed
    latency_msinteger
    response_excerptstringAt most 2 KB of the response body with credentials redacted; response headers are never stored, max length 2048
    errorstring
    created_atstring (date-time)

    WebhookAttemptList object

    NameTypeNotes
    countinteger
    attemptsWebhookAttempt[]

    WebhookReplay object

    NameTypeNotes
    event_idstring (uuid)
    delivery_idinteger
    statuspendingIt is queued; the attempt follows
    attemptsintegerAttempts recorded before this replay

    RotateSecret object

    NameTypeNotes
    webhook_idstring (uuid)
    secretstringThe new signing secret, shown once
    rotated_atstring (date-time)
    previous_secret_valid_untilstring (date-time)Until then the dispatcher signs with the previous secret too

    MFAStatus object

    NameTypeNotes
    enrolledbooleanA confirmed factor; a pending secret does not count
    confirmed_atstring (date-time)
    recovery_codes_leftintegermin 0, max 10
    required_by_organizationbooleanThe organization requires a factor; with enrolled false every other route answers 403 mfa_enrollment_required
    organization_policyMFAPolicy

    MFAPolicy object

    NameTypeNotes
    require_mfaboolean

    MFAEnrollment object

    NameTypeNotes
    secretstringBase32 TOTP secret, for manual entry
    otpauth_urlstringotpauth:// URI a QR code is drawn from (SHA1, 6 digits, 30 seconds)
    recovery_codesstring[]Ten single use codes; only their hashes are stored, at least 10 item, at most 10 items

    MFAVerify object

    NameTypeNotes
    enrolledboolean
    recovery_codes_leftinteger
    sessionSession

    MFAStep object

    NameTypeNotes
    mfa_requiredtrue
    challenge_tokenstringSingle use, five minutes, five attempts; redeem at POST /v0/auth/mfa/challenge
    kindverify | enrollverify when the factor exists, enroll when the organization requires one this person has not set up
    expires_atstring (date-time)

    SearchResult object

    NameTypeNotes
    countinteger
    next_cursorstringPass as cursor= for the next page; absent on the last one
    messagesMessage[]

    Forward object

    NameTypeNotes
    tostring (email)[]required, at least 1 item
    ccstring (email)[]
    bccstring (email)[]
    commentstringOptional text above the quoted message, below the signature
    labelsstring[]

    BatchResult object

    NameTypeNotes
    appliedintegerLines whose action happened (or had already happened: every action is idempotent)
    failedintegerLines with a per item failure: not_found, forbidden or invalid
    resultsBatchItem[]

    BatchItem object

    NameTypeNotes
    idstringThe id as it was sent
    statusapplied | not_found | forbidden | invalid
    errorstringWhy this item did not apply; absent on applied

    RuleTarget object

    NameTypeNotes
    kindinbox | domain | orgrequired
    idstring (uuid)The inbox or the domain id; absent for kind org

    RuleSize object

    NameTypeNotes
    largerinteger (int64)min 0
    smallerinteger (int64)min 0

    RuleConditions object

    NameTypeNotes
    fromstring[]Sender, case and accent insensitive substring, ORed, at most 32 items
    tostring[]Recipient (To or Cc), ORed, at most 32 items
    subjectstring[]Subject substring, ORed, at most 32 items
    querystringFull text, same parser as search, max length 512
    negated_querystringThe message must not match this, max length 512
    has_attachmentboolean
    sizeRuleSize
    spam_verdictclean | review | spam[]at most 3 items, one of clean, review, spam

    RuleAction object

    NameTypeNotes
    typeadd_label | remove_label | archive | move_to_folder | mark_read | forward_to | auto_reply | reject | webhook | assignrequired
    labelstringadd_label, remove_label, move_to_folder: the label, which is also the folder, max length 64
    addressstring (email)forward_to: a verified address of the organization
    reasonstringreject: one line, no address, sent back in the 550, max length 200
    webhook_idstring (uuid)webhook: the endpoint that receives rule.matched
    subjectstringauto_reply: the subject of the answer
    textstringauto_reply: the body of the answer, max length 4000
    assigneestring (uuid)assign: the member who takes the ticket

    Rule object

    NameTypeNotes
    rule_idstring (uuid)
    namestring
    targetRuleTarget
    priorityintegerLower is evaluated first; ties go to the older rule
    enabledboolean
    include_spambooleanFalse means the rule never sees a message with the spam verdict
    conditionsRuleConditions
    actionsRuleAction[]at most 20 items
    created_atstring (date-time)
    updated_atstring (date-time)

    RuleInput object

    NameTypeNotes
    namestringrequired, max length 100
    targetRuleTarget
    priorityintegermin 0, max 100000, default 100
    enabledbooleandefault true
    include_spambooleandefault false
    conditionsRuleConditionsrequired
    actionsRuleAction[]required, at least 1 item, at most 20 items

    RulePatch object

    NameTypeNotes
    namestringmax length 100
    targetRuleTarget
    priorityintegermin 0, max 100000
    enabledboolean
    include_spamboolean
    conditionsRuleConditions
    actionsRuleAction[]at least 1 item, at most 20 items

    RuleApplyReport object

    NameTypeNotes
    job_idstring (uuid)
    rule_idstring (uuid)
    statuspending | running | done
    matchedinteger
    appliedinteger
    skippedobject
    created_atstring (date-time)
    finished_atstring (date-time)

    AgentAction object

    NameTypeNotes
    namedraft_reply | draft_forward | add_labels | assign_thread | mark_spam | archive_thread | move_to_trash
    routestringThe API operation a person uses to do the same thing
    summarystring

    AgentConfig object

    NameTypeNotes
    enabledbooleanThe effective state: the switch on and at least one action. An empty action set is off.
    configuredbooleanFalse when this inbox was never configured; the rest of the answer is then the default form
    disabled_reasonnot_configured | no_actions | switched_offAbsent when the agent is on
    instructionsstringEmpty when none are stored
    toneconcise_professional | concise_casual | expanded_professional | expanded_casual
    allowed_actionsdraft_reply | draft_forward | add_labels | assign_thread | mark_spam | archive_thread | move_to_trash[]The whole set, in policy order; empty means the agent is off, one of draft_reply, draft_forward, add_labels, assign_thread, mark_spam, archive_thread, move_to_trash
    available_actionsAgentAction[]The vocabulary a configuration may name
    budget_per_hourintegerActions this inbox may take in one hour
    actions_usedintegerActions the agent took in the current hour
    agent_key_idstring (uuid)The key that configured the agent: its identity in the audit log
    agent_key_namestring
    updated_atstring (date-time)

    AgentConfigRequest object

    NameTypeNotes
    instructionsstring1 to 4000 characters, or null to clear, max length 4000
    allowed_actionsdraft_reply | draft_forward | add_labels | assign_thread | mark_spam | archive_thread | move_to_trash[]The whole set; an empty array turns the agent off, one of draft_reply, draft_forward, add_labels, assign_thread, mark_spam, archive_thread, move_to_trash
    toneconcise_professional | concise_casual | expanded_professional | expanded_casual
    enabledboolean

    AutoReply object

    NameTypeNotes
    inboxstring (email)
    rule_idstring (uuid)The one ordinary rule that carries the answer; the guards are its guards
    modefixed | daily | weekly | monthly | permanent
    timezonestringThe IANA zone the window is read in, always explicit
    startstringRFC 3339 instant for fixed, HH:MM clock time for daily, weekly and monthly
    endstringThe other end of the window; an end before the start wraps past midnight
    daysstring[]Weekday tokens (mon..sun) in weekly mode, day-of-month numbers in monthly mode, empty otherwise
    subjectstring
    body_textstring
    body_htmlstring
    restrict_to_domainbooleanAnswer only senders on the inbox's own domain or on a domain the organization verified
    activebooleanWhether the window covers now, in the schedule's timezone
    updated_atstring (date-time)

    AutoReplyInput object

    NameTypeNotes
    modefixed | daily | weekly | monthly | permanentrequired
    timezonestringrequired, IANA zone, for example Europe/Rome; required, never derived from the server
    startstringRFC 3339 for fixed, HH:MM for daily, weekly and monthly; absent for permanent
    endstringRFC 3339 for fixed, HH:MM for daily, weekly and monthly; absent for permanent
    daysstring[]Weekday tokens for weekly, day-of-month numbers for monthly, absent otherwise, at most 31 items
    subjectstringrequired, max length 256
    body_textstringrequired, max length 4000
    body_htmlstring
    restrict_to_domainbooleandefault false

    BlocklistEntry object

    NameTypeNotes
    entry_idstring (uuid)
    scopeinbox | org
    scope_idstring (uuid)The inbox, absent for the organization list
    inboxstring (email)
    list_kindblock | allowallow beats block: an allowed address passes through a blocked domain
    kindsender | domain
    valuestringThe lowered address or domain, matched exactly
    created_atstring (date-time)

    BlocklistInput object

    NameTypeNotes
    list_kindblock | allowdefault block
    kindsender | domainrequired
    valuestringrequired, An address for kind sender, a domain for kind domain; never one as the other, max length 320

    MessageTimeline object

    NameTypeNotes
    message_idstring (uuid)
    inbox_idstringThe address that holds the message, never the list of recipients
    statusreceived | queued | sending | sent | failed | held | cancelledThe state of the row now; the events carry how it got there
    eventsMessageTimelineEvent[]

    MessageTimelineEvent object

    NameTypeNotes
    typemessage.received | message.received.spam | message.sent | message.delivered | message.delivery_delayed | message.failed | message.rejected | message.bounced | message.complained | message.dropped | message.ruled
    sourcesmtp | dsn | arf | breaker | rspamd | rulesmtp a reply, dsn a delivery status notification, arf a feedback report, breaker the sending health breaker, rspamd the spam filter, rule a deterministic rule
    codestringThe SMTP status, the DSN status or the policy code; empty when the source has none. unknown always carries a reason in text.
    textstringThe reply or the sentence, one line, at most 500 characters, never a body and never a recipient
    atstring (date-time)

    DomainReputation object

    NameTypeNotes
    domainstring
    window_hoursintegerThe rolling window the counts cover, the same as sending_health.window_hours
    sendsintegerMessages that reached a final outcome in the window
    hard_bouncesintegerPermanent rejections at send time plus bounces reported by a DSN
    complaintsintegerSpam complaints reported through the feedback loop
    bounce_ratenumberhard_bounces divided by sends, 0 when sends is 0
    complaint_ratenumbercomplaints divided by sends, 0 when sends is 0
    thresholdsSendingThresholds
    breach_stateok | breachedbreached when the window trips a limit or when the breaker has paused an inbox on the domain or the organization
    breach_reasonstringThe sentence naming the window and the limit crossed; absent while breach_state is ok
    paused_scopestringWhat paused sending: inbox, organization, or empty. A send is refused by both scopes, so this tells them apart.
    paused_atstring (date-time)
    paused_reasonstringThe sentence of the pause, the same one the 403 sending_paused carries

    OAuthClientInput object

    NameTypeNotes
    client_namestringrequired, max length 100
    client_uristring (uri)Where a person can read about the app
    redirect_urisstring (uri)[]required, https, or http on a loopback host; no fragment, at least 1 item, at most 10 items
    scopemessages:send | full_accessThe most this client may ever ask for, default messages:send

    OAuthClient object

    NameTypeNotes
    client_idstringOpaque, prefixed oac_
    client_namestring
    client_uristring
    redirect_urisstring[]
    scopesstring[]The scopes this client may ask for
    created_atstring (date-time)
    last_used_atstring (date-time)

    OAuthAuthorizeResult object

    NameTypeNotes
    redirect_urlstring (uri)The registered redirect with the code (and the state) in the query
    grant_idstring (uuid)
    scopemessages:send | full_access[]one of messages:send, full_access
    expires_atstring (date-time)When the code stops being exchangeable (five minutes)

    OAuthToken object

    NameTypeNotes
    access_tokenstringOpaque, prefixed mai_oat_; lives one hour
    token_typeBearer
    expires_inintegerSeconds
    refresh_tokenstringOpaque, prefixed mai_ort_; rotated on every use, lives thirty days
    scopemessages:send | full_access

    OAuthGrant object

    NameTypeNotes
    grant_idstring (uuid)
    client_idstring
    client_namestring
    client_uristring
    scopemessages:send | full_access[]one of messages:send, full_access
    created_atstring (date-time)
    last_used_atstring (date-time)
    mfa_protectedbooleanThe organization requires a second factor, so an app could only be connected with one

    OAuthGrantList object

    NameTypeNotes
    countinteger
    grantsOAuthGrant[]

    RequestLogEntry object

    NameTypeNotes
    idstring (uuid)
    request_idstringThe X-Request-Id of the call
    key_idstring (uuid)The key that made the call; absent for a person signed in
    actorstringuser:<id> or api_key:<id>
    actor_typeuser | agent
    methodstring
    pathstringPath and filters, with the value of a credential-shaped query parameter masked
    statusinteger
    duration_msinteger
    sdkstringSDK name normalised from the User-Agent; absent when the caller is not one of our SDKs
    sdk_versionstring
    sdk_update_availablebooleanA newer version of that SDK exists on this deployment
    sdk_lateststring
    sdk_noticestringThe sentence to show a person: which SDK, which version, which one to move to
    created_atstring (date-time)

    RequestLogBody object

    NameTypeNotes
    headersobjectRequest headers only, from an allowlist
    bodyobjectThe JSON as it was, with credentials and mail content replaced by markers
    bytesintegerSize of the original body
    sha256stringDigest of the original body, empty when there was none
    truncatedbooleanThe stored body is a summary: the original was larger than the log keeps

    RetentionPolicy object

    NameTypeNotes
    messages_daysinteger0 keeps messages forever; otherwise 1 to 3650 days. Deleting a message also queues its raw blob and its attachments' blobs., min 0, max 3650
    attachments_daysinteger0 keeps attachments forever; otherwise 1 to 3650 days, independent of messages_days., min 0, max 3650
    audit_daysinteger0 keeps audit entries forever; otherwise 30 to 3650 days, default 90., min 0, max 3650

    Suppression object

    NameTypeNotes
    emailstring (email)The address, lower cased
    originbounce | complaint | manualWhy it is on the list: a permanent bounce, a complaint (ARF report), or a person (the API or a one-click unsubscribe)
    source_idstringProvenance: the message or report the entry came from; absent for a manual entry
    created_atstring (date-time)

    SuppressionInput object

    NameTypeNotes
    emailstring (email)required
    originbounce | complaint | manualrequired, Required: a row that does not say why the address is there cannot be reviewed
    source_idstringmax length 320

    SuppressionsPost object

    NameTypeNotes
    entriesSuppressionInput[]The batch form, 1 to 100 entries; the CSV import is the way to add more, at least 1 item, at most 100 items
    emailstring (email)The single entry form: email and origin, without entries
    originbounce | complaint | manual
    source_idstringmax length 320

    SuppressionResult object

    NameTypeNotes
    addedintegerRows the list gained
    existingintegerAddresses the list already knew; the origin of an existing row is kept
    countinteger
    entriesSuppression[]The entries as they are stored, not as they were sent

    RecipientOutcome object

    NameTypeNotes
    addressstring (email)
    statusqueued | suppressedsuppressed: the address is on the suppression list of the organization, so the message was not written for it

    CustomRole object

    NameTypeNotes
    role_idstring (uuid)
    namestring1 to 60 characters, unique in the organization ignoring case
    descriptionstringAt most 200 characters; empty when none was given
    permissionsPermission[]Names an API key could hold. A custom role that lists nothing is refused on the write path.
    member_countintegerHow many people the role reaches now, counting a person once even when several of their groups carry it
    assignmentsRoleAssignment[]The people and the groups that hold it
    created_atstring (date-time)
    updated_atstring (date-time)

    CustomRoleList object

    NameTypeNotes
    countinteger
    rolesCustomRole[]

    CustomRoleRequest object

    NameTypeNotes
    namestringmax length 60
    descriptionstringmax length 200
    permissionsPermission[]Required on create. An unknown name is 422 unknown_permission; a name the caller does not hold is 403 permission_escalation.

    RoleAssignment object

    NameTypeNotes
    role_idstring (uuid)
    user_idstring (uuid)Set when the role is assigned to a person
    emailstring (email)The address of that person, so the console does not resolve ids
    group_idstring (uuid)Set when the role is assigned to a group
    group_namestringThe brand's display name
    assigned_atstring (date-time)

    RoleAssignmentRequest object

    NameTypeNotes
    role_idsstring (uuid)[]required, The whole set the subject should hold. An empty array revokes every custom role from the subject; that is a revocation, not a mistake., at most 20 items

    RoleAssignmentChange object

    NameTypeNotes
    assignmentsRoleAssignment[]
    addedstring (uuid)[]Role ids this call gave
    removedstring (uuid)[]Role ids this call took away

    ExportJob object

    NameTypeNotes
    export_idstring (uuid)
    statusqueued | running | ready | failed
    row_countintegerRows the document will contain, counted inside the caller's scope; the number that decided it was a job
    size_bytesintegerSize of the document, once it exists
    created_atstring (date-time)
    ready_atstring (date-time)
    expires_atstring (date-time)End of the seven day download window; after it the job and its document are purged
    page_urlstringA page on the site that shows this export, for a person who does not hold a key
    poll_urlstringGET this to follow the job, on the documented version
    download_urlstringGET this once status is ready
    errorstringWhy the job failed, one line, when status is failed

    FeatureState object

    NameTypeNotes
    namerules | agent | oauth | request_logs
    enabledbooleanThe feature works for this organization: deployment and organization both on
    deploymentbooleanThe kill switch of this deployment (MAI_RULES_ENABLED, MAI_AGENT_ENABLED, MAI_OAUTH_ENABLED, MAI_REQUEST_LOGS_ENABLED)
    organizationbooleanThe platform operator's choice for this organization; off by default

    OrganizationFeatures object

    NameTypeNotes
    rulesFeatureState
    agentFeatureState
    oauthFeatureState
    request_logsFeatureState

    Error object

    NameTypeNotes
    namestringrequired
    codemissing_authorization | unknown_api_key | validation_error | not_found | already_exists | domain_not_verified | conflict | cannot_delete | limit_exceeded | rate_limit_exceeded | rate_limited | address_quarantined | sending_paused | missing_permission | permission_escalation | api_key_expired | not_held | billing_disabled | billing_provider_error | already_subscribed | no_billing_account | invalid_signature | too_many_streams | payload_too_large | attachment_infected | antivirus_unavailable | auth_disabled | provider_not_configured | invalid_magic_link | invalid_state | code_rejected | email_not_verified | provider_unavailable | email_delivery_failed | invalid_refresh_token | token_expired | unknown_token | session_revoked | access_denied | internal_error | organization_exists | needs_organization | session_required | thread_required | thread_not_found | ticket_not_found | ticket_exists | invalid_transition | invalid_priority | note_required | no_inbound_message | view_not_found | view_exists | too_many_views | push_disabled | too_many_subscriptions | mfa_required | mfa_enrollment_required | mfa_step_mismatch | invalid_mfa_challenge | invalid_mfa_code | mfa_code_reused | invalid_recovery_code | too_many_attempts | already_enrolled | not_enrolled | mfa_required_by_organization | mfa_reset_required | unknown_action | oauth_disabled | invalid_client | invalid_grant | invalid_request | invalid_scope | unsupported_response_type | invalid_redirect_uri | retention_out_of_range | unknown_permission | app_forbidden | insufficient_rightsrequired
    messagestringrequired
    delivery_error_codeunauthorized_ip | auth_failed | relay_unreachable | connection_refused | tls_failed | unknownWhy the transport refused a send (502 email_delivery_failed only). unauthorized_ip is an SMTP 525, auth_failed a 535.
    delivery_errorstringWhat the mail server said, in its own words, at most 500 characters, never a credential.
    message_idstringThe RFC Message-ID of the message the refusal is recorded on.
    thread_idstring (uuid)The thread of that message, where the console shows it as Not delivered.