# API reference

> Every endpoint of the Maylee REST API, with parameters, request and response schemas, examples and code samples, generated from its OpenAPI specification.

Source: https://docs.maylee.app/api-reference

```txt
Base URL        https://api.maylee.app/api/v1
Authentication  Authorization: Bearer mk_...
Content type    application/json
```

Each endpoint page below is generated from the [OpenAPI 3.1 specification](/openapi.json) of the API, which the Maylee backend produces from its own code: parameters, request and response schemas, examples and code samples in cURL, JavaScript and Python. The same document is served without authentication on `GET https://api.maylee.app/api/v1/openapi.json`, so that you can generate a client before you even have a key.

## Conventions

* **Scope**: the scope the key must hold, stated on every endpoint. Without it: `403 INSUFFICIENT_SCOPE`. Endpoints marked **Send emails** also need that permission on the key. See [Authentication](/authentication).
* **Cost**: one quota unit per call, except bulk operations, which cost one unit per email. See [Rate limits and quotas](/rate-limits).
* Identifiers are opaque strings. Dates are ISO 8601, in UTC.
* A resource that belongs to another workspace returns **404**, never 403: a 403 would confirm that it exists.
* Errors that can happen on every endpoint are not repeated on each page: `401` (missing, invalid, revoked or expired key), `403 WORKSPACE_SUSPENDED`, `429` (rate limit or monthly quota), `413 PAYLOAD_TOO_LARGE` and `500 INTERNAL_ERROR`. See [Errors](/errors).

## Endpoints

### Emails

List, search and read the emails of every connected mailbox, mark them read or starred, label them, and move them to the trash. Bodies are fetched on demand, and nothing is ever deleted permanently.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /emails`](/api-reference/emails/list-emails.md) | read | List emails |
| [`GET /emails/search`](/api-reference/emails/search-emails.md) | read | Full-text search |
| [`GET /emails/{emailId}`](/api-reference/emails/get-email.md) | read | Get an email |
| [`GET /emails/{emailId}/body`](/api-reference/emails/get-email-body.md) | read | Get an email body and its thread |
| [`POST /emails/bulk`](/api-reference/emails/bulk-update-emails.md) | write | Bulk mark-read, delete, apply or remove a label |
| [`POST /emails/{emailId}/labels/{labelId}`](/api-reference/emails/apply-label-to-email.md) | write | Apply a label to an email |
| [`PATCH /emails/{emailId}`](/api-reference/emails/update-email.md) | write | Update read or starred state |
| [`DELETE /emails/{emailId}`](/api-reference/emails/trash-email.md) | write | Move an email to trash |
| [`DELETE /emails/{emailId}/labels/{labelId}`](/api-reference/emails/remove-label-from-email.md) | write | Remove a label from an email |

### Drafts

Create drafts that a person reviews and sends from the Maylee app, or send an email immediately.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /drafts`](/api-reference/drafts/list-drafts.md) | read | List drafts |
| [`GET /drafts/{draftId}`](/api-reference/drafts/get-draft.md) | read | Get a draft |
| [`POST /drafts`](/api-reference/drafts/create-draft.md) | write | Create a draft |
| [`POST /drafts/send`](/api-reference/drafts/send-email.md) | write + Send emails | Send an email |

### Mailboxes

Connected mailboxes, read-only: connecting one goes through OAuth or credentials in the Maylee app, never through a key.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /mailboxes`](/api-reference/mailboxes/list-mailboxes.md) | read | List connected mailboxes |

### Signatures

Signatures of the workspace, read-only: they are written in the Maylee app. Use an id as `signature` on a send or a draft; without it, Maylee signs like the app would.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /signatures`](/api-reference/signatures/list-signatures.md) | read | List signatures |

### Labels

Manual labels are created here and applied by people, or by you through the API. AI labels show up in the same list with `isAiLabel: true`; they are renamed or deleted through their AI label rule.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /labels`](/api-reference/labels/list-labels.md) | read | List labels |
| [`GET /labels/{labelId}`](/api-reference/labels/get-label.md) | read | Get a label |
| [`POST /labels`](/api-reference/labels/create-label.md) | write | Create a label |
| [`PATCH /labels/{labelId}`](/api-reference/labels/update-label.md) | write | Rename or recolor a label |
| [`DELETE /labels/{labelId}`](/api-reference/labels/delete-label.md) | write | Delete a label |

### AI label rules

An AI label plus a condition written in plain language. Maylee reads each incoming email and applies the label when the condition holds. A rule can also prepare replies (auto-draft) and send them (auto-reply).

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /ai-label-rules`](/api-reference/ai-label-rules/list-ai-label-rules.md) | read | List AI label rules |
| [`GET /ai-label-rules/{ruleId}`](/api-reference/ai-label-rules/get-ai-label-rule.md) | read | Get an AI label rule |
| [`POST /ai-label-rules`](/api-reference/ai-label-rules/create-ai-label-rule.md) | write + Send emails | Create an AI label rule |
| [`POST /ai-label-rules/backfill`](/api-reference/ai-label-rules/classify-existing-emails.md) | write | Classify existing emails with the AI label rules |
| [`PATCH /ai-label-rules/{ruleId}`](/api-reference/ai-label-rules/update-ai-label-rule.md) | write + Send emails | Update an AI label rule |
| [`DELETE /ai-label-rules/{ruleId}`](/api-reference/ai-label-rules/delete-ai-label-rule.md) | write | Delete an AI label rule |

### Views

Saved filter trees, shown in the Maylee sidebar. Apply one with `?viewId=` on `GET /emails`.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /views`](/api-reference/views/list-views.md) | read | List saved views |
| [`GET /views/{viewId}`](/api-reference/views/get-view.md) | read | Get a view |
| [`POST /views`](/api-reference/views/create-view.md) | write | Create a view |
| [`PATCH /views/{viewId}`](/api-reference/views/update-view.md) | write | Update a view |
| [`DELETE /views/{viewId}`](/api-reference/views/delete-view.md) | write | Delete a view |

### Inbox filters

Hide matching emails from the main inbox without moving them. Filters are evaluated when listing, so they apply to past emails too.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /filters`](/api-reference/inbox-filters/list-inbox-filters.md) | read | List inbox filters |
| [`GET /filters/{filterId}`](/api-reference/inbox-filters/get-inbox-filter.md) | read | Get an inbox filter |
| [`POST /filters`](/api-reference/inbox-filters/create-inbox-filter.md) | write | Create an inbox filter |
| [`PATCH /filters/{filterId}`](/api-reference/inbox-filters/update-inbox-filter.md) | write | Update an inbox filter |
| [`DELETE /filters/{filterId}`](/api-reference/inbox-filters/delete-inbox-filter.md) | write | Delete an inbox filter |

### Auto-forward rules

Forward every incoming email that matches a condition to another address. Managing rules requires the Send emails permission on the key.

| Endpoint | Scope | Summary |
| --- | --- | --- |
| [`GET /auto-forward-rules`](/api-reference/auto-forward-rules/list-auto-forward-rules.md) | read | List auto-forward rules |
| [`GET /auto-forward-rules/{ruleId}`](/api-reference/auto-forward-rules/get-auto-forward-rule.md) | read | Get an auto-forward rule |
| [`GET /auto-forward-rules/{ruleId}/logs`](/api-reference/auto-forward-rules/list-auto-forward-rule-logs.md) | read | List the forwarding attempts of a rule |
| [`POST /auto-forward-rules`](/api-reference/auto-forward-rules/create-auto-forward-rule.md) | write + Send emails | Create an auto-forward rule |
| [`PATCH /auto-forward-rules/{ruleId}`](/api-reference/auto-forward-rules/update-auto-forward-rule.md) | write + Send emails | Update an auto-forward rule |
| [`DELETE /auto-forward-rules/{ruleId}`](/api-reference/auto-forward-rules/delete-auto-forward-rule.md) | write + Send emails | Delete an auto-forward rule |

## Not available through the API yet

So that you do not look for them:

* **Downloading or sending attachments.** Only their metadata is exposed.
* **Connecting a mailbox**, or restricting a view to specific mailboxes. Both are done in the app.
* **Editing or deleting drafts.** Drafts can be created, listed and read; a person changes or discards them in the app. `POST /drafts/send` sends immediately and does not create a draft.
* **Moving an email between folders**, other than to the trash.
* **Permanent deletion.** By design: a mistake can always be undone from the trash.
* **Managing API keys with a key.** Keys are created and revoked in the app, by owners and admins, so that a leaked key cannot mint new ones.
* **Webhooks.** They are [coming soon](/webhooks).
