> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenantcore.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Mailboxes

> Provision shared mailboxes, update send limits, and query daily usage.

## Overview

A mailbox in TenantCore is a shared mailbox provisioned on a verified custom domain in a Microsoft 365 tenant. Each domain supports up to 3 mailboxes. Mailboxes are created as shared mailboxes in Exchange Online and do not consume a Microsoft 365 license.

Send limits are opt-in, not mandatory. Mailboxes are created without an enforced send limit by design. If you have fewer domains and want higher per-mailbox volume, you can leave limits unenforced and mailboxes will send without restriction.

Send limit enforcement is a two-step process:

1. **Set the limit** — use `PATCH /v1/tenants/{tenant_id}/mailboxes/{mailbox_id}` to store a `daily_send_limit` value per mailbox
2. **Provision enforcement** — use `POST /v1/tenants/{tenant_id}/mailbox-limits` to write the Exchange transport rule that enforces it

Setting a `daily_send_limit` on a mailbox without provisioning enforcement saves the value but does not restrict sending. The Exchange transport rule is what enforces the ceiling at the infrastructure level.

<Note>
  Exchange Online propagation after provisioning a mailbox takes 2 to 5 minutes. The mailbox will not be immediately available for sending after the API call returns.
</Note>

***

## List mailboxes

Returns all mailboxes across all domains on a tenant.

```
GET /v1/tenants/{tenant_id}/mailboxes
```

**Path parameters**

| Parameter   | Type   | Description               |
| ----------- | ------ | ------------------------- |
| `tenant_id` | string | The Microsoft tenant GUID |

**Example request**

```bash theme={null}
curl https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailboxes \
  -H "Authorization: Bearer tc_live_your_key"
```

**Example response**

```json theme={null}
{
  "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "mailboxes": [
    {
      "id": "uuid",
      "display_name": "John Doe",
      "primary_smtp": "john@mail.acmecorp.com",
      "user_principal_name": "john@mail.acmecorp.com",
      "mail_nickname": "john",
      "account_enabled": true,
      "daily_send_limit": 25,
      "sends_today": 12,
      "blocked_at": null,
      "created_at": "2025-01-20T10:00:00Z",
      "domain_name": "mail.acmecorp.com",
      "tenant_name": "Acme Corp"
    }
  ],
  "count": 1
}
```

**Response fields**

| Field              | Type              | Description                                                           |
| ------------------ | ----------------- | --------------------------------------------------------------------- |
| `primary_smtp`     | string            | The mailbox email address                                             |
| `account_enabled`  | boolean           | Whether the account is enabled in Azure AD                            |
| `daily_send_limit` | number            | Configured daily send cap (1 to 25)                                   |
| `sends_today`      | number            | Emails sent today as reported by Exchange message trace               |
| `blocked_at`       | timestamp or null | When the mailbox was blocked by enforcement, or `null` if not blocked |

**Errors**

| Status | Code               | Description                                             |
| ------ | ------------------ | ------------------------------------------------------- |
| `404`  | `tenant_not_found` | Tenant does not exist or belongs to a different account |

***

## Provision mailboxes

Creates one or more shared mailboxes on a verified domain. Up to 3 mailboxes per domain. All mailboxes in the request must belong to the same domain.

```
POST /v1/tenants/{tenant_id}/mailboxes
```

**Path parameters**

| Parameter   | Type   | Description               |
| ----------- | ------ | ------------------------- |
| `tenant_id` | string | The Microsoft tenant GUID |

**Request body**

```json theme={null}
{
  "domain": "mail.acmecorp.com",
  "account_password": "SecureP@ssw0rd!",
  "mailboxes": [
    { "name": "John Doe", "email": "john@mail.acmecorp.com" },
    { "name": "Jane Doe", "email": "jane@mail.acmecorp.com" }
  ]
}
```

| Field               | Type   | Required | Description                                                                                                        |
| ------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `domain`            | string | Yes      | The verified domain to create mailboxes on                                                                         |
| `account_password`  | string | Yes      | Initial password for the underlying user account. Min 8 characters. Must meet Microsoft's complexity requirements. |
| `mailboxes`         | array  | Yes      | List of mailboxes to create. Max 3 total per domain including existing.                                            |
| `mailboxes[].name`  | string | Yes      | Display name for the mailbox                                                                                       |
| `mailboxes[].email` | string | Yes      | Full email address. Must end with `@{domain}`.                                                                     |

**Example request**

```bash theme={null}
curl -X POST \
  https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailboxes \
  -H "Authorization: Bearer tc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "mail.acmecorp.com",
    "account_password": "SecureP@ssw0rd!",
    "mailboxes": [
      { "name": "Sales Outreach", "email": "sales@mail.acmecorp.com" }
    ]
  }'
```

**Example response**

```json theme={null}
{
  "created_count": 1,
  "exists_count": 0,
  "failed_count": 0,
  "results": [
    {
      "status": "created",
      "name": "Sales Outreach",
      "email": "sales@mail.acmecorp.com",
      "details": {
        "display_name": "Sales Outreach",
        "primary_smtp": "sales@mail.acmecorp.com",
        "user_principal_name": "sales@mail.acmecorp.com",
        "alias": "sales"
      }
    }
  ]
}
```

**Result statuses per mailbox**

| Status    | Meaning                                                             |
| --------- | ------------------------------------------------------------------- |
| `created` | Mailbox was successfully provisioned                                |
| `exists`  | Mailbox already exists, no action taken                             |
| `failed`  | Provisioning failed for this mailbox, check `error` field in result |

**Prerequisites**

* The domain must be verified in Microsoft 365
* Exchange bootstrap must be `ready` on the tenant
* SMTP AUTH must be enabled on the tenant

**Errors**

| Status | Code                    | Description                                              |
| ------ | ----------------------- | -------------------------------------------------------- |
| `400`  | `mailbox_limit_reached` | Domain already has 3 mailboxes                           |
| `400`  | —                       | Invalid email domain, duplicate emails, or weak password |
| `404`  | `tenant_not_found`      | Tenant does not exist or belongs to a different account  |
| `404`  | `domain_not_found`      | Domain not registered on this tenant                     |

***

## Update mailbox

Updates the display name or daily send limit of a mailbox. Updating `daily_send_limit` stores the value in TenantCore but does not provision Exchange enforcement on its own. To activate enforcement at the Exchange level, call `POST /v1/tenants/{tenant_id}/mailbox-limits` after updating the limit.

```
PATCH /v1/tenants/{tenant_id}/mailboxes/{mailbox_id}
```

**Path parameters**

| Parameter    | Type   | Description                                       |
| ------------ | ------ | ------------------------------------------------- |
| `tenant_id`  | string | The Microsoft tenant GUID                         |
| `mailbox_id` | string | The TenantCore mailbox UUID (from list mailboxes) |

**Request body**

```json theme={null}
{
  "display_name": "New Display Name",
  "daily_send_limit": 20
}
```

| Field              | Type   | Required | Description                                                                                                           |
| ------------------ | ------ | -------- | --------------------------------------------------------------------------------------------------------------------- |
| `display_name`     | string | No       | New display name for the mailbox                                                                                      |
| `daily_send_limit` | number | No       | Daily send cap between 1 and 25. Stores the value in TenantCore. Exchange enforcement must be provisioned separately. |

At least one field must be provided.

**Example request**

```bash theme={null}
curl -X PATCH \
  https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailboxes/mailbox-uuid \
  -H "Authorization: Bearer tc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"daily_send_limit": 20}'
```

**Example response**

```json theme={null}
{
  "status": "updated",
  "mailbox": {
    "id": "mailbox-uuid",
    "display_name": "Sales Outreach",
    "primary_smtp": "sales@mail.acmecorp.com",
    "daily_send_limit": 20,
    "sends_today": 12,
    "account_enabled": true
  }
}
```

**Errors**

| Status | Code                 | Description                                             |
| ------ | -------------------- | ------------------------------------------------------- |
| `400`  | `invalid_send_limit` | `daily_send_limit` is outside the 1 to 25 range         |
| `400`  | `no_updates`         | Request body contained no recognised fields             |
| `404`  | `tenant_not_found`   | Tenant does not exist or belongs to a different account |
| `404`  | `mailbox_not_found`  | Mailbox does not exist on this tenant                   |

***

## Set enforcement

Saves a send limit policy and provisions the Exchange Online transport rule that enforces it. This is the step that activates the hard ceiling at the infrastructure level. Until this is called, `daily_send_limit` values on mailboxes are stored but not enforced by Exchange.

Enforcement is scoped at the domain level. Apply it to a specific domain or tenant-wide across all domains at once.

```
POST /v1/tenants/{tenant_id}/mailbox-limits
```

**Path parameters**

| Parameter   | Type   | Description               |
| ----------- | ------ | ------------------------- |
| `tenant_id` | string | The Microsoft tenant GUID |

**Request body**

```json theme={null}
{
  "daily_send_limit": 25,
  "domain_scope": "mail.acmecorp.com"
}
```

| Field              | Type   | Required | Description                                                                       |
| ------------------ | ------ | -------- | --------------------------------------------------------------------------------- |
| `daily_send_limit` | number | Yes      | The enforced daily send cap between 1 and 25                                      |
| `domain_scope`     | string | No       | The domain to scope enforcement to. Omit to apply tenant-wide across all domains. |

**Example request — single domain**

```bash theme={null}
curl -X POST \
  https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailbox-limits \
  -H "Authorization: Bearer tc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "daily_send_limit": 25,
    "domain_scope": "mail.acmecorp.com"
  }'
```

**Example request — tenant-wide**

```bash theme={null}
curl -X POST \
  https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailbox-limits \
  -H "Authorization: Bearer tc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"daily_send_limit": 25}'
```

**Example response**

```json theme={null}
{
  "status": "success",
  "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "daily_send_limit": 25,
  "domain_scope": "mail.acmecorp.com",
  "scope_label": "mail.acmecorp.com",
  "policy": {},
  "provisioning": {}
}
```

**Errors**

| Status | Code                           | Description                                               |
| ------ | ------------------------------ | --------------------------------------------------------- |
| `400`  | `invalid_send_limit`           | `daily_send_limit` is outside the 1 to 25 range           |
| `404`  | `tenant_not_found`             | Tenant does not exist or belongs to a different account   |
| `404`  | `domain_not_found`             | Specified `domain_scope` is not registered on this tenant |
| `409`  | `exchange_bootstrap_not_ready` | Exchange bootstrap has not completed for this tenant      |

***

## Get enforcement policy

Returns the current limit policy for a tenant or specific domain.

```
GET /v1/tenants/{tenant_id}/mailbox-limits
```

**Path parameters**

| Parameter   | Type   | Description               |
| ----------- | ------ | ------------------------- |
| `tenant_id` | string | The Microsoft tenant GUID |

**Query parameters**

| Parameter      | Type   | Description                                                                                           |
| -------------- | ------ | ----------------------------------------------------------------------------------------------------- |
| `domain_scope` | string | Optional. Pass a domain name to retrieve the policy for that domain. Omit for the tenant-wide policy. |

**Example request**

```bash theme={null}
curl "https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailbox-limits?domain_scope=mail.acmecorp.com" \
  -H "Authorization: Bearer tc_live_your_key"
```

**Errors**

| Status | Code               | Description                                             |
| ------ | ------------------ | ------------------------------------------------------- |
| `404`  | `tenant_not_found` | Tenant does not exist or belongs to a different account |
| `404`  | `policy_not_found` | No limit policy has been set for this scope             |

***

## Get mailbox usage

Returns daily send counts, limit status, and block state for a specific mailbox.

```
GET /v1/tenants/{tenant_id}/mailboxes/{mailbox_id}/usage
```

**Path parameters**

| Parameter    | Type   | Description                 |
| ------------ | ------ | --------------------------- |
| `tenant_id`  | string | The Microsoft tenant GUID   |
| `mailbox_id` | string | The TenantCore mailbox UUID |

**Example request**

```bash theme={null}
curl https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailboxes/mailbox-uuid/usage \
  -H "Authorization: Bearer tc_live_your_key"
```

**Example response**

```json theme={null}
{
  "mailbox_id": "mailbox-uuid",
  "primary_smtp": "sales@mail.acmecorp.com",
  "display_name": "Sales Outreach",
  "account_enabled": true,
  "daily_send_limit": 25,
  "sends_today": 18,
  "remaining_sends": 7,
  "is_blocked": false,
  "blocked_at": null,
  "utilization_pct": 72.0
}
```

**Response fields**

| Field              | Type              | Description                                                  |
| ------------------ | ----------------- | ------------------------------------------------------------ |
| `daily_send_limit` | number            | The configured cap                                           |
| `sends_today`      | number            | Emails sent today from Exchange message trace                |
| `remaining_sends`  | number            | `daily_send_limit - sends_today`, floored at 0               |
| `is_blocked`       | boolean           | `true` if enforcement has blocked this mailbox               |
| `blocked_at`       | timestamp or null | When the block was applied                                   |
| `utilization_pct`  | number            | `sends_today / daily_send_limit x 100`, rounded to 1 decimal |

**Errors**

| Status | Code                | Description                                             |
| ------ | ------------------- | ------------------------------------------------------- |
| `404`  | `tenant_not_found`  | Tenant does not exist or belongs to a different account |
| `404`  | `mailbox_not_found` | Mailbox does not exist on this tenant                   |
