openapi: 3.2.0 info: title: Bird Email Threads API version: 1.0.0 description: 'The Bird API: one REST API for email, SMS, WhatsApp, verification, and Realtime.' servers: - url: https://{region}.platform.bird.com description: 'Regional API endpoint. Use the host for the region your organization is hosted in. Official Bird SDKs and the CLI select it automatically from your API key, so you rarely need to set it by hand. ' variables: region: default: us1 enum: - us1 - eu1 description: The region your organization's data is hosted in. - url: https://platform.bird.com description: Region-independent endpoint for authentication and account administration. - url: http://localhost:8080 description: Local development. security: - BearerAuth: [] tags: - name: email-threads description: Conversations in a mailbox. Threads group related inbound and outbound messages and carry read state, labels, and participants. paths: /v1/email/threads: get: operationId: listEmailThreads summary: List threads description: 'Returns a paginated list of conversations across the workspace''s mailboxes, most recently active first. `label` selects the view: the inbox (the default when omitted), `archive`, `spam`, `blocked`, or any custom label. You can also filter by mailbox, by linked contact, by participant address, or by a subject substring. This listing filters; it does not search message content. Conversations whose every message is trashed are excluded; restoring a message returns the conversation to the list. `before` and `after` filter by time. To page through the results, pass the response cursors back as `starting_after` or `ending_before`.' tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.list parameters: - name: mailbox_id in: query required: false description: Filter to conversations in a specific mailbox. schema: $ref: '#/components/schemas/MailboxID' - name: contact_id in: query required: false description: Filter to conversations linked to a specific contact. schema: $ref: '#/components/schemas/ContactID' - name: label in: query required: false description: 'Filter to conversations that have this label. Repeat the parameter to ask for more than one: only conversations that have every label you list are returned. A placement label picks a folder: `inbox`, `archive`, `spam`, or `blocked`. A custom label matches a conversation in any folder. Leave this out and you get the inbox.' schema: type: array maxItems: 20 items: type: string minLength: 1 maxLength: 64 example: - urgent - name: has_unread in: query required: false description: When `true`, only conversations with unread messages are returned. This filters on the conversation's unread state, so you can combine it with `label`, for example to get unread conversations in the archive. The `unread` label itself lives on individual messages; this filter uses the conversation's aggregate unread state. schema: type: boolean - name: participant in: query required: false description: Conversations involving this address, matching the sender or any recipient. The match is case-insensitive and matches on any part of the address, so a fragment works as well as the whole address. schema: type: string minLength: 3 maxLength: 320 example: billing@acme.com - name: subject in: query required: false description: Conversations whose subject contains this text (case-insensitive). schema: type: string minLength: 3 maxLength: 256 example: quarterly invoice - name: after in: query required: false description: Filter to conversations whose most recent message is at or after this time. Use the response cursors for pagination. schema: type: string format: date-time - name: before in: query required: false description: Filter to conversations whose most recent message is at or before this time. Use the response cursors for pagination. schema: type: string format: date-time - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/StartingAfter' - $ref: '#/components/parameters/EndingBefore' responses: '200': description: Paginated list of threads. content: application/json: schema: $ref: '#/components/schemas/EmailThreadList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - attio - cli - make - mcp - n8n - sdk /v1/email/threads/{thread_id}: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' get: operationId: getEmailThread summary: Get a thread description: Returns a single conversation. Fetch the messages in the conversation with List messages in a thread. A thread whose retention tier has ended returns `410 Gone`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.get responses: '200': description: Thread object. content: application/json: schema: $ref: '#/components/schemas/EmailThread' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp - n8n - sdk patch: operationId: updateEmailThread summary: Update a thread description: Applies label changes to a conversation, and links or unlinks a contact. Adding `spam` files the conversation, and its received messages, as spam. Adding `archive` files it away without deleting it. Adding `inbox`, or removing `spam`, `blocked`, or `archive`, returns it to the inbox, and its unread count recomputes to match. An archived conversation returns to the inbox by itself when a new message arrives that isn't spam or blocked; a junk reply or an outbound send leaves it archived. To block a sender going forward, add a receive rule instead. Any field you leave out stays unchanged. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.update parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EmailThreadUpdateRequest' responses: '200': description: The updated thread. content: application/json: schema: $ref: '#/components/schemas/EmailThread' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - cli - make - mcp - n8n - sdk delete: operationId: deleteEmailThread summary: Delete a thread description: Moves the conversation and all of its messages to the trash. Trashed messages are permanently deleted after 30 days, or sooner if the mailbox's retention period ends first. Pass `permanent=true` to permanently delete the conversation and its messages immediately. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.delete parameters: - name: permanent in: query required: false description: Permanently delete the conversation and its messages immediately instead of moving them to the trash. schema: type: boolean default: false - $ref: '#/components/parameters/IdempotencyKey' responses: '204': description: Thread deleted. '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - cli - make - mcp - n8n - sdk /v1/email/threads/{thread_id}/messages: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' get: operationId: listEmailThreadMessages summary: List messages in a thread description: 'Returns the messages in a conversation, newest first, both received and sent. To page through older messages, use `starting_after`. The sort order is fixed, so to render the messages in conversation order, reverse the page yourself. By default, every message that is not in the trash is returned, whichever folder the conversation is in. Pass `label` to narrow the view instead: use `trash` for trashed messages, or any custom label. Pass `include=extracted_text` to inline each message''s extracted plain text. A thread whose retention tier has ended returns `410 Gone`.' tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.messages.list parameters: - name: direction in: query required: false description: Filter to received (`inbound`) or sent (`outbound`) messages. schema: $ref: '#/components/schemas/MessageDirection' - name: label in: query required: false description: 'Filter to messages that have this label. `trash` lists trashed messages. Any other label, whether that is `archive`, `spam`, `blocked`, `unread` or one of your own, lists the messages that have it and are not in the trash. When omitted, every message that is not trashed is returned, whichever folder the conversation is in. ' schema: type: string minLength: 1 maxLength: 64 example: unread - name: include in: query required: false description: Set to `extracted_text` to inline each message's extracted plain text. schema: type: string enum: - extracted_text - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/StartingAfter' - $ref: '#/components/parameters/EndingBefore' responses: '200': description: Paginated list of messages in the conversation. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - attio - cli - make - mcp - n8n - sdk /v1/email/threads/{thread_id}/messages/{message_id}: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ get: operationId: getEmailThreadMessage summary: Get a message in a thread description: Returns a single message in a conversation, including its extracted plain text. Metadata and extracted text stay readable for the mailbox's retention tier. A message that has aged past its retention tier returns `410 Gone`. A message that exists but does not belong to this thread returns `404`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.messages.get responses: '200': description: The message. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessage' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp - n8n - sdk patch: operationId: updateEmailThreadMessage summary: Update a message in a thread description: Applies read-state, label, and contact changes to a message in a conversation. Omitted fields are left unchanged. The read flag is only valid on received messages. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public x-snippet-key: none parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageUpdateRequest' responses: '200': description: The updated message. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - make - n8n delete: operationId: deleteEmailThreadMessage summary: Delete a message in a thread description: Moves the message to the trash. Trashed messages are permanently deleted after 30 days, or sooner if the mailbox's retention period ends first. Pass `permanent=true` to permanently delete the message immediately. When the last message in a conversation is permanently deleted, the conversation is deleted with it. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public x-snippet-key: none parameters: - name: permanent in: query required: false description: Permanently delete the message immediately instead of moving it to the trash. schema: type: boolean default: false - $ref: '#/components/parameters/IdempotencyKey' responses: '204': description: Message deleted. '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - make - n8n /v1/email/threads/{thread_id}/messages/{message_id}/body: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ get: operationId: getEmailThreadMessageBody summary: Get a thread message's original body description: Returns the original rendered HTML and plain-text body of a message in a conversation. The original body is available for 30 days after the message occurred. Later requests return `410 Gone`, while the message's extracted text stays readable on the message itself. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.messages.body responses: '200': description: The original rendered body. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageBody' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp - n8n - sdk /v1/email/threads/{thread_id}/messages/{message_id}/raw: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ get: operationId: getEmailThreadMessageRaw summary: Get a thread message's raw content description: Returns the original message exactly as received, in RFC 5322 (MIME) format. Available for received messages for 30 days after the message occurred. Later requests return `410 Gone`. Sent messages have no stored raw form and return `404`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: none responses: '200': description: The original message in RFC 5322 (MIME) format. content: message/rfc822: schema: type: string format: binary '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp /v1/email/threads/{thread_id}/messages/{message_id}/attachments: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ get: operationId: listEmailThreadMessageAttachments summary: List a thread message's attachments description: Returns the attachments on a message in a conversation. Attachment bytes are downloadable for the mailbox's retention tier after the message occurred. Later requests return `410 Gone`, while the attachment metadata stays readable on the message's `attachment_manifest`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.messages.attachments responses: '200': description: The message's attachments. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageAttachmentList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp - n8n - sdk /v1/email/threads/{thread_id}/messages/{message_id}/attachments/{attachment_id}: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ - name: attachment_id in: path required: true description: Attachment identifier. Starts with `ea_` for sent mail or `rea_` for received mail. schema: type: string minLength: 1 pattern: ^(ea|rea)_[0-9a-hjkmnp-tv-z]{26}$ get: operationId: getEmailThreadMessageAttachment summary: Get a thread message's attachment description: Returns the raw bytes of a single attachment on a conversation message. Works for both received messages (`rem_`) and sent messages (`em_`). Attachment bytes are downloadable for the mailbox's retention tier after the message occurred. Later requests return `410 Gone`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: none responses: '200': description: The raw attachment bytes. content: application/octet-stream: schema: type: string format: binary '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp /v1/email/threads/{thread_id}/messages/{message_id}/reply: parameters: - name: thread_id in: path required: true description: Thread identifier. Starts with `thr_`. schema: $ref: '#/components/schemas/ThreadID' - name: message_id in: path required: true description: Message ID (`rem_` for a received message, `em_` for a sent one). schema: type: string minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ post: operationId: replyEmailThreadMessage summary: Reply to a thread message description: 'Sends a reply to a specific message in a conversation, from the mailbox''s own address. Recipients are derived from the message being replied to: for a received message, its Reply-To address when present, otherwise its From address; for a message the mailbox sent, its original To recipients. Set `reply_all` to copy the original To and Cc recipients in as `Cc`, leaving out the mailbox''s own address. The subject and the threading headers that keep the reply in this conversation are set automatically, and the reply is recorded in the conversation. To reply to a conversation as a whole, target its newest received message.' tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.threads.messages.reply parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageReplyRequest' responses: '202': description: Reply accepted for asynchronous delivery and recorded in the conversation. headers: Idempotency-Replay: $ref: '#/components/headers/IdempotencyReplay' content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '410': $ref: '#/components/responses/Gone' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - attio - cli - make - mcp - n8n - sdk /v1/email/mailboxes/{mailbox_id}/messages: parameters: - name: mailbox_id in: path required: true description: Mailbox identifier. Starts with `mbx_`. schema: $ref: '#/components/schemas/MailboxID' get: operationId: listMailboxMessages summary: List a mailbox's messages description: 'Returns the messages in a mailbox across all of its conversations, newest first. By default only received messages in the inbox and all sent messages are returned. Pass `label` to see another view instead: - `archive`: Filed-away mail. - `spam` or `blocked`: Mail placed in either folder. - `trash`: Trashed messages. - `unread`: Messages you have not read yet, across all conversations. - Any custom label you have applied. Filter by direction or combined delivery status. Pass `include=extracted_text` to inline each message''s extracted plain text. `before` and `after` filter by time. To page through results, pass the response cursors back as `starting_after` or `ending_before`.' tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public x-snippet-key: none parameters: - name: label in: query required: false description: 'Filter to messages that have this label. `trash` lists trashed messages. Any other label, whether that is `archive`, `spam`, `blocked`, `unread` or one of your own, lists the messages that have it and are not in the trash. When omitted, received messages in the inbox and all sent messages are returned. ' schema: type: string minLength: 1 maxLength: 64 example: unread - name: direction in: query required: false description: Filter to received (`inbound`) or sent (`outbound`) messages. schema: $ref: '#/components/schemas/MessageDirection' - name: status in: query required: false description: 'Filter sent messages by combined delivery status: `accepted`, `sent`, `delivered`, or `failed`.' schema: type: string enum: - accepted - sent - delivered - failed - name: after in: query required: false description: Filter to messages that occurred at or after this time. Page through results with `starting_after` or `ending_before` instead of this value. schema: type: string format: date-time - name: before in: query required: false description: Filter to messages that occurred at or before this time. Page through results with `starting_after` or `ending_before` instead of this value. schema: type: string format: date-time - name: include in: query required: false description: Set to `extracted_text` to inline each message's extracted plain text. schema: type: string enum: - extracted_text - $ref: '#/components/parameters/PaginationLimit' - $ref: '#/components/parameters/StartingAfter' - $ref: '#/components/parameters/EndingBefore' responses: '200': description: Paginated list of the mailbox's messages. content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessageList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - make - n8n post: operationId: createMailboxMessage summary: Create a message from a mailbox description: Sends a new message from the mailbox's own address and starts a new conversation with it. The request mirrors the plain send request minus `from`, because the mailbox is who the message comes from. We set the RFC 5322 Message-ID, so later replies from the recipients thread back into the conversation automatically. The send is added to the mailbox's remembered messages and returned as the conversation's first message. A mailbox always sends immediately; scheduled sends are unavailable. A suspended mailbox cannot send and returns `403`. tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.mailboxes.messages.create parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EmailMailboxComposeRequest' responses: '202': description: Message accepted for asynchronous delivery and recorded as the first message of a new conversation. headers: Idempotency-Replay: $ref: '#/components/headers/IdempotencyReplay' content: application/json: schema: $ref: '#/components/schemas/EmailThreadMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' x-surfaces: - cli - make - mcp - n8n - sdk /v1/email/mailboxes/{mailbox_id}/labels: parameters: - name: mailbox_id in: path required: true description: Mailbox identifier. Starts with `mbx_`. schema: $ref: '#/components/schemas/MailboxID' get: operationId: listMailboxLabels summary: List a mailbox's labels description: 'Returns the labels available in a mailbox. First, the built-in system labels: - The placements `inbox`, `archive`, `spam`, `blocked`, and `sent`. - `trash`. - `unread`. Then, every custom label currently in use on its conversations and messages. Apply and remove labels through the conversation and message update endpoints. These actions also create and remove custom labels. A custom label exists while at least one message or conversation uses it.' tags: - email-threads security: - BearerAuth: [] - CookieAuth: [] x-audiences: - public - command x-snippet-key: email.mailboxes.labels responses: '200': description: The mailbox's labels. content: application/json: schema: $ref: '#/components/schemas/EmailMailboxLabelList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/Unprocessable' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' x-surfaces: - cli - make - mcp - n8n - sdk components: schemas: EmailThreadHighlights: type: object additionalProperties: false readOnly: true description: 'Matched search fragments for a thread, one array per field the query matched, with the matched terms wrapped in `**`. A field is present only when the query matched it, so the keys that are present tell you which fields produced the hit. Returned only on thread search results. ' properties: subject: type: array items: type: string minLength: 1 description: Matched fragments from the conversation's subject. example: - 'Re: your **order** **4821**' text: type: array items: type: string minLength: 1 description: Matched fragments from a message's body text. example: - confirming your **order** **4821** shipped ErrorBody: type: object additionalProperties: false required: - type - code - name - message - doc_url - request_id properties: type: type: string minLength: 1 description: Broad category for coarse client branching. enum: - auth_error - bad_request_error - billing_error - conflict_error - gone_error - internal_error - misdirected_error - not_found_error - not_implemented_error - payload_too_large_error - permission_error - precondition_error - rate_limit_error - service_unavailable_error - too_early_error - validation_error code: type: string minLength: 1 pattern: ^E\d{5}$ description: Opaque, stable, unique error identifier. Never reused. name: type: string minLength: 1 description: Human-readable slug for log readability. Paired with code, never replaces it. message: type: string minLength: 1 description: Human-readable description. Not stable; clients must not parse it. param: type: string minLength: 1 description: Identifies the offending field. Omitted when not applicable. doc_url: type: string minLength: 1 format: uri description: Stable link to the docs page for this error code. request_id: type: string minLength: 1 description: Request correlation ID for support and troubleshooting. Also returned in the `X-Request-Id` response header. vendor_code: type: string minLength: 1 description: 'Verbatim error code from an external system, such as an SMTP response code or a payment decline code. Present only when the code may help you resolve the error. ' details: type: array description: Per-field validation errors. Present only on validation_error responses. items: $ref: '#/components/schemas/ErrorDetail' remediation: type: string minLength: 1 description: A human-readable next step to resolve this error. Present when a recovery is known. next: type: array description: 'The steps that resolve this error. Perform them in order, re-reading after each; a `wait` or `terminal` step is always last. Present for errors with a well-defined recovery, such as unmet preconditions and conflicts. ' items: $ref: '#/components/schemas/NextAction' EmailLabelsUpdate: type: object additionalProperties: false description: 'Label changes to apply. Labels in `add` are applied and labels in `remove` are taken off; other labels are left untouched. Adding a label that is already present, or removing one that is not, has no effect. System labels express state changes. On a conversation, adding `spam` files it as spam. Adding `archive` files it away without deleting it. Adding `inbox`, or removing `spam`, `blocked`, or `archive`, returns it to the inbox. Removing `unread` marks all retained received messages as read in one call. On a message, adding or removing `unread` flips read state. Adding or removing `trash` moves it to or out of the trash. The API rejects changes that contradict this model. A request cannot add more than one placement label. It cannot add `blocked`, because blocking a sender is a receive-rule decision. Removing `inbox` requires adding a destination. A conversation cannot add `trash` or `unread`; removing `unread` is the mark-all-read shortcut, and `trash` uses the `DELETE` verb. A message cannot use placement labels; move its conversation instead. A sent message cannot use `unread`. Custom labels are 1-64 characters with no commas, control characters, or leading or trailing whitespace. System label names and a small reserved set (`all`, `archived`, `deleted`, `draft`, `drafts`, `flagged`, `important`, `junk`, `muted`, `none`, `outbox`, `pinned`, `read`, `scheduled`, `snoozed`, `starred`) cannot be used as custom labels, in any casing. A conversation or message has at most 20 labels, system labels included. ' properties: add: type: array items: type: string minLength: 1 maxLength: 64 pattern: ^[^,\s](?:[^,]*[^,\s])?$ maxItems: 20 description: Labels to apply. example: - urgent remove: type: array items: type: string minLength: 1 maxLength: 64 pattern: ^[^,\s](?:[^,]*[^,\s])?$ maxItems: 20 description: Labels to take off. example: - pending EmailThread: type: object additionalProperties: false description: 'A conversation in a mailbox. It groups every message in both directions, the mail the mailbox received and the replies it sent, and it holds the conversation''s read state, labels, and participant list. A message is retained until it is trashed or ages past the mailbox''s retention tier. Only retained messages count toward the totals below. ' required: - id - mailbox_id - channel - contact_id - subject - participants - message_count - unread_count - last_message_at - last_direction - labels - created_at - updated_at properties: id: readOnly: true $ref: '#/components/schemas/ThreadID' description: Thread ID. mailbox_id: readOnly: true $ref: '#/components/schemas/MailboxID' description: Mailbox this conversation belongs to. channel: type: string readOnly: true minLength: 1 description: Channel this conversation lives on. Always `email`. example: email contact_id: oneOf: - $ref: '#/components/schemas/ContactID' - type: 'null' description: Contact linked to this conversation, or null when none is linked. subject: type: - string - 'null' readOnly: true description: Subject of the conversation, taken from its first message. Null when that message had no subject. example: 'Re: Your order' participants: type: array readOnly: true items: type: string format: email description: Addresses that appear on the retained messages in this conversation, including the mailbox's own address. message_count: type: integer readOnly: true minimum: 0 description: Number of retained messages in this conversation, both directions. unread_count: type: integer readOnly: true minimum: 0 description: Number of retained received messages that are still unread. Spam and blocked mail is not counted. last_message_at: type: string format: date-time minLength: 1 readOnly: true description: When the most recent retained message in this conversation was received or sent. last_direction: type: string enum: - inbound - outbound minLength: 1 readOnly: true description: 'Direction of the most recent message: `inbound` for a received message, `outbound` for a sent one.' labels: type: array items: type: string minLength: 1 maxLength: 64 maxItems: 20 description: 'Labels on this conversation. Exactly one system placement label is always present, set by the message that started the conversation: - `inbox`: The conversation is in the inbox. - `archive`: The conversation was filed away and is done for now. - `spam`: The conversation''s opening message is filed in Spam. - `blocked`: The conversation''s opening message was rejected by the mailbox''s receive policy or rules. Move a conversation by updating its labels. Add `spam` to file it as spam, add `archive` to clean it out of the inbox, and add `inbox`, or remove `spam`, `blocked`, or `archive`, to bring it back. An archived conversation returns to the inbox by itself when a new message arrives. Custom labels share the same list, and a conversation has at most 20 labels in total. ' example: - inbox - urgent created_at: type: string format: date-time minLength: 1 readOnly: true description: When the thread was created. updated_at: type: string format: date-time minLength: 1 readOnly: true description: When the thread last changed. highlights: $ref: '#/components/schemas/EmailThreadHighlights' readOnly: true description: 'Matched search fragments, keyed by the field that matched. Returned only by thread search. Omitted when listing threads. ' EmailThreadMessageList: allOf: - type: object required: - data properties: data: type: array items: $ref: '#/components/schemas/EmailThreadMessage' - $ref: '#/components/schemas/_ListEnvelope' MessageDirection: type: string enum: - outbound - inbound description: Whether a message was sent from the workspace (`outbound`) or received by it (`inbound`). EmailMailboxComposeRequest: type: object additionalProperties: false description: 'A new message sent from a mailbox, starting a new conversation. Mirrors the plain send request without `from`, because the mailbox is who the message comes from, and without `scheduled_at`, because a mailbox sends immediately. We set the RFC 5322 Message-ID so replies thread back into this conversation. At least one of `html` or `text` must be provided. ' required: - to - subject properties: to: type: array items: $ref: '#/components/schemas/EmailAddressInput' minItems: 1 maxItems: 50 description: Primary recipients. Each entry is a plain email string, an RFC 5322 mailbox string (`Jane `), or an object with an optional display name. cc: type: array items: $ref: '#/components/schemas/EmailAddressInput' maxItems: 50 description: CC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (`Jane `), or an object with an optional display name. bcc: type: array items: $ref: '#/components/schemas/EmailAddressInput' maxItems: 50 description: BCC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (`Jane `), or an object with an optional display name. subject: type: string minLength: 1 maxLength: 998 description: Message subject line. html: type: string maxLength: 524288 description: HTML body. At least one of html or text must be provided. text: type: string maxLength: 524288 description: Plain-text body. At least one of html or text must be provided. reply_to: type: array items: $ref: '#/components/schemas/EmailAddressInput' minItems: 1 maxItems: 25 description: 'Reply-To addresses. When omitted, the mailbox''s `default_reply_to` applies (replies then come back to the mailbox itself). ' attachments: type: array items: $ref: '#/components/schemas/EmailAttachment' maxItems: 20 description: 'File attachments. The send is rejected when the estimated generated message size exceeds 20 MB (bodies plus all attachments after base64 encoding). Keep total raw attachment content at or below 15 MB for reliable headroom. Attachment metadata stays on the message''s `attachment_manifest`, and the bytes are downloadable for the mailbox''s retention tier. ' tags: type: array items: $ref: '#/components/schemas/Tag' maxItems: 20 description: 'Structured `{name, value}` labels for filtering and analytics on the sent-message log. Cap: 20 tags per send. ' metadata: type: object additionalProperties: true description: 'Arbitrary JSON object stored on the send and echoed in webhook payloads. Cap: 2 KB serialized. ' category: $ref: '#/components/schemas/EmailMessageCategory' default: transactional example: to: - delivered@messagebird.dev subject: Your quote text: Hi, here is the quote you asked for. EmailThreadMessageAttachment: type: object additionalProperties: false description: 'Attachment metadata on a conversation message. Both the metadata and the attachment bytes stay available for the mailbox''s retention tier. ' required: - id - filename - content_type - size properties: id: type: string readOnly: true minLength: 1 description: Attachment ID, used to download the attachment bytes. example: rea_01krdgeqcxet5s7t44vh8rt9mg filename: type: - string - 'null' readOnly: true description: Original filename, or null when the attachment had none. example: invoice.pdf content_type: type: - string - 'null' readOnly: true description: MIME content type, or null when it could not be determined. example: application/pdf size: type: integer readOnly: true minimum: 0 description: Attachment size in bytes. EmailThreadMessage: type: object additionalProperties: false description: 'A message in a mailbox conversation, either direction. Message metadata, extracted text, and attachment bytes stay readable for the mailbox''s retention tier. The body and raw MIME are available through the body and raw endpoints for 30 days after the message occurred. ' required: - id - direction - channel - thread_id - from - to - cc - delivered_to - subject - preview - labels - status - authentication - spf_pass - dkim_pass - dmarc_pass - attachment_count - attachment_manifest - reference_ids - contact_id - recipients - purge_at - source - occurred_at properties: id: type: string readOnly: true minLength: 1 pattern: ^(rem|em)_[0-9a-hjkmnp-tv-z]{26}$ description: 'Message ID. Received messages have a `rem_` ID, sent messages an `em_` ID: the same IDs used by the received-message and sent-message logs. ' example: rem_01krdgeqcxet5s7t44vh8rt9mg direction: type: string enum: - inbound - outbound minLength: 1 readOnly: true description: Which way the message went. `inbound` means you received it, `outbound` means you sent it. channel: type: string readOnly: true minLength: 1 description: Channel this message lives on. Always `email`. example: email thread_id: readOnly: true $ref: '#/components/schemas/ThreadID' description: Conversation this message belongs to. from: type: string format: email readOnly: true minLength: 1 description: Sender address. to: type: array readOnly: true items: type: string format: email description: Recipient addresses on the To line. cc: type: array readOnly: true items: type: string format: email description: Recipient addresses on the Cc line. Empty when the message had none. delivered_to: type: - string - 'null' format: email readOnly: true description: 'Address the message was actually delivered to, when it differs from the mailbox address (for example mail routed in from another address). Null for sent messages and for mail addressed directly to the mailbox. ' subject: type: - string - 'null' readOnly: true description: Message subject. Null when the message had no subject. example: 'Re: Your order' preview: type: - string - 'null' readOnly: true description: Short plain-text preview of the message body. extracted_text: type: - string - 'null' readOnly: true description: 'Plain-text content of the message with quoted history stripped. Readable for the mailbox''s full retention tier, in both directions. Always present when fetching a single message. On list endpoints it is included only when the request sets `include=extracted_text`. Null when no text could be extracted. ' labels: type: array items: type: string minLength: 1 maxLength: 64 maxItems: 20 description: 'Labels on this message. A received message always has exactly one placement label: - `inbox`: Accepted mail. - `archive`: The message''s conversation was filed away. - `spam`: The message is filed in Spam. - `blocked`: The message was rejected by the mailbox''s receive policy or rules. A received message also has `unread` until it is read. `trash` marks a message in the trash, in either direction. Custom labels share the same list, and a message has at most 20 labels in total. ' example: - inbox - unread status: type: - string - 'null' readOnly: true description: 'Aggregate delivery status of a sent message: - `accepted`: Accepted for sending. - `sent`: Handed off to the provider. - `delivered`: All attempted recipients delivered. - `failed`: Terminal failure. Null for received messages. ' recipients: type: - array - 'null' readOnly: true items: $ref: '#/components/schemas/EmailThreadMessageRecipient' description: 'Terminal per-recipient delivery outcomes of a sent message, filled in as each one becomes known and kept for the mailbox''s full retention tier. Null for received messages and before any recipient reaches a terminal state. Per-recipient event detail lives on the sent-message log (`source`) for 30 days. ' authentication: type: - string - 'null' enum: - pass - fail - unknown - null readOnly: true description: 'DMARC result for the domain in the received message''s `From` header. - `pass`: SPF or DKIM passed and aligned with that domain. - `fail`: DMARC was evaluated and did not pass. - `unknown`: no trustworthy verdict is available. This follows `dmarc_pass` and does not verify a particular person. The receiving provider currently supplies no DMARC result, so received messages report `unknown`. Null for sent messages. This field is readable for the mailbox''s full retention tier, so the verdict is still available after the 30-day received-message log has expired. ' spf_pass: type: - boolean - 'null' readOnly: true description: Whether the receiving provider reports that SPF authorized the envelope sender for the sending server. A soft failure is `false`. Missing, neutral and inconclusive results are `null`. Sent messages have `null` results. Kept for the mailbox retention tier. dkim_pass: type: - boolean - 'null' readOnly: true description: Whether the receiving provider verified a DKIM signature. A passing signature makes this `true` even when another signature fails. Missing signatures and inconclusive verification results are `null`. Sent messages have `null` results. Kept for the mailbox retention tier. dmarc_pass: type: - boolean - 'null' readOnly: true description: Whether SPF or DKIM passed and aligned with the domain in the message's `From` header. The receiving provider currently supplies no DMARC result, so this is `null`. Sent messages have `null` results. Kept for the mailbox retention tier. purge_at: type: string format: date-time minLength: 1 readOnly: true description: 'Scheduled permanent-deletion time. This is the end of the mailbox''s retention tier, moved to no more than 30 days in the future while the message is in the trash. Restore a trashed message before then with `PATCH {"labels": {"remove": ["trash"]}}`. ' attachment_count: type: integer readOnly: true minimum: 0 description: Number of attachments on the message. attachment_manifest: type: array readOnly: true items: $ref: '#/components/schemas/EmailThreadMessageAttachment' description: 'Attachment metadata (filename, content type, size). Both the metadata and the attachment bytes stay available for the mailbox''s retention tier. ' reference_ids: type: array readOnly: true items: type: string description: RFC 5322 References header entries used to thread the conversation. contact_id: oneOf: - $ref: '#/components/schemas/ContactID' - type: 'null' description: Contact linked to this message, or null when none is linked. source: readOnly: true $ref: '#/components/schemas/EmailThreadMessageSource' occurred_at: type: string format: date-time minLength: 1 readOnly: true description: When the message was received or accepted for sending. MailboxID: type: string minLength: 1 pattern: ^mbx_[0-9a-hjkmnp-tv-z]{26}$ example: mbx_01krdgeqcxet5s7t44vh8rt9mg ContactID: type: string minLength: 1 pattern: ^con_[0-9a-hjkmnp-tv-z]{26}$ example: con_01krdgeqcxet5s7t44vh8rt9mg EmailThreadMessageUpdateRequest: type: object additionalProperties: false description: Changes to apply to a conversation message. Omitted fields are left unchanged. properties: labels: $ref: '#/components/schemas/EmailLabelsUpdate' contact_id: oneOf: - $ref: '#/components/schemas/ContactID' - type: 'null' description: Contact to link this message to, or null to unlink the current contact. ThreadID: type: string minLength: 1 pattern: ^thr_[0-9a-hjkmnp-tv-z]{26}$ example: thr_01krdgeqcxet5s7t44vh8rt9mg EmailThreadUpdateRequest: type: object additionalProperties: false description: Changes to apply to a thread. Omitted fields are left unchanged. properties: labels: $ref: '#/components/schemas/EmailLabelsUpdate' contact_id: oneOf: - $ref: '#/components/schemas/ContactID' - type: 'null' description: Contact to link this conversation to, or null to unlink the current contact. EmailMessageCategory: type: string minLength: 1 enum: - marketing - transactional description: 'Content classification, which controls suppression policy: - `marketing`: Blocks on all suppression reasons. - `transactional`: Allows delivery through complaint and unsubscribe suppressions, for receipts, password resets, and similar operational mail. ' _ListEnvelope: type: object required: - next_cursor - prev_cursor - refresh_cursor properties: next_cursor: type: - string - 'null' description: Cursor for the next page. Pass back as `starting_after` to advance forward. `null` when no next page exists. example: eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE0OjAzOjEwWlwiIiwiaSI6IjAxOTJmM2IxLTRjN2UtN2EyYi05ZDYxLThmM2E1YzJlN2I0MCJ9 prev_cursor: type: - string - 'null' description: Cursor for the previous page. Pass back as `ending_before` to step backward. `null` when no previous page exists. example: null refresh_cursor: type: - string - 'null' description: Refresh anchor, the first row of this response. Pass back as `ending_before` to fetch what precedes it in the current sort order. On a newest-first sort those are the items that have appeared since; on any other sort they are the items that sort earlier, so refreshing such a list means re-fetching it instead. Non-`null` whenever `data` is non-empty; `null` only on an empty page. Distinct from `prev_cursor`. example: eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE2OjQyOjAxWlwiIiwiaSI6IjAxOTJmM2IxLTllMDQtN2NkMy1iODE3LTJhNmY0ZDFjOGUwOSJ9 EmailThreadMessageSource: type: object additionalProperties: false description: 'Link to the message''s entry in the received-message or sent-message log, which has delivery analytics such as per-recipient events. Log entries expire 30 days after the message occurred. ' required: - resource - available_until properties: resource: type: string readOnly: true minLength: 1 description: API path of the log entry for this message. example: /v1/email/inbound-messages/rem_01krdgeqcxet5s7t44vh8rt9mg available_until: type: string format: date-time minLength: 1 readOnly: true description: When the log entry (and the message's body and raw MIME) expires. ErrorDetail: type: object additionalProperties: false required: - param - message properties: param: type: string minLength: 1 description: 'Dotted field path, such as `to[0].email`, `subject`, or `.`. When the request was rejected for a query parameter the endpoint does not declare, this carries that parameter''s name instead of a field path. ' message: type: string minLength: 1 description: What is wrong with this field. EmailAddressInput: description: 'A sender or recipient address. Accepts a plain email string (`jane@acme.com`), an RFC 5322 mailbox string with an embedded display name (`Jane Doe `), or an object carrying the address and an optional display name. All forms can be mixed freely within one request. Responses always return the object form. ' oneOf: - type: string minLength: 5 maxLength: 998 pattern: ^[^\r\n]+$ title: Email string description: Email address, optionally in RFC 5322 mailbox form with an embedded display name. example: Jane Doe - $ref: '#/components/schemas/EmailAddress' Tag: type: object additionalProperties: false required: - name - value description: 'Structured key/value label attached to a message or a call. Use tags for low-cardinality filtering dimensions (category, experiment ID, template ID); they surface in the list filter of whatever carries them. On a message they also surface in the event log and in webhook payloads, and a message can carry `metadata` beside them for arbitrary per-send context that does not need to be filterable. A call has none of those three: its tags are set on the wire when the call is placed, and the call record is the one place you read them back. Whatever carries the tags defines how many it may have. Tag names are unique: a send that repeats one is rejected, and on a call the first instance of a name wins. ' properties: name: type: string minLength: 1 maxLength: 32 pattern: ^[A-Za-z0-9_-]+$ description: 'Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters. ' example: category value: type: string minLength: 1 maxLength: 64 pattern: ^[A-Za-z0-9_-]+$ description: 'Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters. ' example: welcome NextAction: type: object additionalProperties: false required: - kind - description properties: kind: type: string minLength: 1 x-extensible-enum: - operation - external - wait - terminal description: "What you do about this step.\n\n- `operation`: call the operation named in `operation`, then\n read again.\n- `external`: act somewhere this API does not reach, then read\n again.\n- `wait`: nothing is asked of you, so read again later.\n- `terminal`: nothing you do resolves this, so stop retrying.\n\nTolerate a value you do not recognize: show the `description` and\noffer no action.\n" description: type: string minLength: 1 description: A short, human-readable label for the step, suitable for display. operation: type: string minLength: 1 description: 'The operationId to call. Present only when `kind` is `operation`. The operation''s own schema says how to call it; this says only which one, and what to address it with. ' params: type: object additionalProperties: type: string minLength: 1 description: 'The parameters that address the operation, by name: `{"sender_id": "…"}` for an operation on `/v1/sms/senders/{sender_id}/requirements`. A parameter the operation takes in its query string is given the same way, so an operation addressed as `?subject_id=` carries `{"subject_id": "…"}`. Every parameter the call needs is here, whether its value came from the thing you were acting on or is fixed for this step, so you can make the call from this object alone. Present only when `kind` is `operation` and the operation names a subject. A request body, when the operation takes one, is described by the operation''s own schema and never appears here. ' url: type: string format: uri description: 'A URL to open. Present only when `kind` is `external`, and only when the step has one. An external step whose `description` says to go and do something with no URL to open is normal. ' Error: type: object additionalProperties: false required: - error properties: error: $ref: '#/components/schemas/ErrorBody' EmailMailboxLabel: type: object additionalProperties: false description: One label available in a mailbox. required: - name - type properties: name: type: string readOnly: true minLength: 1 maxLength: 64 description: The label name, as it appears on conversations and messages. example: inbox type: type: string readOnly: true minLength: 1 enum: - system - custom description: '`system` labels are the built-in placements a message can be in: - Inbox. - Archive. - Spam. - Blocked. - Sent. - Trash. - Unread. `custom` labels are the workspace''s own tags.' EmailThreadMessageAttachmentList: type: object additionalProperties: false description: The attachments on a conversation message. required: - data properties: data: type: array items: $ref: '#/components/schemas/EmailThreadMessageAttachment' EmailThreadMessageBody: type: object additionalProperties: false description: 'The original rendered body of a conversation message. Available for 30 days after the message occurred. After that, the endpoint returns `410 Gone`, but the message''s extracted text stays readable on the message itself. ' required: - html - text properties: html: type: - string - 'null' description: The HTML body of the message, or null when the message had no HTML part. text: type: - string - 'null' description: The plain-text body of the message, or null when the message had no text part. EmailAttachment: type: object additionalProperties: false required: - filename - content description: 'A file attached to an email. Put the base64-encoded bytes in `content` and the recipient-facing name in `filename`. To show an image inline, set `content_id` and reference it from the HTML body with ``. The generated message is limited to 20 MB across the HTML body, text body, attachments, and inline images after base64 and MIME encoding. Keep raw attachment content at or below 15 MB to leave room for encoding and the body. Batch sends apply the same 20 MB limit to each message and to the full request body. Executable and script content types are rejected. ' properties: filename: type: string minLength: 1 maxLength: 255 description: The name the recipient sees on the attachment. example: invoice.pdf content: type: string format: byte minLength: 1 description: Base64-encoded file bytes. The encoded value and MIME wrapping count toward the 20 MB message limit. content_type: type: string description: The file's MIME type. If omitted, the API infers it from the extension in `filename`. The API rejects executable and script types based on this value. example: application/pdf content_id: type: string minLength: 1 maxLength: 128 pattern: ^[A-Za-z0-9._-]+$ description: An RFC 2392 Content-ID for an inline file. Reference it from the HTML body with ``. Omit it to send a downloadable attachment. example: invoice-logo EmailThreadMessageRecipient: type: object additionalProperties: false description: 'One recipient''s terminal delivery outcome on a sent conversation message, recorded once the outcome becomes known. ' required: - address - status properties: address: type: string format: email readOnly: true minLength: 1 description: Recipient address. status: type: string enum: - delivered - failed minLength: 1 readOnly: true description: 'Terminal outcome: `delivered`, or `failed` (bounce or provider rejection).' EmailMailboxLabelList: type: object additionalProperties: false description: The labels available in a mailbox. required: - data properties: data: type: array items: $ref: '#/components/schemas/EmailMailboxLabel' EmailThreadMessageReplyRequest: type: object additionalProperties: false description: 'A reply to a conversation message. Recipients are derived from the message being replied to: its Reply-To address when present, otherwise its From address. Set `reply_all` to also include the original To and Cc recipients (minus the mailbox''s own address). The subject and threading headers are set automatically. At least one of `html` or `text` must be provided. ' properties: html: type: string maxLength: 524288 description: HTML body of the reply. At least one of html or text must be provided. text: type: string maxLength: 524288 description: Plain-text body of the reply. At least one of html or text must be provided. reply_all: type: boolean default: false description: Also send the reply to the original To and Cc recipients, minus the mailbox's own address. tags: type: array items: $ref: '#/components/schemas/Tag' maxItems: 20 description: 'Structured `{name, value}` labels for filtering and analytics on the sent-message log. Cap: 20 tags per send. ' metadata: type: object additionalProperties: true description: 'Arbitrary JSON object stored on the send and echoed in webhook payloads. Cap: 2 KB serialized. ' category: $ref: '#/components/schemas/EmailMessageCategory' default: transactional attachments: type: array items: $ref: '#/components/schemas/EmailAttachment' maxItems: 20 description: 'File attachments to include with the reply. The send is rejected when the estimated generated message size exceeds 20 MB (bodies plus all attachments after base64 encoding). Keep total raw attachment content at or below 15 MB for reliable headroom. Attachment metadata stays on the message''s `attachment_manifest`, and the bytes are downloadable for the mailbox''s retention tier. ' example: text: Thanks, confirming we received your request. EmailThreadList: allOf: - type: object required: - data properties: data: type: array items: $ref: '#/components/schemas/EmailThread' - $ref: '#/components/schemas/_ListEnvelope' EmailAddress: type: object additionalProperties: false description: An email address with an optional display name. required: - email properties: email: type: string format: email minLength: 5 description: Email address. example: jane@acme.com name: type: string minLength: 1 maxLength: 256 pattern: ^[^\r\n]+$ description: Display name shown alongside the address in mail clients. example: Jane Doe parameters: PaginationLimit: name: limit in: query required: false description: Maximum number of items to return per page. schema: type: integer minimum: 1 maximum: 100 default: 25 IdempotencyKey: name: Idempotency-Key in: header required: false description: "Client-supplied key. On operations supporting request deduplication, a retained\nresponse is replayed for duplicate requests with the same key within the\nidempotency window (3 hours by default). This protection requires a workspace,\norganization, or staff-account scope. User-only and unauthenticated operations,\nstreams, and operations with a separate replay contract do not use this\nresponse replay.\n\nOn a supported operation, if idempotency protection is unavailable before execution, the API returns\n`503 IdempotencyUnavailable` (E01033) without executing this attempt. Retry with\nbackoff using the same key and request. An operation that takes effect before\nits response is retained can still execute again on retry.\n\nTwo distinct 409 errors signal misuse:\n\n- `request_in_progress` (E01004): The same key is currently being\n processed by a concurrent request. Wait briefly and retry. The lock expires within 30 seconds.\n- `idempotency_key_reuse` (E01005): The same key has already completed\n against a different request body or method. Generate a new key.\n\nRecommended key format is `/` (for example `welcome-user/usr_abc123`).\n" schema: type: string maxLength: 255 StartingAfter: name: starting_after in: query required: false description: Cursor from the `next_cursor` field of a previous list response. Returns items immediately after the cursor position in the current sort order. schema: type: string EndingBefore: name: ending_before in: query required: false description: Cursor from the `prev_cursor` or `refresh_cursor` field of a previous list response. Returns items immediately before the cursor position in the current sort order. `prev_cursor` returns the preceding page. `refresh_cursor` anchors at the first row of that response, which on a newest-first sort is how to fetch the items that have appeared since. schema: type: string responses: InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' PaymentRequired: description: Insufficient balance content: application/json: schema: $ref: '#/components/schemas/Error' RateLimited: description: Rate limit exceeded headers: RateLimit: $ref: '#/components/headers/RateLimit' RateLimit-Policy: $ref: '#/components/headers/RateLimit-Policy' Retry-After: $ref: '#/components/headers/RetryAfter' content: application/json: schema: $ref: '#/components/schemas/Error' Forbidden: description: Insufficient permissions content: application/json: schema: $ref: '#/components/schemas/Error' ServiceUnavailable: description: 'The service is temporarily unavailable. If `Retry-After` is present, wait for that delay before retrying; otherwise, retry with exponential backoff. Reuse the same idempotency key and request when retrying a mutation. ' headers: Retry-After: $ref: '#/components/headers/RetryAfter' content: application/json: schema: $ref: '#/components/schemas/Error' Unprocessable: description: 'The request has invalid field values, violates a business rule, or carries a query parameter the endpoint does not declare. Field validation errors use `type: validation_error` and include the affected fields in `details`. Business-rule errors identify the failed rule in `type`. ' content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' Gone: description: The resource existed but is no longer available. content: application/json: schema: $ref: '#/components/schemas/Error' BadRequest: description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Authentication required content: application/json: schema: $ref: '#/components/schemas/Error' Conflict: description: Resource conflict content: application/json: schema: $ref: '#/components/schemas/Error' headers: RetryAfter: description: 'Number of seconds to wait before retrying the request. ' schema: type: integer minimum: 0 example: 35 IdempotencyReplay: description: The API includes this header when it replays the response for an earlier request that used the same `Idempotency-Key`. The API does not process the request again. schema: type: string enum: - 'true' RateLimit: description: 'Remaining capacity for the request''s rate-limit policy as an IETF Structured Field. Format: `"";r=;t=`. ' schema: type: string example: '"email_send";r=842;t=35' RateLimit-Policy: description: 'Effective quota for the request''s rate-limit policy as an IETF Structured Field. Format: `"";q=;w=`. ' schema: type: string example: '"email_send";q=1000;w=60' securitySchemes: BearerAuth: type: http scheme: bearer description: 'Pass the API key as a bearer token in the `Authorization` header. Keys use the format `bk_{region}_*`. The prefix identifies the region and selects the API endpoint. Official Bird SDKs and the CLI derive the region from the key. ' CookieAuth: type: apiKey in: cookie name: bird_session description: 'Session cookie set after signing in to the Bird dashboard. The cookie value is an opaque session token; no session data is stored in the cookie itself. ' RealtimeKey: type: apiKey in: header name: X-Realtime-Key description: 'The Realtime app key. Together with `X-Realtime-Secret`, it authenticates a request to the Realtime API in addition to the workspace credential. Both values come from the app''s credentials and must belong to the calling workspace. Official Bird SDKs accept the pair as client configuration. ' RealtimeSecret: type: apiKey in: header name: X-Realtime-Secret description: 'The Realtime app secret paired with `X-Realtime-Key`. The API returns the secret only when the key is created and does not store it. Create a new key and revoke the current key if you lose the secret. Official Bird SDKs accept the pair as client configuration. '