Skip to main content

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.
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.

List mailboxes

Returns all mailboxes across all domains on a tenant.
GET /v1/tenants/{tenant_id}/mailboxes
Path parameters
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
Example request
curl https://api.tenantcore.io/v1/tenants/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mailboxes \
  -H "Authorization: Bearer tc_live_your_key"
Example response
{
  "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
FieldTypeDescription
primary_smtpstringThe mailbox email address
account_enabledbooleanWhether the account is enabled in Azure AD
daily_send_limitnumberConfigured daily send cap (1 to 25)
sends_todaynumberEmails sent today as reported by Exchange message trace
blocked_attimestamp or nullWhen the mailbox was blocked by enforcement, or null if not blocked
Errors
StatusCodeDescription
404tenant_not_foundTenant 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
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
Request body
{
  "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" }
  ]
}
FieldTypeRequiredDescription
domainstringYesThe verified domain to create mailboxes on
account_passwordstringYesInitial password for the underlying user account. Min 8 characters. Must meet Microsoft’s complexity requirements.
mailboxesarrayYesList of mailboxes to create. Max 3 total per domain including existing.
mailboxes[].namestringYesDisplay name for the mailbox
mailboxes[].emailstringYesFull email address. Must end with @{domain}.
Example request
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
{
  "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
StatusMeaning
createdMailbox was successfully provisioned
existsMailbox already exists, no action taken
failedProvisioning 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
StatusCodeDescription
400mailbox_limit_reachedDomain already has 3 mailboxes
400Invalid email domain, duplicate emails, or weak password
404tenant_not_foundTenant does not exist or belongs to a different account
404domain_not_foundDomain 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
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
mailbox_idstringThe TenantCore mailbox UUID (from list mailboxes)
Request body
{
  "display_name": "New Display Name",
  "daily_send_limit": 20
}
FieldTypeRequiredDescription
display_namestringNoNew display name for the mailbox
daily_send_limitnumberNoDaily 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
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
{
  "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
StatusCodeDescription
400invalid_send_limitdaily_send_limit is outside the 1 to 25 range
400no_updatesRequest body contained no recognised fields
404tenant_not_foundTenant does not exist or belongs to a different account
404mailbox_not_foundMailbox 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
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
Request body
{
  "daily_send_limit": 25,
  "domain_scope": "mail.acmecorp.com"
}
FieldTypeRequiredDescription
daily_send_limitnumberYesThe enforced daily send cap between 1 and 25
domain_scopestringNoThe domain to scope enforcement to. Omit to apply tenant-wide across all domains.
Example request — single domain
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
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
{
  "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
StatusCodeDescription
400invalid_send_limitdaily_send_limit is outside the 1 to 25 range
404tenant_not_foundTenant does not exist or belongs to a different account
404domain_not_foundSpecified domain_scope is not registered on this tenant
409exchange_bootstrap_not_readyExchange 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
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
Query parameters
ParameterTypeDescription
domain_scopestringOptional. Pass a domain name to retrieve the policy for that domain. Omit for the tenant-wide policy.
Example request
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
StatusCodeDescription
404tenant_not_foundTenant does not exist or belongs to a different account
404policy_not_foundNo 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
ParameterTypeDescription
tenant_idstringThe Microsoft tenant GUID
mailbox_idstringThe TenantCore mailbox UUID
Example request
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
{
  "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
FieldTypeDescription
daily_send_limitnumberThe configured cap
sends_todaynumberEmails sent today from Exchange message trace
remaining_sendsnumberdaily_send_limit - sends_today, floored at 0
is_blockedbooleantrue if enforcement has blocked this mailbox
blocked_attimestamp or nullWhen the block was applied
utilization_pctnumbersends_today / daily_send_limit x 100, rounded to 1 decimal
Errors
StatusCodeDescription
404tenant_not_foundTenant does not exist or belongs to a different account
404mailbox_not_foundMailbox does not exist on this tenant