{
  "openapi": "3.1.0",
  "info": {
    "title": "Emelia Inbox API",
    "version": "1.0.0",
    "summary": "Read, search, classify and send the emails of the Emelia unified inbox.",
    "description": "The Emelia Inbox API is the programmatic side of the Emelia unified inbox (the Inbox tab of Emelia, https://v3.emelia.io/inbox). It lets your code or an AI agent list, search and read the emails of the mailboxes connected to Emelia, organise them (labels, AI label rules, saved views, inbox filters), prepare drafts for a human to review, send replies and forward emails automatically.\n\nDocumentation and guides: https://docs.emelia.io\n\n## Base URL and key\n\nThe Inbox API is served under `https://api.emelia.io/inbox/api/v1` and takes the same API key as the Emelia API: the 48 character key created in Settings, API & Webhooks (https://v3.emelia.io/settings/api).\n\n| | Emelia API | Emelia Inbox API |\n| --- | --- | --- |\n| Base URL | https://api.emelia.io | https://api.emelia.io/inbox/api/v1 |\n| Scope | campaigns, contacts, LinkedIn, enrichment | emails of the inbox |\n| Errors | `{ \"error\", \"code\"? }` | `{ \"code\", \"error\", \"details\"? }` |\n\n## Authentication\n\n`Authorization: <your API key>` on every call (a `Bearer ` prefix is accepted). The key opens the inbox of its Emelia account, sending included. The workspace comes from the key: no path carries a workspace id, so a key can only reach its own data. An unknown or disabled key gets `401 INVALID_API_KEY`; disabling a key in Emelia can take up to 5 minutes to apply to this API. A suspended workspace (Emelia subscription expired) gets `403 WORKSPACE_SUSPENDED`.\n\n## Quotas\n\nCounted per Emelia account (all its keys share them), with a sliding one minute window and a calendar month in UTC, separately from the quotas of the Emelia API: 60 requests per minute, 10,000 requests per month and 1 active webhook.\n\nOne request costs 1 unit; `POST /emails/bulk` costs one unit per id, checked against the per minute limit too (so at most 60 ids per batch). Units are counted when the request passes the counters, even if it then fails validation. Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `X-RateLimit-Quota`, `X-RateLimit-Quota-Remaining` and `X-RateLimit-Quota-Reset`, except on 401 and `403 WORKSPACE_SUSPENDED`, and on `429 RATE_LIMIT_EXCEEDED` (only the three per minute headers plus `Retry-After`).\n\n## AI and Emelia credits\n\nAI work triggered by this API is paid with Emelia credits: classification of each incoming email while the workspace has at least one AI label rule, and auto-drafts.\n\n## Conventions\n\n- JSON in and out, body limited to 256 KB. Dates are ISO 8601 UTC. Ids are opaque strings.\n- Errors: `{ \"code\", \"error\", \"details\"? }`; branch on `code`. A resource of another workspace answers 404, never 403.\n- Pagination: only `GET /emails` and `GET /emails/search` (cursor). Other lists are returned in full, except `GET /drafts` (limit only) and rule logs (50).\n- Idempotency: `Idempotency-Key` on the creating POST routes, stored 24 hours, scoped to the workspace.\n- Every read is cancelled after 10 seconds (`408 QUERY_TIMEOUT`).",
    "contact": {
      "name": "Emelia support",
      "email": "contact@emelia.io",
      "url": "https://docs.emelia.io"
    }
  },
  "servers": [
    {
      "url": "https://api.emelia.io/inbox/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Emails",
      "description": "List, search, read, mark, trash and label emails."
    },
    {
      "name": "Drafts and sending",
      "description": "Prepare drafts for a human, or send immediately."
    },
    {
      "name": "Mailboxes and signatures",
      "description": "Read only reference data: connected mailboxes and signatures."
    },
    {
      "name": "Labels",
      "description": "Manual labels. AI labels are listed here but managed through AI label rules."
    },
    {
      "name": "AI label rules",
      "description": "AI labels with a plain language condition, auto-draft and auto-reply."
    },
    {
      "name": "Views",
      "description": "Saved filter trees, applied with `GET /emails?viewId=`."
    },
    {
      "name": "Inbox filters",
      "description": "Hide matching emails from the main inbox without moving them."
    },
    {
      "name": "Auto-forward rules",
      "description": "Forward matching incoming emails automatically."
    },
    {
      "name": "Webhooks",
      "description": "Events pushed to your endpoint. Not manageable with an API key."
    }
  ],
  "paths": {
    "/emails": {
      "get": {
        "operationId": "listEmails",
        "tags": [
          "Emails"
        ],
        "summary": "List emails",
        "description": "Returns a page of emails, most recent first (by date, then by id). Use it to browse a mailbox, a folder, a saved view, or the emails hidden from the main inbox. For a keyword lookup, prefer `GET /emails/search`.\n\nHow the criteria combine:\n- Without `folderType`, every folder is listed, SPAM and TRASH included. Pass `folderType=INBOX` to read incoming mail only.\n- With `folderType=INBOX` and no `viewId`, emails hidden by inbox filters (`/filters`) or by AI label rules with `hideFromInbox: true` are left out. `filtered=only` returns exactly those hidden INBOX emails instead.\n- `mailboxId`, `folderType`, `viewId` and `filters` combine with AND.\n- Known issue: when `search` has 2 characters or more, the request is served by the search engine, which ignores `filters`, `filtered=only` and the inbox exclusion, and ranks results by relevance. Do not combine `search` with `filters` until this is fixed.\n- Known issue: an unknown `viewId` returns `500 INTERNAL_ERROR` instead of a 404.\n\nPagination: pass `nextCursor` back as `cursor`. Stop on `hasMore: false`. `nextCursor` is not null on the last non empty page, only on an empty page.\n\nThe body is never included: fetch it with `GET /emails/{emailId}/body`. Every read is cancelled server side after 10 seconds (`408 QUERY_TIMEOUT`).",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxIdQuery"
          },
          {
            "$ref": "#/components/parameters/FolderType"
          },
          {
            "name": "viewId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Apply a saved view (ids from `GET /views`). The view filter tree and its mailbox restriction are combined with the other criteria. An unknown id currently returns 500 (bug).",
            "example": "cmvwacme0000000000000001"
          },
          {
            "name": "filtered",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "only"
              ]
            },
            "description": "`only` lists the INBOX emails hidden by inbox filters and by `hideFromInbox` AI labels (the app's \"Filtered emails\"). Any other value is rejected with 400. Forces the INBOX folder."
          },
          {
            "name": "filters",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "contentMediaType": "application/json"
            },
            "description": "JSON encoded filter tree (see the `FilterNode` schema). Bounds: 8192 bytes raw, 5 levels, 50 conditions in total, 500 characters per value. Unknown fields or operators are rejected. Known issue: an invalid date value is silently ignored instead of rejected.",
            "example": "{\"id\": \"c1\", \"label\": \"sender_domain\", \"type\": \"equals\", \"value\": \"example.com\"}"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Optional keyword. Shorter than 2 characters after trimming: ignored. Longer than 200: 400. When present, see the known bug above (filters are dropped)."
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of emails.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "cmemacme0000000000000001",
                      "mailboxId": "cmbxacme0000000000000001",
                      "folderId": "cmfdacme0000000000000001",
                      "messageId": "<CAJacme.0001@mail.example.com>",
                      "threadId": "18c2acme0001",
                      "subject": "Re: Partnership with Acme",
                      "from": {
                        "email": "jane.roe@example.com",
                        "name": "Jane Roe"
                      },
                      "to": [
                        {
                          "email": "john.doe@acme.com",
                          "name": null
                        }
                      ],
                      "cc": [],
                      "date": "2026-10-08T09:12:44.000Z",
                      "snippet": "Thanks John, could we schedule a call next week?",
                      "isRead": false,
                      "isStarred": false,
                      "isDraft": false,
                      "waitingForReply": false,
                      "hasAttachments": true,
                      "attachments": [
                        {
                          "filename": "brief.pdf",
                          "size": 48213,
                          "mimeType": "application/pdf"
                        }
                      ],
                      "tags": [
                        {
                          "id": "cmtgacme0000000000000002",
                          "name": "Interested",
                          "color": "#2563eb",
                          "isAiLabel": true
                        }
                      ],
                      "inReplyTo": "<20261008091500.acme01@acme.com>",
                      "references": [
                        "<20261008091500.acme01@acme.com>"
                      ]
                    }
                  ],
                  "nextCursor": "2026-10-08T09:12:44.000Z|cmemacme0000000000000001",
                  "hasMore": true
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: unknown `folderType`, `filtered` other than `only`, invalid or too large `filters`, or `search` longer than 200 characters. `details` names the parameter or the bound.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "folderType": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Unknown folder type.",
                      "details": {
                        "folderType": [
                          "Expected one of INBOX, SENT, DRAFTS, SPAM, TRASH"
                        ]
                      }
                    }
                  },
                  "filtersTooDeep": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Filter nesting is too deep, max 5 levels.",
                      "details": {
                        "maxDepth": 5
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/QueryTimeout"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/emails/search": {
      "get": {
        "operationId": "searchEmails",
        "tags": [
          "Emails"
        ],
        "summary": "Search emails by keyword",
        "description": "Full text style search on the subject, the sender name and address, the preview snippet and the recipient addresses. The full body is not searched. Matching is a case insensitive substring match.\n\nRanking: subject match first (with a bonus when the subject starts with the term), then sender (bonus on an exact sender match), snippet, recipients; ties are broken by date then id, most recent first.\n\nWithout `folderType`, every folder is searched. The inbox filters do not apply here: hidden emails can be returned.\n\nThe cursor of this endpoint has its own format (it starts with `s|`); pass it back unchanged. An unreadable cursor is ignored and the first page is returned again. Stop on `hasMore: false`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 200
            },
            "description": "Search term, 2 to 200 characters after trimming. Too short or missing: 400 with `details.q`. Too long: 400 with `details.search`.",
            "example": "partnership"
          },
          {
            "$ref": "#/components/parameters/MailboxIdQuery"
          },
          {
            "$ref": "#/components/parameters/FolderType"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of matching emails.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "cmemacme0000000000000001",
                      "mailboxId": "cmbxacme0000000000000001",
                      "folderId": "cmfdacme0000000000000001",
                      "messageId": "<CAJacme.0001@mail.example.com>",
                      "threadId": "18c2acme0001",
                      "subject": "Re: Partnership with Acme",
                      "from": {
                        "email": "jane.roe@example.com",
                        "name": "Jane Roe"
                      },
                      "to": [
                        {
                          "email": "john.doe@acme.com",
                          "name": null
                        }
                      ],
                      "cc": [],
                      "date": "2026-10-08T09:12:44.000Z",
                      "snippet": "Thanks John, could we schedule a call next week?",
                      "isRead": false,
                      "isStarred": false,
                      "isDraft": false,
                      "waitingForReply": false,
                      "hasAttachments": true,
                      "attachments": [
                        {
                          "filename": "brief.pdf",
                          "size": 48213,
                          "mimeType": "application/pdf"
                        }
                      ],
                      "tags": [
                        {
                          "id": "cmtgacme0000000000000002",
                          "name": "Interested",
                          "color": "#2563eb",
                          "isAiLabel": true
                        }
                      ],
                      "inReplyTo": "<20261008091500.acme01@acme.com>",
                      "references": [
                        "<20261008091500.acme01@acme.com>"
                      ]
                    }
                  ],
                  "nextCursor": "s|65|2026-10-08T09:12:44.000Z|cmemacme0000000000000001",
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: `q` missing, shorter than 2 or longer than 200 characters, or unknown `folderType`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "tooShort": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Search query must be at least 2 characters.",
                      "details": {
                        "q": [
                          "Min 2 characters"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "408": {
            "$ref": "#/components/responses/QueryTimeout"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/emails/{emailId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EmailId"
        }
      ],
      "get": {
        "operationId": "getEmail",
        "tags": [
          "Emails"
        ],
        "summary": "Get the metadata of an email",
        "description": "Returns one email without its body. This object carries everything needed to reply in the same thread: `mailboxId`, `messageId`, `references` and `from`.\n\nNote: `labels` here are the provider labels (for example Gmail `INBOX`, `UNREAD`), not the inbox labels. The inbox labels of an email are the `tags` of `GET /emails` items.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The email.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "email"
                  ],
                  "properties": {
                    "email": {
                      "$ref": "#/components/schemas/Email"
                    }
                  }
                },
                "example": {
                  "email": {
                    "id": "cmemacme0000000000000001",
                    "mailboxId": "cmbxacme0000000000000001",
                    "folderId": "cmfdacme0000000000000001",
                    "messageId": "<CAJacme.0001@mail.example.com>",
                    "threadId": "18c2acme0001",
                    "subject": "Re: Partnership with Acme",
                    "from": {
                      "email": "jane.roe@example.com",
                      "name": "Jane Roe"
                    },
                    "to": [
                      {
                        "email": "john.doe@acme.com",
                        "name": null
                      }
                    ],
                    "cc": [],
                    "bcc": [],
                    "date": "2026-10-08T09:12:44.000Z",
                    "snippet": "Thanks John, could we schedule a call next week?",
                    "isRead": false,
                    "isStarred": false,
                    "isDraft": false,
                    "hasAttachments": true,
                    "attachments": [
                      {
                        "filename": "brief.pdf",
                        "size": 48213,
                        "mimeType": "application/pdf"
                      }
                    ],
                    "inReplyTo": "<20261008091500.acme01@acme.com>",
                    "references": [
                      "<20261008091500.acme01@acme.com>"
                    ],
                    "labels": [
                      "INBOX",
                      "UNREAD"
                    ],
                    "waitingForReply": false,
                    "isAutoReply": false,
                    "isAutoForward": false,
                    "scheduledStatus": null,
                    "scheduledSendAt": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`EMAIL_NOT_FOUND`: the email does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "email_not_found": {
                    "value": {
                      "code": "EMAIL_NOT_FOUND",
                      "error": "Email not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateEmail",
        "tags": [
          "Emails"
        ],
        "summary": "Mark an email read or unread, starred or unstarred",
        "description": "Provide `isRead`, `isStarred` or both, as booleans. A body with neither is rejected rather than treated as a no-op. The change is idempotent, pushed to open inbox windows in real time, propagated to the provider in the background for the read state (the star stays local), and delivered to `email.updated` webhooks.\n\nInconsistency: an unknown id returns `404 NOT_FOUND` here, while `GET /emails/{emailId}` returns `EMAIL_NOT_FOUND`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateEmailRequest"
              },
              "example": {
                "isRead": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated email.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "email"
                  ],
                  "properties": {
                    "email": {
                      "$ref": "#/components/schemas/Email"
                    }
                  }
                },
                "example": {
                  "email": {
                    "id": "cmemacme0000000000000001",
                    "mailboxId": "cmbxacme0000000000000001",
                    "folderId": "cmfdacme0000000000000001",
                    "messageId": "<CAJacme.0001@mail.example.com>",
                    "threadId": "18c2acme0001",
                    "subject": "Re: Partnership with Acme",
                    "from": {
                      "email": "jane.roe@example.com",
                      "name": "Jane Roe"
                    },
                    "to": [
                      {
                        "email": "john.doe@acme.com",
                        "name": null
                      }
                    ],
                    "cc": [],
                    "bcc": [],
                    "date": "2026-10-08T09:12:44.000Z",
                    "snippet": "Thanks John, could we schedule a call next week?",
                    "isRead": true,
                    "isStarred": false,
                    "isDraft": false,
                    "hasAttachments": true,
                    "attachments": [
                      {
                        "filename": "brief.pdf",
                        "size": 48213,
                        "mimeType": "application/pdf"
                      }
                    ],
                    "inReplyTo": "<20261008091500.acme01@acme.com>",
                    "references": [
                      "<20261008091500.acme01@acme.com>"
                    ],
                    "labels": [
                      "INBOX"
                    ],
                    "waitingForReply": false,
                    "isAutoReply": false,
                    "isAutoForward": false,
                    "scheduledStatus": null,
                    "scheduledSendAt": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED` when neither field is a boolean (`details.accepted` lists them), or `REQUEST_ERROR` on malformed JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "noField": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Provide at least one of `isRead` or `isStarred` as a boolean.",
                      "details": {
                        "accepted": [
                          "isRead",
                          "isStarred"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: the email does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "code": "NOT_FOUND",
                      "error": "Email not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "trashEmail",
        "tags": [
          "Emails"
        ],
        "summary": "Move an email to the trash",
        "description": "Moves the email to the trash folder of its mailbox, locally and at the provider (in the background). Never a permanent deletion: the message stays recoverable. Deleting an email already in the trash returns 204 as well. Delivered to `email.deleted` webhooks when the move actually happened.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Moved to the trash, or already there.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "400": {
            "description": "`NO_TRASH_FOLDER`: the mailbox has no trash folder, the move cannot be applied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "noTrash": {
                    "value": {
                      "code": "NO_TRASH_FOLDER",
                      "error": "Trash folder not available for this mailbox"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: the email does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "code": "NOT_FOUND",
                      "error": "Email not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/emails/{emailId}/body": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EmailId"
        }
      ],
      "get": {
        "operationId": "getEmailBody",
        "tags": [
          "Emails"
        ],
        "summary": "Get the body of an email and its whole thread",
        "description": "Returns the HTML and text body of the requested email, plus every message of its conversation, oldest first: messages received, messages you sent (`isMe: true`) and drafts in progress. The thread is resolved from the provider thread id when there is one, otherwise from the `Message-ID`, `In-Reply-To` and `References` headers, and is bounded to the mailbox of the email. Works with a draft id too.\n\nInline images (`cid:`) are rewritten to presigned storage URLs valid 15 minutes.\n\nKnown issue: this response is not passed through the public serializer. Thread messages may also contain internal fields that are not part of the contract: do not rely on them, they may be removed. An unknown id returns `NOT_FOUND`, not `EMAIL_NOT_FOUND`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Body and thread.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailThread"
                },
                "example": {
                  "emailId": "cmemacme0000000000000001",
                  "html": "<div>Thanks John, could we schedule a call next week?</div>",
                  "text": "Thanks John, could we schedule a call next week?",
                  "thread": [
                    {
                      "id": "cmemacme0000000000000002",
                      "mailboxId": "cmbxacme0000000000000001",
                      "messageId": "<20261008091500.acme01@acme.com>",
                      "references": [],
                      "fromAddress": "john.doe@acme.com",
                      "fromName": "John Doe",
                      "toAddresses": [
                        {
                          "email": "jane.roe@example.com",
                          "name": "Jane Roe"
                        }
                      ],
                      "date": "2026-10-06T08:00:00.000Z",
                      "subject": "Partnership with Acme",
                      "html": "<div>Hi Jane, would a partnership make sense?</div>",
                      "text": "Hi Jane, would a partnership make sense?",
                      "isMe": true
                    },
                    {
                      "id": "cmemacme0000000000000001",
                      "mailboxId": "cmbxacme0000000000000001",
                      "messageId": "<CAJacme.0001@mail.example.com>",
                      "references": [
                        "<20261008091500.acme01@acme.com>"
                      ],
                      "fromAddress": "jane.roe@example.com",
                      "fromName": "Jane Roe",
                      "toAddresses": [
                        {
                          "email": "john.doe@acme.com"
                        }
                      ],
                      "date": "2026-10-08T09:12:44.000Z",
                      "subject": "Re: Partnership with Acme",
                      "html": "<div>Thanks John, could we schedule a call next week?</div>",
                      "text": "Thanks John, could we schedule a call next week?",
                      "isMe": false,
                      "attachmentsS3": [
                        {
                          "filename": "brief.pdf",
                          "s3Key": "emails/acme-example/attachments/brief.pdf",
                          "size": 48213,
                          "mimeType": "application/pdf"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`NOT_FOUND`: the email does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "value": {
                      "code": "NOT_FOUND",
                      "error": "Email not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/emails/{emailId}/labels/{labelId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EmailId"
        },
        {
          "$ref": "#/components/parameters/LabelId"
        }
      ],
      "post": {
        "operationId": "applyLabel",
        "tags": [
          "Emails"
        ],
        "summary": "Apply a label to an email",
        "description": "Applies a manual or AI label (ids from `GET /labels`). Idempotent: applying a label the email already has returns the same list and does not fire `label.applied` again. A real application is pushed to open inbox windows and delivered to `label.applied` webhooks. No `Idempotency-Key` handling: the operation is naturally idempotent.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Every label now on the email.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "labels"
                  ],
                  "properties": {
                    "labels": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LabelRef"
                      }
                    }
                  }
                },
                "example": {
                  "labels": [
                    {
                      "id": "cmtgacme0000000000000001",
                      "name": "Quotes",
                      "color": "#16a34a",
                      "isAiLabel": false
                    },
                    {
                      "id": "cmtgacme0000000000000002",
                      "name": "Interested",
                      "color": "#2563eb",
                      "isAiLabel": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`EMAIL_NOT_FOUND` or `LABEL_NOT_FOUND`: unknown id, or it belongs to another workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "email": {
                    "value": {
                      "code": "EMAIL_NOT_FOUND",
                      "error": "Email not found"
                    }
                  },
                  "label": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "removeLabel",
        "tags": [
          "Emails"
        ],
        "summary": "Remove a label from an email",
        "description": "Idempotent: removing a label the email does not carry, or an unknown label id, is not an error and returns 204. No webhook is fired on removal.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Removed, or was not there.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`EMAIL_NOT_FOUND`: the email does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "email_not_found": {
                    "value": {
                      "code": "EMAIL_NOT_FOUND",
                      "error": "Email not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/emails/bulk": {
      "post": {
        "operationId": "bulkEmails",
        "tags": [
          "Emails"
        ],
        "summary": "Bulk mark read, trash, apply or remove a label",
        "description": "Applies one action to up to 500 emails. Ids that are unknown, from another workspace or already in the target state do not fail the batch: they come back in `skippedIds` (or `unchangedIds` for the read state). Duplicates and non string entries are ignored.\n\nCost: one quota unit per entry of `emailIds`, counted against BOTH the per minute limit and the monthly quota. Known issue: a batch larger than the per minute limit of the plan is always refused with `429 RATE_LIMIT_EXCEEDED`, whatever `Retry-After` says. Every Emelia workspace is on FREE (60 per minute): keep batches at 60 ids or fewer.\n\n`label.applied` webhooks are sent for every processed email as soon as at least one of them actually changed.\n\nSupports `Idempotency-Key`; a replay still consumes the same quota units.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEmailsRequest"
              },
              "example": {
                "action": "markRead",
                "isRead": true,
                "emailIds": [
                  "cmemacme0000000000000001",
                  "cmemacme0000000000000002",
                  "cmemacme0000000000000003"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per id outcome. The shape depends on `action`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/BulkMarkReadResult"
                    },
                    {
                      "$ref": "#/components/schemas/BulkDeleteResult"
                    },
                    {
                      "$ref": "#/components/schemas/BulkLabelResult"
                    }
                  ]
                },
                "examples": {
                  "markRead": {
                    "value": {
                      "updatedIds": [
                        "cmemacme0000000000000001"
                      ],
                      "unchangedIds": [
                        "cmemacme0000000000000002"
                      ],
                      "skippedIds": [
                        "cmemacme0000000000000003"
                      ],
                      "isRead": true
                    }
                  },
                  "delete": {
                    "value": {
                      "deletedIds": [
                        "cmemacme0000000000000001",
                        "cmemacme0000000000000002"
                      ],
                      "skippedIds": [
                        "cmemacme0000000000000003"
                      ],
                      "noTrashIds": []
                    }
                  },
                  "applyLabel": {
                    "value": {
                      "labelId": "cmtgacme0000000000000001",
                      "emailIds": [
                        "cmemacme0000000000000001",
                        "cmemacme0000000000000002"
                      ],
                      "skippedIds": [
                        "cmemacme0000000000000003"
                      ],
                      "updatedCount": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: empty or missing `emailIds`, more than 500 ids, unknown `action`, `isRead` missing for `markRead`, or `labelId` missing for a label action.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "tooMany": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Too many emails, max 500 per request.",
                      "details": {
                        "max": 500
                      }
                    }
                  },
                  "action": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Unsupported `action`. Use `markRead`, `delete`, `applyLabel` or `removeLabel`.",
                      "details": {
                        "accepted": [
                          "markRead",
                          "delete",
                          "applyLabel",
                          "removeLabel"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`LABEL_NOT_FOUND`: the label does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "label_not_found": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/drafts": {
      "get": {
        "operationId": "listDrafts",
        "tags": [
          "Drafts and sending"
        ],
        "summary": "List drafts",
        "description": "Returns the most recent drafts of the workspace (rows with `isDraft: true`, all mailboxes), most recent first. Not paginated: there is no cursor, so at most `limit` drafts (200 maximum) can ever be read. Read a draft body with `GET /emails/{draftId}/body`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Drafts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Email"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmdracme0000000000000001",
                      "mailboxId": "cmbxacme0000000000000001",
                      "folderId": "cmfdacme0000000000000001",
                      "messageId": "<draft-cmdracme0000000000000001@acme.com>",
                      "threadId": "18c2acme0001",
                      "subject": "Re: Partnership with Acme",
                      "from": {
                        "email": "john.doe@acme.com",
                        "name": null
                      },
                      "to": [
                        {
                          "email": "jane.roe@example.com",
                          "name": "Jane Roe"
                        }
                      ],
                      "cc": [],
                      "bcc": [],
                      "date": "2026-10-08T09:12:44.000Z",
                      "snippet": "Hello Jane, Tuesday 10am works for me.",
                      "isRead": true,
                      "isStarred": false,
                      "isDraft": true,
                      "hasAttachments": false,
                      "attachments": [],
                      "inReplyTo": "<CAJacme.0001@mail.example.com>",
                      "references": [
                        "<20261008091500.acme01@acme.com>",
                        "<CAJacme.0001@mail.example.com>"
                      ],
                      "labels": [],
                      "waitingForReply": false,
                      "isAutoReply": false,
                      "isAutoForward": false,
                      "scheduledStatus": null,
                      "scheduledSendAt": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createDraft",
        "tags": [
          "Drafts and sending"
        ],
        "summary": "Create a draft without sending it",
        "description": "Creates a draft in one of the workspace mailboxes. It appears immediately in the Drafts folder of the inbox, where a person reviews, edits and sends it: the way to prepare an email from an integration or an agent while keeping a human in the loop.\n\nSignatures: by default the default signature of the mailbox address is inserted (`signature` omitted or `\"default\"`). Pass `\"none\"` for no signature, or a signature id from `GET /signatures`. In Emelia, signatures come from the Emelia sending accounts.\n\nImportant: when `inReplyTo` is set and the mailbox already holds a draft replying to the same message (including an AI auto-draft), that draft is overwritten and returned with 201, instead of a new one being created. If that draft is being sent (scheduled send or auto-reply in progress) the call fails with `409 SCHEDULED_SEND_IN_PROGRESS`; if it was synchronised from the provider, with `409 DRAFT_ALREADY_EXISTS`.\n\nAttachments cannot be added through the API. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDraftRequest"
              },
              "example": {
                "mailboxId": "cmbxacme0000000000000001",
                "to": [
                  {
                    "email": "jane.roe@example.com",
                    "name": "Jane Roe"
                  }
                ],
                "subject": "Re: Partnership with Acme",
                "inReplyTo": "<CAJacme.0001@mail.example.com>",
                "references": [
                  "<20261008091500.acme01@acme.com>",
                  "<CAJacme.0001@mail.example.com>"
                ],
                "body": {
                  "text": "Hello Jane,\n\nTuesday 10am works for me.",
                  "html": "<p>Hello Jane,</p><p>Tuesday 10am works for me.</p>"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (or an existing draft reply was overwritten).",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "draft"
                  ],
                  "properties": {
                    "draft": {
                      "$ref": "#/components/schemas/Email"
                    }
                  }
                },
                "example": {
                  "draft": {
                    "id": "cmdracme0000000000000001",
                    "mailboxId": "cmbxacme0000000000000001",
                    "folderId": "cmfdacme0000000000000001",
                    "messageId": "<draft-cmdracme0000000000000001@acme.com>",
                    "threadId": "18c2acme0001",
                    "subject": "Re: Partnership with Acme",
                    "from": {
                      "email": "john.doe@acme.com",
                      "name": null
                    },
                    "to": [
                      {
                        "email": "jane.roe@example.com",
                        "name": "Jane Roe"
                      }
                    ],
                    "cc": [],
                    "bcc": [],
                    "date": "2026-10-08T09:12:44.000Z",
                    "snippet": "Hello Jane, Tuesday 10am works for me.",
                    "isRead": true,
                    "isStarred": false,
                    "isDraft": true,
                    "hasAttachments": false,
                    "attachments": [],
                    "inReplyTo": "<CAJacme.0001@mail.example.com>",
                    "references": [
                      "<20261008091500.acme01@acme.com>",
                      "<CAJacme.0001@mail.example.com>"
                    ],
                    "labels": [],
                    "waitingForReply": false,
                    "isAutoReply": false,
                    "isAutoForward": false,
                    "scheduledStatus": null,
                    "scheduledSendAt": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: missing or invalid field; `details` maps each field to its errors.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid draft payload.",
                      "details": {
                        "mailboxId": [
                          "Required"
                        ],
                        "body": [
                          "Required"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`MAILBOX_NOT_FOUND` (unknown `mailboxId`) or `SIGNATURE_NOT_FOUND` (unknown signature id).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "mailbox": {
                    "value": {
                      "code": "MAILBOX_NOT_FOUND",
                      "error": "Mailbox not found in this workspace. Call GET /mailboxes to list the available ids."
                    }
                  },
                  "signature": {
                    "value": {
                      "code": "SIGNATURE_NOT_FOUND",
                      "error": "No signature with this id in the workspace.",
                      "details": {
                        "signature": "cmsgunknown000000000000"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`CONFLICT` (Idempotency-Key reused with another body, or original call in progress), `SCHEDULED_SEND_IN_PROGRESS` or `DRAFT_ALREADY_EXISTS` (an existing draft reply cannot be overwritten).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "inFlight": {
                    "value": {
                      "code": "SCHEDULED_SEND_IN_PROGRESS",
                      "error": "A reply to this message is being sent and can no longer be edited.",
                      "details": {
                        "draftId": "cmdracme0000000000000001"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/drafts/{draftId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DraftId"
        }
      ],
      "get": {
        "operationId": "getDraft",
        "tags": [
          "Drafts and sending"
        ],
        "summary": "Get a draft",
        "description": "Returns one draft (an `Email` with `isDraft: true`). Scheduled drafts carry `scheduledStatus` and `scheduledSendAt`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The draft.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "draft"
                  ],
                  "properties": {
                    "draft": {
                      "$ref": "#/components/schemas/Email"
                    }
                  }
                },
                "example": {
                  "draft": {
                    "id": "cmdracme0000000000000001",
                    "mailboxId": "cmbxacme0000000000000001",
                    "folderId": "cmfdacme0000000000000001",
                    "messageId": "<draft-cmdracme0000000000000001@acme.com>",
                    "threadId": "18c2acme0001",
                    "subject": "Re: Partnership with Acme",
                    "from": {
                      "email": "john.doe@acme.com",
                      "name": null
                    },
                    "to": [
                      {
                        "email": "jane.roe@example.com",
                        "name": "Jane Roe"
                      }
                    ],
                    "cc": [],
                    "bcc": [],
                    "date": "2026-10-08T09:12:44.000Z",
                    "snippet": "Hello Jane, Tuesday 10am works for me.",
                    "isRead": true,
                    "isStarred": false,
                    "isDraft": true,
                    "hasAttachments": false,
                    "attachments": [],
                    "inReplyTo": "<CAJacme.0001@mail.example.com>",
                    "references": [
                      "<20261008091500.acme01@acme.com>",
                      "<CAJacme.0001@mail.example.com>"
                    ],
                    "labels": [],
                    "waitingForReply": false,
                    "isAutoReply": false,
                    "isAutoForward": false,
                    "scheduledStatus": null,
                    "scheduledSendAt": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`DRAFT_NOT_FOUND`: the draft does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "draft_not_found": {
                    "value": {
                      "code": "DRAFT_NOT_FOUND",
                      "error": "Draft not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/drafts/send": {
      "post": {
        "operationId": "sendEmail",
        "tags": [
          "Drafts and sending"
        ],
        "summary": "Send an email now",
        "description": "Sends an email immediately from one of the workspace mailboxes. The only irreversible action of the API: it reaches a third party.\n\nTo reply in a thread: send from the `mailboxId` of the original, set `inReplyTo` to its `messageId`, `references` to its `references` followed by its `messageId`, and prefix the subject with `Re: `.\n\nSignatures: inserted by default, exactly as for `POST /drafts` (`\"default\"`, `\"none\"` or a signature id), resolved on the `from` alias when given, otherwise on the mailbox address. Your HTML is sent as is.\n\nAlways send an `Idempotency-Key`. Known issue: if the message left but a later step failed (copy to the Sent folder, disconnection), the API answers `500 INTERNAL_ERROR` and releases the idempotency key, so a retry sends the message a second time. After a 500, check the SENT folder before retrying.\n\nFires a `draft.sent` webhook. Attachments cannot be sent through the API.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              },
              "example": {
                "mailboxId": "cmbxacme0000000000000001",
                "to": [
                  {
                    "email": "jane.roe@example.com",
                    "name": "Jane Roe"
                  }
                ],
                "subject": "Re: Partnership with Acme",
                "inReplyTo": "<CAJacme.0001@mail.example.com>",
                "references": [
                  "<20261008091500.acme01@acme.com>",
                  "<CAJacme.0001@mail.example.com>"
                ],
                "body": {
                  "text": "Hello Jane,\n\nTuesday 10am works for me.",
                  "html": "<p>Hello Jane,</p><p>Tuesday 10am works for me.</p>"
                },
                "signature": "default"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendEmailResult"
                },
                "example": {
                  "messageId": "<20261008100233.acme02@acme.com>",
                  "threadId": "18c2acme0001"
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED` (invalid payload), `MAILBOX_INACTIVE` (mailbox disconnected) or `INVALID_SENDER_ALIAS` (`from` is not a verified send-as alias of the mailbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid email payload.",
                      "details": {
                        "to": [
                          "At least one recipient is required"
                        ]
                      }
                    }
                  },
                  "inactive": {
                    "value": {
                      "code": "MAILBOX_INACTIVE",
                      "error": "Mailbox is not active. Reconnect it before sending."
                    }
                  },
                  "alias": {
                    "value": {
                      "code": "INVALID_SENDER_ALIAS",
                      "error": "Sender alias is not a verified send-as address for this mailbox.",
                      "details": {
                        "from": {
                          "email": "sales@acme.com"
                        },
                        "mailboxId": "cmbxacme0000000000000001"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`MAILBOX_NOT_FOUND` or `SIGNATURE_NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "mailbox": {
                    "value": {
                      "code": "MAILBOX_NOT_FOUND",
                      "error": "Mailbox not found in this workspace. Call GET /mailboxes to list the available ids."
                    }
                  }
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "description": "`INTERNAL_ERROR`: the provider refused the message, or a step failed AFTER the message left (see known issue). The idempotency key is released in both cases.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "value": {
                      "code": "INTERNAL_ERROR",
                      "error": "Internal server error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes": {
      "get": {
        "operationId": "listMailboxes",
        "tags": [
          "Mailboxes and signatures"
        ],
        "summary": "List connected mailboxes",
        "description": "Lists the mailboxes of the workspace, newest first. Call it first: `mailboxId` is required to send and useful in most filters. Credentials and OAuth tokens are never exposed. Read only: in Emelia, mailboxes are the sending accounts connected in Emelia, synchronised to the inbox by Emelia itself. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mailboxes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Mailbox"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmbxacme0000000000000001",
                      "email": "john.doe@acme.com",
                      "name": "John Doe",
                      "picture": null,
                      "provider": "GOOGLE",
                      "isActive": true,
                      "createdAt": "2026-09-30T08:00:00.000Z",
                      "lastSyncAt": "2026-10-08T09:14:02.000Z",
                      "syncError": null,
                      "backwardSyncComplete": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/signatures": {
      "get": {
        "operationId": "listSignatures",
        "tags": [
          "Mailboxes and signatures"
        ],
        "summary": "List signatures",
        "description": "Lists the signatures of the workspace, to turn a name into the id accepted by `signature` on `POST /drafts` and `POST /drafts/send`. The HTML content is never returned. `mailboxId` and `aliasEmail` both null means the signature applies to any address; `isDefault` marks the one inserted when nothing is requested. Read only. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Signatures.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Signature"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmsgacme0000000000000001",
                      "name": "John, Acme",
                      "mailboxId": "cmbxacme0000000000000001",
                      "aliasEmail": null,
                      "isDefault": true,
                      "position": 0,
                      "createdAt": "2026-09-30T08:05:00.000Z",
                      "updatedAt": "2026-09-30T08:05:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/labels": {
      "get": {
        "operationId": "listLabels",
        "tags": [
          "Labels"
        ],
        "summary": "List labels",
        "description": "Every label of the workspace, AI labels included (`isAiLabel: true`), in creation order. In Emelia, the labels created automatically for each campaign (same color, campaign name) are listed too, as manual labels. Use the ids in filters and on `POST /emails/{emailId}/labels/{labelId}`. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Labels.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Label"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmtgacme0000000000000001",
                      "name": "Quotes",
                      "color": "#16a34a",
                      "isAiLabel": false,
                      "createdAt": "2026-10-01T10:00:00.000Z"
                    },
                    {
                      "id": "cmtgacme0000000000000002",
                      "name": "Interested",
                      "color": "#2563eb",
                      "isAiLabel": true,
                      "createdAt": "2026-10-01T10:05:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Create a manual label",
        "description": "Creates a manual label. Names are unique per workspace across manual and AI labels. To have the AI apply a label automatically, create an AI label rule instead. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLabelRequest"
              },
              "example": {
                "name": "Quotes",
                "color": "#16a34a"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "label"
                  ],
                  "properties": {
                    "label": {
                      "$ref": "#/components/schemas/Label"
                    }
                  }
                },
                "example": {
                  "label": {
                    "id": "cmtgacme0000000000000001",
                    "name": "Quotes",
                    "color": "#16a34a",
                    "isAiLabel": false,
                    "createdAt": "2026-10-01T10:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: missing or invalid field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid label payload.",
                      "details": {
                        "name": [
                          "Required"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`DUPLICATE_TAG_NAME` (name already used) or `CONFLICT` (idempotency).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_TAG_NAME",
                      "error": "A label named \"Quotes\" already exists in this workspace. Pick another name, or reuse the existing label."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/labels/{labelId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/LabelId"
        }
      ],
      "get": {
        "operationId": "getLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Get a label",
        "description": "One label, manual or AI.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The label.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "label"
                  ],
                  "properties": {
                    "label": {
                      "$ref": "#/components/schemas/Label"
                    }
                  }
                },
                "example": {
                  "label": {
                    "id": "cmtgacme0000000000000001",
                    "name": "Quotes",
                    "color": "#16a34a",
                    "isAiLabel": false,
                    "createdAt": "2026-10-01T10:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`LABEL_NOT_FOUND`: the label does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "label_not_found": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Rename or recolor a manual label",
        "description": "At least one of `name` or `color`. AI labels are changed through their rule (`PATCH /ai-label-rules/{ruleId}`): here they return `400 INVALID_TAG`. In Emelia, renaming a campaign label is overwritten by the next synchronisation of the campaign name.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLabelRequest"
              },
              "example": {
                "name": "Quotes 2026"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated label.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "label"
                  ],
                  "properties": {
                    "label": {
                      "$ref": "#/components/schemas/Label"
                    }
                  }
                },
                "example": {
                  "label": {
                    "id": "cmtgacme0000000000000001",
                    "name": "Quotes 2026",
                    "color": "#16a34a",
                    "isAiLabel": false,
                    "createdAt": "2026-10-01T10:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED` (invalid or empty body) or `INVALID_TAG` (AI label).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "aiLabel": {
                    "value": {
                      "code": "INVALID_TAG",
                      "error": "This label is an AI label. AI labels are managed through /ai-label-rules: update or delete its rule instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`LABEL_NOT_FOUND`: the label does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "label_not_found": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`DUPLICATE_TAG_NAME`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_TAG_NAME",
                      "error": "A label named \"Quotes 2026\" already exists in this workspace. Pick another name, or reuse the existing label."
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Delete a manual label",
        "description": "Deletes a manual label and removes it from every email that carries it (emails are not touched otherwise). AI labels are deleted through their rule: here they return `400 INVALID_TAG`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "400": {
            "description": "`INVALID_TAG`: the label is an AI label.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "aiLabel": {
                    "value": {
                      "code": "INVALID_TAG",
                      "error": "This label is an AI label. AI labels are managed through /ai-label-rules: update or delete its rule instead."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`LABEL_NOT_FOUND`: the label does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "label_not_found": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/ai-label-rules": {
      "get": {
        "operationId": "listAiLabelRules",
        "tags": [
          "AI label rules"
        ],
        "summary": "List AI label rules",
        "description": "Every rule of the workspace with its AI label, oldest first. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Rules.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AiLabelRule"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmrlacme0000000000000001",
                      "label": {
                        "id": "cmtgacme0000000000000002",
                        "name": "Interested",
                        "color": "#2563eb",
                        "isAiLabel": true
                      },
                      "condition": "The prospect shows interest: asks for a call, a demo, pricing or more information.",
                      "autoDraftEnabled": true,
                      "autoReplyEnabled": false,
                      "autoReplyConfidenceThreshold": 85,
                      "autoReplyDelayMinutes": 0,
                      "autoReplyNotifyOnSend": true,
                      "hideFromInbox": false,
                      "createdAt": "2026-10-01T10:05:00.000Z",
                      "updatedAt": "2026-10-02T16:40:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createAiLabelRule",
        "tags": [
          "AI label rules"
        ],
        "summary": "Create an AI label and its rule",
        "description": "Creates the AI label and the plain language condition that applies it, in one call. The rule applies to emails synchronised after its creation. Setting `autoReplyEnabled: true` makes the inbox send replies on your behalf. In Emelia, AI features are paid with Emelia credits: each incoming email classified while the workspace has at least one rule, and each auto-draft, is debited from the Emelia account. Setting `autoDraftEnabled` or `autoReplyEnabled` to true never returns `402 PLAN_REQUIRED` in Emelia. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAiLabelRuleRequest"
              },
              "example": {
                "name": "Interested",
                "color": "#2563eb",
                "condition": "The prospect shows interest: asks for a call, a demo, pricing or more information.",
                "autoDraftEnabled": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AiLabelRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmrlacme0000000000000001",
                    "label": {
                      "id": "cmtgacme0000000000000002",
                      "name": "Interested",
                      "color": "#2563eb",
                      "isAiLabel": true
                    },
                    "condition": "The prospect shows interest: asks for a call, a demo, pricing or more information.",
                    "autoDraftEnabled": true,
                    "autoReplyEnabled": false,
                    "autoReplyConfidenceThreshold": 85,
                    "autoReplyDelayMinutes": 0,
                    "autoReplyNotifyOnSend": true,
                    "hideFromInbox": false,
                    "createdAt": "2026-10-01T10:05:00.000Z",
                    "updatedAt": "2026-10-02T16:40:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: missing or invalid field, empty condition, threshold or delay out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "condition": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid AI label rule payload.",
                      "details": {
                        "condition": [
                          "Condition is required"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "`PLAN_REQUIRED`: auto-draft or auto-reply on a workspace without a paid plan. Never returned in Emelia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan": {
                    "value": {
                      "code": "PLAN_REQUIRED",
                      "error": "Auto-Draft and Auto-Reply require a subscription."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`DUPLICATE_RULE` (a label with this name exists) or `CONFLICT` (idempotency).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_RULE",
                      "error": "An AI label with this name already exists in this workspace. Choose another name.",
                      "details": {
                        "name": "Interested"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/ai-label-rules/{ruleId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AiRuleId"
        }
      ],
      "get": {
        "operationId": "getAiLabelRule",
        "tags": [
          "AI label rules"
        ],
        "summary": "Get an AI label rule",
        "description": "One rule with its label.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The rule.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AiLabelRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmrlacme0000000000000001",
                    "label": {
                      "id": "cmtgacme0000000000000002",
                      "name": "Interested",
                      "color": "#2563eb",
                      "isAiLabel": true
                    },
                    "condition": "The prospect shows interest: asks for a call, a demo, pricing or more information.",
                    "autoDraftEnabled": true,
                    "autoReplyEnabled": false,
                    "autoReplyConfidenceThreshold": 85,
                    "autoReplyDelayMinutes": 0,
                    "autoReplyNotifyOnSend": true,
                    "hideFromInbox": false,
                    "createdAt": "2026-10-01T10:05:00.000Z",
                    "updatedAt": "2026-10-02T16:40:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the AI label rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "AI label rule not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateAiLabelRule",
        "tags": [
          "AI label rules"
        ],
        "summary": "Update an AI label rule",
        "description": "Renames or recolors the label, changes the condition, configures auto-draft, auto-reply and `hideFromInbox`. All fields are optional but at least one is required. In Emelia, AI features are paid with Emelia credits: each incoming email classified while the workspace has at least one rule, and each auto-draft, is debited from the Emelia account. Setting `autoDraftEnabled` or `autoReplyEnabled` to true never returns `402 PLAN_REQUIRED` in Emelia.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAiLabelRuleRequest"
              },
              "example": {
                "autoReplyEnabled": false,
                "hideFromInbox": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated rule.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AiLabelRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmrlacme0000000000000001",
                    "label": {
                      "id": "cmtgacme0000000000000002",
                      "name": "Interested",
                      "color": "#2563eb",
                      "isAiLabel": true
                    },
                    "condition": "The prospect shows interest: asks for a call, a demo, pricing or more information.",
                    "autoDraftEnabled": true,
                    "autoReplyEnabled": false,
                    "autoReplyConfidenceThreshold": 85,
                    "autoReplyDelayMinutes": 0,
                    "autoReplyNotifyOnSend": true,
                    "hideFromInbox": true,
                    "createdAt": "2026-10-01T10:05:00.000Z",
                    "updatedAt": "2026-10-02T16:40:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: invalid field, or no field at all (`details.accepted`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "empty": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Provide at least one field to update.",
                      "details": {
                        "accepted": [
                          "name",
                          "color",
                          "condition",
                          "autoDraftEnabled",
                          "autoReplyEnabled",
                          "autoReplyConfidenceThreshold",
                          "autoReplyDelayMinutes",
                          "autoReplyNotifyOnSend",
                          "hideFromInbox"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "`PLAN_REQUIRED` (never in Emelia).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan": {
                    "value": {
                      "code": "PLAN_REQUIRED",
                      "error": "Auto-Draft and Auto-Reply require a subscription."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the AI label rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "AI label rule not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`DUPLICATE_RULE`: the new name is already used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_RULE",
                      "error": "An AI label with this name already exists in this workspace. Choose another name.",
                      "details": {
                        "name": "Interested"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteAiLabelRule",
        "tags": [
          "AI label rules"
        ],
        "summary": "Delete an AI label rule and its label",
        "description": "Deletes the rule AND its label; the label is removed from every email that carried it.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the AI label rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "AI label rule not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/views": {
      "get": {
        "operationId": "listViews",
        "tags": [
          "Views"
        ],
        "summary": "List saved views",
        "description": "Saved views of the workspace, in the order of the inbox sidebar. `filters` is the view definition in the same DSL as `?filters=`. Apply a view with `GET /emails?viewId=`. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Views.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/View"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmvwacme0000000000000001",
                      "name": "Hot leads",
                      "icon": "🔥",
                      "filters": {
                        "id": "g1",
                        "_and": [
                          {
                            "id": "c1",
                            "label": "ai_label",
                            "type": "contains",
                            "value": "cmtgacme0000000000000002"
                          },
                          {
                            "id": "c2",
                            "label": "read_status",
                            "type": "is_false",
                            "value": ""
                          }
                        ]
                      },
                      "mailboxIds": [],
                      "createdAt": "2026-10-01T11:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createView",
        "tags": [
          "Views"
        ],
        "summary": "Create a view",
        "description": "Saves a filter tree under a name, at the end of the sidebar. The tree is bounded like `?filters=` (5 levels, 50 conditions, 500 character values). Restricting a view to some mailboxes is only possible in the app. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateViewRequest"
              },
              "example": {
                "name": "Hot leads",
                "icon": "🔥",
                "filters": {
                  "id": "g1",
                  "_and": [
                    {
                      "id": "c1",
                      "label": "ai_label",
                      "type": "contains",
                      "value": "cmtgacme0000000000000002"
                    },
                    {
                      "id": "c2",
                      "label": "read_status",
                      "type": "is_false",
                      "value": ""
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "view"
                  ],
                  "properties": {
                    "view": {
                      "$ref": "#/components/schemas/View"
                    }
                  }
                },
                "example": {
                  "view": {
                    "id": "cmvwacme0000000000000001",
                    "name": "Hot leads",
                    "icon": "🔥",
                    "filters": {
                      "id": "g1",
                      "_and": [
                        {
                          "id": "c1",
                          "label": "ai_label",
                          "type": "contains",
                          "value": "cmtgacme0000000000000002"
                        },
                        {
                          "id": "c2",
                          "label": "read_status",
                          "type": "is_false",
                          "value": ""
                        }
                      ]
                    },
                    "mailboxIds": [],
                    "createdAt": "2026-10-01T11:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: invalid field, invalid filter tree or bound exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "tooDeep": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Filter nesting is too deep, max 5 levels.",
                      "details": {
                        "maxDepth": 5
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/views/{viewId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ViewId"
        }
      ],
      "get": {
        "operationId": "getView",
        "tags": [
          "Views"
        ],
        "summary": "Get a view",
        "description": "One view, `filters` included.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The view.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "view"
                  ],
                  "properties": {
                    "view": {
                      "$ref": "#/components/schemas/View"
                    }
                  }
                },
                "example": {
                  "view": {
                    "id": "cmvwacme0000000000000001",
                    "name": "Hot leads",
                    "icon": "🔥",
                    "filters": {
                      "id": "g1",
                      "_and": [
                        {
                          "id": "c1",
                          "label": "ai_label",
                          "type": "contains",
                          "value": "cmtgacme0000000000000002"
                        },
                        {
                          "id": "c2",
                          "label": "read_status",
                          "type": "is_false",
                          "value": ""
                        }
                      ]
                    },
                    "mailboxIds": [],
                    "createdAt": "2026-10-01T11:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`VIEW_NOT_FOUND`: the view does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "view_not_found": {
                    "value": {
                      "code": "VIEW_NOT_FOUND",
                      "error": "View not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateView",
        "tags": [
          "Views"
        ],
        "summary": "Update a view",
        "description": "Changes `name`, `icon` (null clears it) and/or `filters` (replaces the whole tree). At least one field.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateViewRequest"
              },
              "example": {
                "name": "Hot leads (unread)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated view.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "view"
                  ],
                  "properties": {
                    "view": {
                      "$ref": "#/components/schemas/View"
                    }
                  }
                },
                "example": {
                  "view": {
                    "id": "cmvwacme0000000000000001",
                    "name": "Hot leads (unread)",
                    "icon": "🔥",
                    "filters": {
                      "id": "g1",
                      "_and": [
                        {
                          "id": "c1",
                          "label": "ai_label",
                          "type": "contains",
                          "value": "cmtgacme0000000000000002"
                        },
                        {
                          "id": "c2",
                          "label": "read_status",
                          "type": "is_false",
                          "value": ""
                        }
                      ]
                    },
                    "mailboxIds": [],
                    "createdAt": "2026-10-01T11:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: invalid or empty body, invalid tree or bound exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "empty": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Provide at least one of `name`, `icon` or `filters`.",
                      "details": {
                        "accepted": [
                          "name",
                          "icon",
                          "filters"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`VIEW_NOT_FOUND`: the view does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "view_not_found": {
                    "value": {
                      "code": "VIEW_NOT_FOUND",
                      "error": "View not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteView",
        "tags": [
          "Views"
        ],
        "summary": "Delete a view",
        "description": "Permanent deletion of the view. Emails are not affected.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`VIEW_NOT_FOUND`: the view does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "view_not_found": {
                    "value": {
                      "code": "VIEW_NOT_FOUND",
                      "error": "View not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/filters": {
      "get": {
        "operationId": "listInboxFilters",
        "tags": [
          "Inbox filters"
        ],
        "summary": "List inbox filters",
        "description": "Every inbox filter of the workspace, oldest first. A filter hides matching emails from the main inbox without moving them: they stay in INBOX, are listed by `GET /emails?folderType=INBOX&filtered=only`, and stay visible in any view whose criteria match them. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Filters.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/InboxFilter"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmflacme0000000000000001",
                      "type": "domain",
                      "value": "newsletter.example.com",
                      "label": null,
                      "createdAt": "2026-10-01T12:00:00.000Z",
                      "updatedAt": "2026-10-01T12:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createInboxFilter",
        "tags": [
          "Inbox filters"
        ],
        "summary": "Create an inbox filter",
        "description": "Evaluated when listing, so it also hides past emails, and deleting it brings them back. Addresses and domains are stored lowercase; a leading `@` on a domain is dropped. A `label` filter must reference a label of the workspace. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInboxFilterRequest"
              },
              "example": {
                "type": "domain",
                "value": "newsletter.example.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "filter"
                  ],
                  "properties": {
                    "filter": {
                      "$ref": "#/components/schemas/InboxFilter"
                    }
                  }
                },
                "example": {
                  "filter": {
                    "id": "cmflacme0000000000000001",
                    "type": "domain",
                    "value": "newsletter.example.com",
                    "label": null,
                    "createdAt": "2026-10-01T12:00:00.000Z",
                    "updatedAt": "2026-10-01T12:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: unknown `type`, or a `value` that is not an address, a domain or an id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "domain": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid filter payload.",
                      "details": {
                        "value": [
                          "Expected a domain such as acme.com"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`LABEL_NOT_FOUND`: the label of a `label` filter does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "label_not_found": {
                    "value": {
                      "code": "LABEL_NOT_FOUND",
                      "error": "Label not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`DUPLICATE_FILTER` (`details.filterId` names the existing one) or `CONFLICT` (idempotency).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_FILTER",
                      "error": "A filter with this type and value already exists in this workspace.",
                      "details": {
                        "filterId": "cmflacme0000000000000001"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/filters/{filterId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FilterId"
        }
      ],
      "get": {
        "operationId": "getInboxFilter",
        "tags": [
          "Inbox filters"
        ],
        "summary": "Get an inbox filter",
        "description": "One filter.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The filter.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "filter"
                  ],
                  "properties": {
                    "filter": {
                      "$ref": "#/components/schemas/InboxFilter"
                    }
                  }
                },
                "example": {
                  "filter": {
                    "id": "cmflacme0000000000000001",
                    "type": "domain",
                    "value": "newsletter.example.com",
                    "label": null,
                    "createdAt": "2026-10-01T12:00:00.000Z",
                    "updatedAt": "2026-10-01T12:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`FILTER_NOT_FOUND`: the filter does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "filter_not_found": {
                    "value": {
                      "code": "FILTER_NOT_FOUND",
                      "error": "Filter not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateInboxFilter",
        "tags": [
          "Inbox filters"
        ],
        "summary": "Update an inbox filter",
        "description": "Changes `type` and/or `value`. The resulting filter is validated as a whole: a new `type` needs a compatible `value`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateInboxFilterRequest"
              },
              "example": {
                "value": "news.example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated filter.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "filter"
                  ],
                  "properties": {
                    "filter": {
                      "$ref": "#/components/schemas/InboxFilter"
                    }
                  }
                },
                "example": {
                  "filter": {
                    "id": "cmflacme0000000000000001",
                    "type": "domain",
                    "value": "news.example.com",
                    "label": null,
                    "createdAt": "2026-10-01T12:00:00.000Z",
                    "updatedAt": "2026-10-01T12:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: invalid field, incompatible `type` and `value`, or no field at all.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "empty": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Provide at least one field to update.",
                      "details": {
                        "accepted": [
                          "type",
                          "value"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`FILTER_NOT_FOUND`, or `LABEL_NOT_FOUND` for a `label` filter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "filter": {
                    "value": {
                      "code": "FILTER_NOT_FOUND",
                      "error": "Filter not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`DUPLICATE_FILTER`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "duplicate": {
                    "value": {
                      "code": "DUPLICATE_FILTER",
                      "error": "A filter with this type and value already exists in this workspace.",
                      "details": {
                        "filterId": "cmflacme0000000000000001"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteInboxFilter",
        "tags": [
          "Inbox filters"
        ],
        "summary": "Delete an inbox filter",
        "description": "The emails it hid reappear in the main inbox immediately.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`FILTER_NOT_FOUND`: the filter does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "filter_not_found": {
                    "value": {
                      "code": "FILTER_NOT_FOUND",
                      "error": "Filter not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/auto-forward-rules": {
      "get": {
        "operationId": "listAutoForwardRules",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "List auto-forward rules",
        "description": "Every rule of the workspace, oldest first. Reading only needs `read`. Not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Rules.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AutoForwardRule"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmfwacme0000000000000001",
                      "conditionField": "label",
                      "conditionValue": "Interested",
                      "forwardTo": "sales@acme.com",
                      "mode": "normal",
                      "isActive": true,
                      "createdAt": "2026-10-01T13:00:00.000Z",
                      "updatedAt": "2026-10-01T13:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createAutoForwardRule",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "Create an auto-forward rule",
        "description": "Forwards every incoming email matching the condition to `forwardTo`. A rule makes email leave the workspace without human action. Combined with an AI label rule, this routes for example every interested reply to a sales address. Supports `Idempotency-Key`.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAutoForwardRuleRequest"
              },
              "example": {
                "conditionField": "label",
                "conditionValue": "Interested",
                "forwardTo": "sales@acme.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/Idempotent-Replay"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AutoForwardRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmfwacme0000000000000001",
                    "conditionField": "label",
                    "conditionValue": "Interested",
                    "forwardTo": "sales@acme.com",
                    "mode": "normal",
                    "isActive": true,
                    "createdAt": "2026-10-01T13:00:00.000Z",
                    "updatedAt": "2026-10-01T13:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: `forwardTo` not an email address, empty `conditionValue`, or unknown `conditionField` or `mode`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "forwardTo": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "Invalid auto-forward rule payload.",
                      "details": {
                        "forwardTo": [
                          "Invalid email"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/auto-forward-rules/{ruleId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ForwardRuleId"
        }
      ],
      "get": {
        "operationId": "getAutoForwardRule",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "Get an auto-forward rule",
        "description": "One rule.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The rule.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AutoForwardRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmfwacme0000000000000001",
                    "conditionField": "label",
                    "conditionValue": "Interested",
                    "forwardTo": "sales@acme.com",
                    "mode": "normal",
                    "isActive": true,
                    "createdAt": "2026-10-01T13:00:00.000Z",
                    "updatedAt": "2026-10-01T13:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the auto-forward rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "Auto-forward rule not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateAutoForwardRule",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "Update an auto-forward rule",
        "description": "At least one field; `forwardTo` and `conditionValue` cannot be emptied (pause a rule with `isActive: false`). A rule makes email leave the workspace without human action.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutoForwardRuleRequest"
              },
              "example": {
                "isActive": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated rule.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rule"
                  ],
                  "properties": {
                    "rule": {
                      "$ref": "#/components/schemas/AutoForwardRule"
                    }
                  }
                },
                "example": {
                  "rule": {
                    "id": "cmfwacme0000000000000001",
                    "conditionField": "label",
                    "conditionValue": "Interested",
                    "forwardTo": "sales@acme.com",
                    "mode": "normal",
                    "isActive": false,
                    "createdAt": "2026-10-01T13:00:00.000Z",
                    "updatedAt": "2026-10-01T13:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION_FAILED`: invalid field, no field at all, or an emptied `forwardTo` / `conditionValue`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "emptied": {
                    "value": {
                      "code": "VALIDATION_FAILED",
                      "error": "An auto-forward rule with an empty `conditionValue` or `forwardTo` is never applied. Set `isActive` to false to pause it, or delete it.",
                      "details": {
                        "forwardTo": [
                          "Must not be empty"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the auto-forward rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "Auto-forward rule not found"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteAutoForwardRule",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "Delete an auto-forward rule",
        "description": "Permanent deletion; its logs are deleted with it. Emails already forwarded are not affected. A rule makes email leave the workspace without human action.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the auto-forward rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "Auto-forward rule not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/auto-forward-rules/{ruleId}/logs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ForwardRuleId"
        }
      ],
      "get": {
        "operationId": "listAutoForwardLogs",
        "tags": [
          "Auto-forward rules"
        ],
        "summary": "List the forwarding attempts of a rule",
        "description": "The 50 most recent finished attempts (`sent` or `failed`), newest first, with the email that triggered each one. In flight attempts are not listed. Fixed size, not paginated.",
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Attempts.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-RateLimit-Quota": {
                "$ref": "#/components/headers/X-RateLimit-Quota"
              },
              "X-RateLimit-Quota-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Remaining"
              },
              "X-RateLimit-Quota-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Quota-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ForwardLog"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "cmlgacme0000000000000001",
                      "emailId": "cmemacme0000000000000001",
                      "destination": "sales@acme.com",
                      "mode": "normal",
                      "status": "sent",
                      "error": null,
                      "forwardedMessageId": "<20261008091703.fwd01@acme.com>",
                      "createdAt": "2026-10-08T09:17:03.000Z",
                      "email": {
                        "id": "cmemacme0000000000000001",
                        "subject": "Re: Partnership with Acme",
                        "from": {
                          "email": "jane.roe@example.com",
                          "name": "Jane Roe"
                        },
                        "date": "2026-10-08T09:12:44.000Z"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`RULE_NOT_FOUND`: the auto-forward rule does not exist, or belongs to another workspace (never 403, to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rule_not_found": {
                    "value": {
                      "code": "RULE_NOT_FOUND",
                      "error": "Auto-forward rule not found"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "webhooks": {
    "email.received": {
      "post": {
        "operationId": "onEmailReceived",
        "tags": [
          "Webhooks"
        ],
        "summary": "An email arrived in an inbox",
        "description": "Fired once per new message synchronised into an INBOX folder. Not fired for sent messages, drafts or other folders. Deduplicated across backend instances for 5 minutes.\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "email.received"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EmailReceivedData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "email.received",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "emailId": "cmemacme0000000000000001",
                  "mailboxId": "cmbxacme0000000000000001",
                  "folderType": "INBOX"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    },
    "email.updated": {
      "post": {
        "operationId": "onEmailUpdated",
        "tags": [
          "Webhooks"
        ],
        "summary": "Read or starred state changed",
        "description": "Fired when the read state or the star changes through the API or the inbox app. Changes made directly at the provider (for example in Gmail) and synchronised later do not fire it.\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "email.updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EmailUpdatedData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "email.updated",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "emailId": "cmemacme0000000000000001",
                  "changes": {
                    "isRead": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    },
    "email.deleted": {
      "post": {
        "operationId": "onEmailDeleted",
        "tags": [
          "Webhooks"
        ],
        "summary": "An email was moved to the trash",
        "description": "Fired when an email is moved to the trash through the API or the inbox app.\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "email.deleted"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EmailDeletedData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "email.deleted",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "emailId": "cmemacme0000000000000001"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    },
    "draft.sent": {
      "post": {
        "operationId": "onDraftSent",
        "tags": [
          "Webhooks"
        ],
        "summary": "An email was sent directly",
        "description": "Fired by direct sends only: `POST /drafts/send` and the direct send of the inbox app. Not fired when a saved draft is sent from the app, nor for scheduled sends, auto-replies or auto-forwards.\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "draft.sent"
                      },
                      "data": {
                        "$ref": "#/components/schemas/DraftSentData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "draft.sent",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "mailboxId": "cmbxacme0000000000000001",
                  "messageId": "<20261008100233.acme02@acme.com>",
                  "threadId": "18c2acme0001",
                  "to": [
                    "jane.roe@example.com"
                  ],
                  "subject": "Re: Partnership with Acme"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    },
    "label.applied": {
      "post": {
        "operationId": "onLabelApplied",
        "tags": [
          "Webhooks"
        ],
        "summary": "A label was applied by hand or through the API",
        "description": "Fired when a label is applied through the API or the inbox app. Not fired for labels applied by the AI pipeline, by an AI backfill or for Emelia campaign labels (they are applied by the worker). On `POST /emails/bulk` with `applyLabel`, it is fired for every processed email as soon as one of them actually changed.\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "label.applied"
                      },
                      "data": {
                        "$ref": "#/components/schemas/LabelAppliedData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "label.applied",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "emailId": "cmemacme0000000000000001",
                  "tagId": "cmtgacme0000000000000001",
                  "tagName": "Quotes",
                  "isAiLabel": false
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    },
    "mailbox.sync_failed": {
      "post": {
        "operationId": "onMailboxSyncFailed",
        "tags": [
          "Webhooks"
        ],
        "summary": "The synchronisation of a mailbox failed",
        "description": "Fired at each failed synchronisation attempt (deduplicated per mailbox and failure count). `deactivated: true` means synchronisation stopped and the mailbox must be reconnected (in Emelia, from the Emelia accounts page).\n\nRegistration: webhook subscriptions cannot be created with an API key, and Emelia has no screen for them yet: contact support.",
        "parameters": [
          {
            "name": "X-Maylee-Event",
            "in": "header",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/WebhookEventName"
            },
            "description": "Event name, same as `event` in the body."
          },
          {
            "name": "X-Maylee-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the webhook secret>`. Reject deliveries older than 300 seconds and compare in constant time.",
            "example": "t=1791460800,v1=a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1a3f1"
          },
          {
            "name": "User-Agent",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Fixed User-Agent of the delivery client. Do not use it to authenticate a delivery: verify the signature."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/WebhookEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "event": {
                        "const": "mailbox.sync_failed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/MailboxSyncFailedData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "event": "mailbox.sync_failed",
                "createdAt": "2026-10-08T09:12:51.000Z",
                "data": {
                  "mailboxId": "cmbxacme0000000000000001",
                  "error": "Invalid credentials",
                  "failCount": 3,
                  "deactivated": false
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Answer within 10 seconds, process later."
          },
          "default": {
            "description": "Any other status, or a timeout, schedules a retry."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Your 48 character Emelia API key, the same as for the Emelia API, sent as is (a `Bearer ` prefix is tolerated). Create it at https://v3.emelia.io/settings/api. Disabling a key can take up to 5 minutes to apply to the Inbox API."
      }
    },
    "parameters": {
      "EmailId": {
        "name": "emailId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Inbox id of the email (from `GET /emails`, webhooks...).",
        "example": "cmemacme0000000000000001"
      },
      "LabelId": {
        "name": "labelId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Label id, from `GET /labels`.",
        "example": "cmtgacme0000000000000001"
      },
      "ViewId": {
        "name": "viewId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "cmvwacme0000000000000001"
      },
      "AiRuleId": {
        "name": "ruleId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "AI label rule id (not the label id).",
        "example": "cmrlacme0000000000000001"
      },
      "ForwardRuleId": {
        "name": "ruleId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Auto-forward rule id.",
        "example": "cmfwacme0000000000000001"
      },
      "FilterId": {
        "name": "filterId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "cmflacme0000000000000001"
      },
      "DraftId": {
        "name": "draftId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "cmdracme0000000000000001"
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Opaque `nextCursor` from the previous page. Its format is not part of the contract."
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        },
        "description": "Page size. Above 200 it is clamped to 200; an unreadable or non positive value falls back to 50 (no error)."
      },
      "FolderType": {
        "name": "folderType",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "INBOX",
            "SENT",
            "DRAFTS",
            "SPAM",
            "TRASH"
          ]
        },
        "description": "Restrict to one system folder. Case sensitive; any other value is rejected with 400. Omitted, every folder is considered."
      },
      "MailboxIdQuery": {
        "name": "mailboxId",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Restrict to one mailbox (ids from `GET /mailboxes`). An unknown id returns an empty page.",
        "example": "cmbxacme0000000000000001"
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 255
        },
        "description": "Any unique string (a UUID). The first successful response is stored 24 hours and replayed with `Idempotent-Replay: true` for the same key, method, URL and body. Same key with another body: 409 CONFLICT. Original call still running: 409 CONFLICT. Failed calls (status 400 and above) release the key. Keys are scoped to the workspace, not to the API key: two integrations of the same workspace must not reuse values. Replays count in the quotas.",
        "example": "3f6c1b2e-7d4a-4f0e-9a51-acme00000001"
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Requests allowed per minute for the workspace.",
        "schema": {
          "type": "integer"
        },
        "example": 60
      },
      "X-RateLimit-Remaining": {
        "description": "Units left in the current sliding minute.",
        "schema": {
          "type": "integer"
        },
        "example": 57
      },
      "X-RateLimit-Reset": {
        "description": "Unix seconds when the current minute window ends.",
        "schema": {
          "type": "integer"
        },
        "example": 1791460860
      },
      "X-RateLimit-Quota": {
        "description": "Requests allowed per calendar month (UTC).",
        "schema": {
          "type": "integer"
        },
        "example": 10000
      },
      "X-RateLimit-Quota-Remaining": {
        "description": "Units left this month.",
        "schema": {
          "type": "integer"
        },
        "example": 9421
      },
      "X-RateLimit-Quota-Reset": {
        "description": "Unix seconds of the 1st of next month, 00:00 UTC.",
        "schema": {
          "type": "integer"
        },
        "example": 1793491200
      },
      "Retry-After": {
        "description": "Seconds to wait (per minute limit only).",
        "schema": {
          "type": "integer"
        },
        "example": 12
      },
      "Idempotent-Replay": {
        "description": "`true` when the response is a stored replay.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, malformed, unknown or disabled key. No `X-RateLimit-*` headers.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing": {
                "value": {
                  "code": "INVALID_API_KEY",
                  "error": "Missing API key. Send your Emelia API key as `Authorization: <key>`."
                }
              },
              "malformed": {
                "value": {
                  "code": "INVALID_API_KEY",
                  "error": "Invalid API key. Send your Emelia API key as `Authorization: <key>`."
                }
              },
              "unknown": {
                "value": {
                  "code": "INVALID_API_KEY",
                  "error": "Invalid API key. Check the key you are sending, or create one in Emelia, Settings, API & Webhooks."
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "`WORKSPACE_SUSPENDED`: the Emelia subscription has expired.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "suspended": {
                "value": {
                  "code": "WORKSPACE_SUSPENDED",
                  "error": "This workspace is suspended. Reactivate the subscription to resume API access."
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "`RATE_LIMIT_EXCEEDED`: per minute limit of the workspace (wait `Retry-After`). `QUOTA_EXCEEDED`: monthly quota exhausted until the 1st of next month UTC (in Emelia the plan cannot be upgraded).",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "rate": {
                "value": {
                  "code": "RATE_LIMIT_EXCEEDED",
                  "error": "Rate limit of 60 requests per minute exceeded. Retry in 12s.",
                  "details": {
                    "limit": 60,
                    "retryAfterSeconds": 12,
                    "resetAt": 1791460860
                  }
                }
              },
              "quota": {
                "value": {
                  "code": "QUOTA_EXCEEDED",
                  "error": "Monthly API quota of 10000 requests exhausted. It resets on the 1st of next month (UTC), or upgrade the workspace plan.",
                  "details": {
                    "quota": 10000,
                    "used": 10000,
                    "resetAt": 1793491200
                  }
                }
              }
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "`PAYLOAD_TOO_LARGE`: JSON body above 256 KB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "tooLarge": {
                "value": {
                  "code": "PAYLOAD_TOO_LARGE",
                  "error": "Request body is too large"
                }
              }
            }
          }
        }
      },
      "QueryTimeout": {
        "description": "`QUERY_TIMEOUT`: the query ran more than 10 seconds and was cancelled by the database.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "timeout": {
                "value": {
                  "code": "QUERY_TIMEOUT",
                  "error": "Query exceeded the 10000ms limit. Narrow the filters, reduce `limit`, or scope the request to a single mailbox.",
                  "details": {
                    "timeoutMs": 10000
                  }
                }
              }
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "`CONFLICT`: Idempotency-Key reused with a different request, or the original call is still in progress.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "reused": {
                "value": {
                  "code": "CONFLICT",
                  "error": "This `Idempotency-Key` was already used with a different request body. Use a new key for a new operation."
                }
              },
              "inProgress": {
                "value": {
                  "code": "CONFLICT",
                  "error": "A request with this `Idempotency-Key` is still in progress. Retry in a moment."
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "`INTERNAL_ERROR`: unexpected failure. The message is generic in production.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "internal": {
                "value": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorCode": {
        "type": "string",
        "enum": [
          "INVALID_API_KEY",
          "WORKSPACE_SUSPENDED",
          "FORBIDDEN",
          "PLAN_REQUIRED",
          "VALIDATION_FAILED",
          "REQUEST_ERROR",
          "PAYLOAD_TOO_LARGE",
          "NOT_FOUND",
          "EMAIL_NOT_FOUND",
          "DRAFT_NOT_FOUND",
          "MAILBOX_NOT_FOUND",
          "LABEL_NOT_FOUND",
          "VIEW_NOT_FOUND",
          "RULE_NOT_FOUND",
          "FILTER_NOT_FOUND",
          "SIGNATURE_NOT_FOUND",
          "MAILBOX_INACTIVE",
          "INVALID_SENDER_ALIAS",
          "NO_TRASH_FOLDER",
          "INVALID_TAG",
          "CONFLICT",
          "DUPLICATE_TAG_NAME",
          "DUPLICATE_RULE",
          "DUPLICATE_FILTER",
          "SCHEDULED_SEND_IN_PROGRESS",
          "DRAFT_ALREADY_EXISTS",
          "QUERY_TIMEOUT",
          "RATE_LIMIT_EXCEEDED",
          "QUOTA_EXCEEDED",
          "INTERNAL_ERROR"
        ],
        "description": "Codes that the Inbox API can return, as found in the code. Branch on `code`, never on `error`. The HTTP status is derived from the code (unknown business codes are 400)."
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "error"
        ],
        "description": "Every error of the API has this shape, except unknown paths with a valid key, which get the default Express HTML 404 page.",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "error": {
            "type": "string",
            "description": "Human readable."
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional context: faulty fields, bounds, ids."
          }
        }
      },
      "EmailAddress": {
        "type": "object",
        "required": [
          "email",
          "name"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "An address as returned by the API. `name` is null when unknown."
      },
      "EmailAddressInput": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Attachment": {
        "type": "object",
        "required": [
          "filename",
          "size",
          "mimeType"
        ],
        "description": "Metadata only. There is no download endpoint in this API.",
        "properties": {
          "filename": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "description": "Bytes, 0 when unknown."
          },
          "mimeType": {
            "type": "string",
            "description": "`application/octet-stream` when unknown."
          }
        }
      },
      "LabelRef": {
        "type": "object",
        "required": [
          "id",
          "name",
          "color",
          "isAiLabel"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "isAiLabel": {
            "type": "boolean"
          }
        }
      },
      "Label": {
        "type": "object",
        "required": [
          "id",
          "name",
          "color",
          "isAiLabel",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "description": "Free string (usually a hex color)."
          },
          "isAiLabel": {
            "type": "boolean",
            "description": "Applied by the AI pipeline, managed through `/ai-label-rules`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EmailListItem": {
        "type": "object",
        "description": "Email as returned by `GET /emails` and `GET /emails/search`. Never contains the body.",
        "required": [
          "attachments",
          "cc",
          "date",
          "folderId",
          "from",
          "hasAttachments",
          "id",
          "inReplyTo",
          "isDraft",
          "isRead",
          "isStarred",
          "mailboxId",
          "messageId",
          "references",
          "snippet",
          "subject",
          "tags",
          "threadId",
          "to",
          "waitingForReply"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Inbox id of the email."
          },
          "mailboxId": {
            "type": "string"
          },
          "folderId": {
            "type": "string"
          },
          "messageId": {
            "type": "string",
            "description": "RFC 5322 Message-ID header. Needed to reply in a thread."
          },
          "threadId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Provider conversation id (Gmail, Microsoft), null for IMAP."
          },
          "subject": {
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/EmailAddress"
          },
          "to": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddress"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddress"
            }
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "snippet": {
            "type": "string",
            "description": "Short text preview (about 200 characters)."
          },
          "isRead": {
            "type": "boolean"
          },
          "isStarred": {
            "type": "boolean"
          },
          "isDraft": {
            "type": "boolean"
          },
          "waitingForReply": {
            "type": "boolean",
            "description": "Estimate that a sent email still expects an answer."
          },
          "hasAttachments": {
            "type": "boolean"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "inReplyTo": {
            "type": [
              "string",
              "null"
            ]
          },
          "references": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LabelRef"
            },
            "description": "Inbox labels applied to the email (manual and AI)."
          }
        }
      },
      "Email": {
        "type": "object",
        "description": "Full metadata of an email or a draft (`GET /emails/{emailId}`, `PATCH /emails/{emailId}`, drafts). Has `bcc` and provider `labels`, has no `tags`. Never contains the body.",
        "required": [
          "attachments",
          "bcc",
          "cc",
          "date",
          "folderId",
          "from",
          "hasAttachments",
          "id",
          "inReplyTo",
          "isAutoForward",
          "isAutoReply",
          "isDraft",
          "isRead",
          "isStarred",
          "labels",
          "mailboxId",
          "messageId",
          "references",
          "scheduledSendAt",
          "scheduledStatus",
          "snippet",
          "subject",
          "threadId",
          "to",
          "waitingForReply"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Inbox id of the email."
          },
          "mailboxId": {
            "type": "string"
          },
          "folderId": {
            "type": "string"
          },
          "messageId": {
            "type": "string",
            "description": "RFC 5322 Message-ID header. Needed to reply in a thread."
          },
          "threadId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Provider conversation id (Gmail, Microsoft), null for IMAP."
          },
          "subject": {
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/EmailAddress"
          },
          "to": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddress"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddress"
            }
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "snippet": {
            "type": "string",
            "description": "Short text preview (about 200 characters)."
          },
          "isRead": {
            "type": "boolean"
          },
          "isStarred": {
            "type": "boolean"
          },
          "isDraft": {
            "type": "boolean"
          },
          "waitingForReply": {
            "type": "boolean",
            "description": "Estimate that a sent email still expects an answer."
          },
          "hasAttachments": {
            "type": "boolean"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "inReplyTo": {
            "type": [
              "string",
              "null"
            ]
          },
          "references": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddress"
            },
            "description": "Only known on sent messages and drafts."
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Provider labels (for example Gmail `INBOX`, `UNREAD`, `IMPORTANT`), NOT inbox labels."
          },
          "isAutoReply": {
            "type": "boolean",
            "description": "Sent automatically by an auto-reply."
          },
          "isAutoForward": {
            "type": "boolean",
            "description": "Sent automatically by an auto-forward rule."
          },
          "scheduledStatus": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "PENDING",
              "QUEUED",
              "SENDING",
              "FAILED",
              null
            ],
            "description": "For a scheduled draft: its sending state."
          },
          "scheduledSendAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "EmailPage": {
        "type": "object",
        "required": [
          "items",
          "nextCursor",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailListItem"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor of the last item of the page; null only when the page is empty. Use `hasMore` to stop."
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "ThreadAddress": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "description": "Raw stored address: `name` may be absent."
      },
      "ThreadMessage": {
        "type": "object",
        "description": "One message of a thread. Contract fields are listed as required; the other fields (attachmentsS3, magicReply*) are internal, not part of the contract, and may be removed.",
        "required": [
          "id",
          "mailboxId",
          "messageId",
          "references",
          "fromAddress",
          "toAddresses",
          "date",
          "subject",
          "isMe"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "mailboxId": {
            "type": "string"
          },
          "messageId": {
            "type": "string"
          },
          "references": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "fromAddress": {
            "type": "string"
          },
          "fromName": {
            "type": "string"
          },
          "toAddresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadAddress"
            }
          },
          "ccAddresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadAddress"
            }
          },
          "bccAddresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadAddress"
            }
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "subject": {
            "type": "string"
          },
          "html": {
            "type": "string",
            "description": "HTML body; inline images rewritten to 15 minute URLs."
          },
          "text": {
            "type": "string"
          },
          "isMe": {
            "type": "boolean",
            "description": "Sent from the mailbox address itself."
          },
          "isDraft": {
            "type": "boolean",
            "description": "Present only when true."
          },
          "isAutoReply": {
            "type": "boolean",
            "description": "Present only when true."
          },
          "isAutoForward": {
            "type": "boolean",
            "description": "Present only when true."
          },
          "attachmentsS3": {
            "type": "array",
            "deprecated": true,
            "description": "Internal field, not part of the contract (may be removed).",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "magicReplyConfidence": {
            "type": "number",
            "deprecated": true,
            "description": "Internal field, not part of the contract (may be removed)."
          },
          "magicReplyReasoning": {
            "type": "string",
            "deprecated": true,
            "description": "Internal field, not part of the contract (may be removed)."
          },
          "magicReplyContextSource": {
            "type": "string",
            "enum": [
              "label",
              "global"
            ],
            "deprecated": true,
            "description": "Internal field, not part of the contract (may be removed)."
          }
        }
      },
      "EmailThread": {
        "type": "object",
        "required": [
          "emailId",
          "thread"
        ],
        "properties": {
          "emailId": {
            "type": "string"
          },
          "html": {
            "type": "string",
            "description": "Body of the requested email, if any."
          },
          "text": {
            "type": "string"
          },
          "thread": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadMessage"
            },
            "description": "Oldest first."
          }
        }
      },
      "UpdateEmailRequest": {
        "type": "object",
        "description": "At least one of the two fields.",
        "properties": {
          "isRead": {
            "type": "boolean"
          },
          "isStarred": {
            "type": "boolean"
          }
        }
      },
      "BulkEmailsRequest": {
        "type": "object",
        "required": [
          "action",
          "emailIds"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "markRead",
              "delete",
              "applyLabel",
              "removeLabel"
            ],
            "description": "`delete` moves to the trash (never permanent)."
          },
          "emailIds": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "string"
            },
            "description": "Up to 500 ids, but see the per minute limit (60 on FREE)."
          },
          "isRead": {
            "type": "boolean",
            "description": "Required for `markRead`."
          },
          "labelId": {
            "type": "string",
            "description": "Required for `applyLabel` and `removeLabel`."
          }
        }
      },
      "BulkMarkReadResult": {
        "type": "object",
        "required": [
          "updatedIds",
          "unchangedIds",
          "skippedIds"
        ],
        "properties": {
          "updatedIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "unchangedIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skippedIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isRead": {
            "type": "boolean",
            "description": "Absent when no valid id was given."
          }
        }
      },
      "BulkDeleteResult": {
        "type": "object",
        "required": [
          "deletedIds",
          "skippedIds",
          "noTrashIds"
        ],
        "properties": {
          "deletedIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skippedIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Unknown, other workspace, already gone or already in trash."
          },
          "noTrashIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "BulkLabelResult": {
        "type": "object",
        "required": [
          "labelId",
          "emailIds",
          "skippedIds",
          "updatedCount"
        ],
        "properties": {
          "labelId": {
            "type": "string"
          },
          "emailIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Processed emails of the workspace, deduplicated."
          },
          "skippedIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "updatedCount": {
            "type": "integer",
            "description": "Rows actually written (applied or removed)."
          }
        }
      },
      "SignatureChoice": {
        "type": "string",
        "minLength": 1,
        "maxLength": 128,
        "default": "default",
        "description": "`default` (or omitted): default signature of the sending identity. `none`: no signature, and a signature already in the body is removed. Otherwise a signature id from `GET /signatures` (unknown id: 404 SIGNATURE_NOT_FOUND). A body already signed is not signed twice."
      },
      "SendEmailRequest": {
        "type": "object",
        "required": [
          "mailboxId",
          "to",
          "body"
        ],
        "properties": {
          "mailboxId": {
            "type": "string",
            "minLength": 1,
            "description": "Sending mailbox (`GET /mailboxes`)."
          },
          "from": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EmailAddressInput"
              }
            ],
            "description": "Optional send-as alias; must be a verified alias of the mailbox, otherwise 400 INVALID_SENDER_ALIAS."
          },
          "to": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 2000,
            "default": "",
            "pattern": "^[^\\r\\n]*$",
            "description": "No line breaks."
          },
          "body": {
            "type": "object",
            "description": "HTML, text or both. Both may be omitted (empty body).",
            "properties": {
              "html": {
                "type": "string"
              },
              "text": {
                "type": "string"
              }
            }
          },
          "inReplyTo": {
            "type": "string",
            "maxLength": 998,
            "pattern": "^[^\\r\\n]*$",
            "description": "`messageId` of the email being answered."
          },
          "references": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 998,
              "pattern": "^[^\\r\\n]*$"
            },
            "description": "References of the answered email followed by its `messageId`."
          },
          "signature": {
            "$ref": "#/components/schemas/SignatureChoice"
          }
        }
      },
      "SendEmailResult": {
        "type": "object",
        "required": [
          "messageId",
          "threadId"
        ],
        "properties": {
          "messageId": {
            "type": "string",
            "description": "RFC Message-ID of the sent message."
          },
          "threadId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateDraftRequest": {
        "type": "object",
        "required": [
          "mailboxId",
          "body"
        ],
        "properties": {
          "mailboxId": {
            "type": "string",
            "minLength": 1
          },
          "to": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            },
            "default": []
          },
          "cc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAddressInput"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 2000,
            "default": "",
            "pattern": "^[^\\r\\n]*$"
          },
          "body": {
            "type": "object",
            "properties": {
              "html": {
                "type": "string"
              },
              "text": {
                "type": "string"
              }
            },
            "description": "`text` feeds the preview snippet."
          },
          "inReplyTo": {
            "type": "string",
            "maxLength": 998,
            "pattern": "^[^\\r\\n]*$",
            "description": "Joins the conversation; overwrites an existing draft reply to the same message."
          },
          "references": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 998
            }
          },
          "signature": {
            "$ref": "#/components/schemas/SignatureChoice"
          }
        }
      },
      "Mailbox": {
        "type": "object",
        "required": [
          "id",
          "email",
          "name",
          "picture",
          "provider",
          "isActive",
          "createdAt",
          "lastSyncAt",
          "syncError",
          "backwardSyncComplete"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "picture": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "GOOGLE",
              "MICROSOFT",
              "IMAP"
            ]
          },
          "isActive": {
            "type": "boolean",
            "description": "false: sending refused (MAILBOX_INACTIVE)."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSyncAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "syncError": {
            "type": [
              "string",
              "null"
            ]
          },
          "backwardSyncComplete": {
            "type": "boolean"
          }
        }
      },
      "Signature": {
        "type": "object",
        "required": [
          "id",
          "name",
          "mailboxId",
          "aliasEmail",
          "isDefault",
          "position",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "mailboxId": {
            "type": [
              "string",
              "null"
            ]
          },
          "aliasEmail": {
            "type": [
              "string",
              "null"
            ]
          },
          "isDefault": {
            "type": "boolean"
          },
          "position": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateLabelRequest": {
        "type": "object",
        "required": [
          "name",
          "color"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "color": {
            "type": "string",
            "minLength": 1,
            "maxLength": 30
          }
        }
      },
      "UpdateLabelRequest": {
        "type": "object",
        "description": "At least one field.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "color": {
            "type": "string",
            "minLength": 1,
            "maxLength": 30
          }
        }
      },
      "AiLabelRule": {
        "type": "object",
        "required": [
          "id",
          "label",
          "condition",
          "autoDraftEnabled",
          "autoReplyEnabled",
          "autoReplyConfidenceThreshold",
          "autoReplyDelayMinutes",
          "autoReplyNotifyOnSend",
          "hideFromInbox",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "$ref": "#/components/schemas/LabelRef"
          },
          "condition": {
            "type": "string",
            "maxLength": 500
          },
          "autoDraftEnabled": {
            "type": "boolean"
          },
          "autoReplyEnabled": {
            "type": "boolean"
          },
          "autoReplyConfidenceThreshold": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "autoReplyDelayMinutes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 15
          },
          "autoReplyNotifyOnSend": {
            "type": "boolean"
          },
          "hideFromInbox": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateAiLabelRuleRequest": {
        "type": "object",
        "required": [
          "name",
          "color",
          "condition"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "color": {
            "type": "string",
            "description": "Not validated (any string)."
          },
          "condition": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "Plain language condition, written like a brief to a colleague."
          },
          "autoDraftEnabled": {
            "type": "boolean",
            "default": false
          },
          "autoReplyEnabled": {
            "type": "boolean",
            "default": false,
            "description": "Makes the inbox send replies on your behalf."
          },
          "autoReplyConfidenceThreshold": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 85
          },
          "autoReplyDelayMinutes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 15,
            "default": 0
          },
          "autoReplyNotifyOnSend": {
            "type": "boolean",
            "default": true
          },
          "hideFromInbox": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "UpdateAiLabelRuleRequest": {
        "type": "object",
        "description": "All optional, at least one field.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "color": {
            "type": "string"
          },
          "condition": {
            "type": "string",
            "maxLength": 500
          },
          "autoDraftEnabled": {
            "type": "boolean"
          },
          "autoReplyEnabled": {
            "type": "boolean"
          },
          "autoReplyConfidenceThreshold": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "autoReplyDelayMinutes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 15
          },
          "autoReplyNotifyOnSend": {
            "type": "boolean"
          },
          "hideFromInbox": {
            "type": "boolean"
          }
        }
      },
      "FilterCondition": {
        "type": "object",
        "required": [
          "id",
          "label",
          "type",
          "value"
        ],
        "description": "`label` is the FIELD (historical name, unrelated to email labels). Valid operators per field: mailbox: is, is_not (mailbox id); label: contains, not_contains (manual label id); ai_label: contains, not_contains (AI label id); keyword_subject: contains, not_contains (text); sender_address: equals, contains; sender_domain: equals (exact domain after @), contains; date: before, after (ISO 8601), between (`start|end`, inclusive); read_status and has_attachment: is_true, is_false (`value` ignored, send \"\"). All text matches are case insensitive. Known issue: an invalid date makes the condition match everything instead of being rejected.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Free client side id."
          },
          "label": {
            "type": "string",
            "enum": [
              "mailbox",
              "label",
              "ai_label",
              "keyword_subject",
              "sender_address",
              "sender_domain",
              "date",
              "read_status",
              "has_attachment"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "contains",
              "not_contains",
              "equals",
              "before",
              "after",
              "between",
              "is_true",
              "is_false"
            ]
          },
          "value": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "FilterGroup": {
        "type": "object",
        "required": [
          "id"
        ],
        "description": "Group of nodes. `_and` and `_or` may both be present (they are then combined with AND). The `id` is required in views; in `?filters=` it is tolerated when missing.",
        "properties": {
          "id": {
            "type": "string"
          },
          "_and": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilterNode"
            }
          },
          "_or": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilterNode"
            }
          }
        }
      },
      "FilterNode": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/FilterCondition"
          },
          {
            "$ref": "#/components/schemas/FilterGroup"
          }
        ],
        "description": "Bounds: 5 levels, 50 conditions in total, 500 characters per value, 8192 bytes for the raw `filters` parameter."
      },
      "ViewFilters": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/FilterNode"
          },
          {
            "type": "object",
            "maxProperties": 0
          }
        ],
        "description": "A filter tree, or `{}` for a view without filter."
      },
      "View": {
        "type": "object",
        "required": [
          "id",
          "name",
          "icon",
          "filters",
          "mailboxIds",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "icon": {
            "type": [
              "string",
              "null"
            ],
            "description": "Emoji, possibly as an HTML numeric entity."
          },
          "filters": {
            "$ref": "#/components/schemas/ViewFilters"
          },
          "mailboxIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Mailboxes the view is restricted to; empty means all. Read only."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateViewRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "icon": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 32,
            "description": "An emoji or a numeric HTML entity; no markup."
          },
          "filters": {
            "$ref": "#/components/schemas/ViewFilters"
          }
        }
      },
      "UpdateViewRequest": {
        "type": "object",
        "description": "At least one field. `filters` replaces the whole tree.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "icon": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 32
          },
          "filters": {
            "$ref": "#/components/schemas/ViewFilters"
          }
        }
      },
      "InboxFilter": {
        "type": "object",
        "required": [
          "id",
          "type",
          "value",
          "label",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "sender",
              "domain",
              "subject",
              "label"
            ]
          },
          "value": {
            "type": "string"
          },
          "label": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/LabelRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The targeted label when `type` is `label`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateInboxFilterRequest": {
        "type": "object",
        "required": [
          "type",
          "value"
        ],
        "description": "`sender`: an email address, exact match, case insensitive. `domain`: a domain such as example.com (leading @ dropped). `subject`: text contained in the subject. `label`: id of a manual or AI label of the workspace.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "sender",
              "domain",
              "subject",
              "label"
            ]
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          }
        }
      },
      "UpdateInboxFilterRequest": {
        "type": "object",
        "description": "At least one field; revalidated as a whole.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "sender",
              "domain",
              "subject",
              "label"
            ]
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          }
        }
      },
      "AutoForwardRule": {
        "type": "object",
        "required": [
          "id",
          "conditionField",
          "conditionValue",
          "forwardTo",
          "mode",
          "isActive",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "conditionField": {
            "type": "string",
            "enum": [
              "label",
              "sender_contains",
              "sender_equals",
              "subject_contains",
              "subject_equals"
            ]
          },
          "conditionValue": {
            "type": "string"
          },
          "forwardTo": {
            "type": "string",
            "format": "email"
          },
          "mode": {
            "type": "string",
            "enum": [
              "normal",
              "invisible"
            ]
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateAutoForwardRuleRequest": {
        "type": "object",
        "required": [
          "conditionValue",
          "forwardTo"
        ],
        "properties": {
          "conditionField": {
            "type": "string",
            "default": "label",
            "enum": [
              "label",
              "sender_contains",
              "sender_equals",
              "subject_contains",
              "subject_equals"
            ],
            "description": "`label`: exact, case insensitive match on the NAME of any label of the email. `sender_*`: compared to the sender address and name. `subject_*`: subject."
          },
          "conditionValue": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "forwardTo": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "mode": {
            "type": "string",
            "enum": [
              "normal",
              "invisible"
            ],
            "default": "normal",
            "description": "`normal`: `Fwd:` subject and quoted header. `invisible`: original subject and body, `Reply-To` set to the original sender."
          },
          "isActive": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "UpdateAutoForwardRuleRequest": {
        "type": "object",
        "description": "At least one field; `conditionValue` and `forwardTo` cannot be emptied.",
        "properties": {
          "conditionField": {
            "type": "string",
            "enum": [
              "label",
              "sender_contains",
              "sender_equals",
              "subject_contains",
              "subject_equals"
            ]
          },
          "conditionValue": {
            "type": "string",
            "maxLength": 255
          },
          "forwardTo": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "mode": {
            "type": "string",
            "enum": [
              "normal",
              "invisible"
            ]
          },
          "isActive": {
            "type": "boolean"
          }
        }
      },
      "ForwardLog": {
        "type": "object",
        "required": [
          "id",
          "emailId",
          "destination",
          "mode",
          "status",
          "error",
          "forwardedMessageId",
          "createdAt",
          "email"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "emailId": {
            "type": "string"
          },
          "destination": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "normal",
              "invisible"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "failed"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "forwardedMessageId": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "email": {
            "type": "object",
            "required": [
              "id",
              "subject",
              "from",
              "date"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "subject": {
                "type": "string"
              },
              "from": {
                "$ref": "#/components/schemas/EmailAddress"
              },
              "date": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "WebhookEventName": {
        "type": "string",
        "enum": [
          "email.received",
          "email.updated",
          "email.deleted",
          "draft.sent",
          "label.applied",
          "mailbox.sync_failed"
        ]
      },
      "WebhookEnvelope": {
        "type": "object",
        "required": [
          "event",
          "createdAt",
          "data"
        ],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/WebhookEventName"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time of THIS delivery attempt (changes on retries)."
          },
          "data": {
            "type": "object"
          }
        }
      },
      "EmailReceivedData": {
        "type": "object",
        "required": [
          "emailId",
          "mailboxId",
          "folderType"
        ],
        "properties": {
          "emailId": {
            "type": "string"
          },
          "mailboxId": {
            "type": "string"
          },
          "folderType": {
            "type": "string",
            "const": "INBOX"
          }
        }
      },
      "EmailUpdatedData": {
        "type": "object",
        "required": [
          "emailId",
          "changes"
        ],
        "properties": {
          "emailId": {
            "type": "string"
          },
          "changes": {
            "type": "object",
            "description": "Either `isRead` or `isStarred`.",
            "properties": {
              "isRead": {
                "type": "boolean"
              },
              "isStarred": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "EmailDeletedData": {
        "type": "object",
        "required": [
          "emailId"
        ],
        "properties": {
          "emailId": {
            "type": "string"
          }
        }
      },
      "DraftSentData": {
        "type": "object",
        "required": [
          "mailboxId",
          "messageId",
          "threadId",
          "to",
          "subject"
        ],
        "properties": {
          "mailboxId": {
            "type": "string"
          },
          "messageId": {
            "type": "string"
          },
          "threadId": {
            "type": [
              "string",
              "null"
            ]
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Addresses of `to` only (cc and bcc are not listed)."
          },
          "subject": {
            "type": "string"
          }
        }
      },
      "LabelAppliedData": {
        "type": "object",
        "required": [
          "emailId",
          "tagId",
          "tagName",
          "isAiLabel"
        ],
        "properties": {
          "emailId": {
            "type": "string"
          },
          "tagId": {
            "type": "string",
            "description": "The label id."
          },
          "tagName": {
            "type": "string"
          },
          "isAiLabel": {
            "type": "boolean"
          }
        }
      },
      "MailboxSyncFailedData": {
        "type": "object",
        "required": [
          "mailboxId",
          "error",
          "failCount",
          "deactivated"
        ],
        "properties": {
          "mailboxId": {
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "failCount": {
            "type": "integer"
          },
          "deactivated": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
