API reference
Mailboxes
The mailboxes endpoints manage the mailboxes of your company and their alternate emails. They follow the same rules as the console: addresses only in the company's verified domains, the plan's user limit and mailbox size, and the console privileges of the person who created the key.
Every endpoint needs a full-access key. A mailbox is named by its address in the path, URL-encoded
(jane%40acme.com; an unencoded @ works too) and in any case. The endpoints can also return
the common errors listed in the overview. Request bodies may be at most 64 KB. For
setting up many mailboxes with a script, see Managing mailboxes, aliases and groups.
| Endpoint | Node.js | Python | CLI |
|---|---|---|---|
| GET /mailboxes | mailboxes.list | mailboxes.list | tsmart mailboxes list |
| POST /mailboxes | mailboxes.create | mailboxes.create | tsmart mailboxes create |
| GET /mailboxes/{email} | mailboxes.get | mailboxes.get | tsmart mailboxes get |
| PATCH /mailboxes/{email} | mailboxes.update | mailboxes.update | tsmart mailboxes update |
| DELETE /mailboxes/{email} | mailboxes.remove | mailboxes.remove | tsmart mailboxes delete |
| POST /mailboxes/{email}/password | mailboxes.resetPassword | mailboxes.reset_password | tsmart mailboxes reset-password |
| GET /mailboxes/{email}/aliases | mailboxes.aliases.list | mailboxes.aliases.list | tsmart mailboxes aliases |
| POST /mailboxes/{email}/aliases | mailboxes.aliases.create | mailboxes.aliases.create | tsmart mailboxes alias-add |
| DELETE /mailboxes/{email}/aliases/{address} | mailboxes.aliases.remove | mailboxes.aliases.remove | tsmart mailboxes alias-remove |
Permissions
A full-access key acts with the console rights of the person who created it. Each endpoint needs one of their
console privileges; a role limited to an organisational unit can change only the mailboxes of that unit. A
sending-access key gets 401 restricted_api_key, and a key whose creator lacks the right gets
403 invalid_permission.
| Endpoint | Key creator needs (console) |
|---|---|
GET /mailboxes, GET /mailboxes/{email}, GET …/aliases | View users |
POST /mailboxes | Create users (for the target unit) |
PATCH /mailboxes/{email} | Per field: Update users (name, quota_mb), Suspend users (active), Reset user passwords (force_password_change) |
POST /mailboxes/{email}/password | Reset user passwords |
POST …/aliases, DELETE …/aliases/{address} | Update users |
DELETE /mailboxes/{email} | To be the company owner (with Delete users) |
Every change is recorded in the company's audit log under the key's name, like the same change made in the console.
The mailbox object
| Name | Type | Description |
|---|---|---|
object | string | Always "mailbox". |
email | string | The address, lowercase. It names the mailbox in every path. |
name | string | Display name. |
domain | string | The domain of the address. |
active | boolean | false while the mailbox is suspended (mail is still received; the user cannot sign in). |
quota_mb | integer | Mailbox size in MB. |
used_bytes | integer | Storage in use, in bytes. |
messages | integer | Number of stored messages. |
force_password_change | boolean | The user must choose a new password at the next sign-in. |
org_unit | object | null | The organisational unit, { id, name }. Mailboxes not moved to a unit belong to the root unit. |
aliases | string[] | The mailbox's alternate emails, lowercase and sorted. |
last_sign_in_at | string | null | The last sign-in from a mail app, or null. |
A password or its hash is never returned. The only exception is the temporary password in the answer of POST /mailboxes and POST /mailboxes/{email}/password, which is shown once and not stored anywhere readable.
The alias object
An alternate email (alias) is another address of a mailbox: mail to it is delivered to the mailbox, and the mailbox may also send as it.
| Name | Type | Description |
|---|---|---|
object | string | Always "alias". |
address | string | The alternate email, lowercase. |
mailbox | string | The mailbox it belongs to. |
active | boolean | Whether mail to the address is accepted. |
GET /mailboxes
Lists the company's mailboxes, ordered by address.
Permission: full access; the key's creator needs View users.
Query
| Name | Type | Description |
|---|---|---|
limit | integer | 1 to 100, default 20. |
after | string | An address: return the mailboxes that come after it. Pass the email of the last mailbox of a page to get the next page. |
before | string | An address: return the mailboxes that come before it. Use either after or before. |
domain | string | Only mailboxes in this domain, which must be one of the company's verified domains. |
Request
curl "https://send.tsmart.ai/mailboxes?domain=acme.com&limit=100" \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "list",
"has_more": false,
"data": [
{
"object": "mailbox",
"email": "jane@acme.com",
"name": "Jane Doe",
"domain": "acme.com",
"active": true,
"quota_mb": 2048,
"used_bytes": 13002342,
"messages": 120,
"force_password_change": false,
"org_unit": { "id": 12, "name": "Sales" },
"aliases": ["j.doe@acme.com"],
"last_sign_in_at": "2026-10-12 08:15:02.123000+00"
}
]
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks View users. |
| 422 | validation_error | limit out of range, both after and before, a cursor that is not an address ("Invalid pagination cursor"), or a domain that is not a verified domain of the company. |
| 500 | application_error | The mail server could not be reached. The list is never answered as empty because of an outage. |
POST /mailboxes
Creates a mailbox and returns it with a temporary password. The mailbox gets the console's settings for new users: encrypted connections are required for its incoming and outgoing mail, it is placed in its organisational unit and takes that unit's storage and mail app policies at once, and the user must choose a new password at the first sign-in. Creates for one company run one at a time, so requests sent in parallel wait for each other and can never go past the plan's user limit together.
Permission: full access; the key's creator needs Create users for the target unit.
Body
| Name | Type | Description |
|---|---|---|
email required | string | The new address, in one of the company's verified domains. The part before @ may use letters, digits and . _ + -, must start and end with a letter or digit, and is at most 64 characters. Stored in lowercase. |
name | string | Display name, at most 120 characters. Required unless first_name is given. |
first_name | string | Instead of name: the display name becomes first_name and last_name joined by a space (each at most 60 characters). |
last_name | string | Optional, with first_name. |
quota_mb | integer | Mailbox size, 256 to 51200. A value above the plan's mailbox size is lowered to it. Default: the company's default mailbox size. |
org_unit_id | integer | The organisational unit (its id from the console). Default: the root unit. |
Request
curl -X POST https://send.tsmart.ai/mailboxes \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jane@acme.com",
"first_name": "Jane",
"last_name": "Doe",
"quota_mb": 2048,
"org_unit_id": 12
}' const { data, error } = await tsmart.mailboxes.create({
email: "jane@acme.com",
first_name: "Jane",
last_name: "Doe",
quota_mb: 2048,
});
// data.temporary_password: give it to Jane over a safe channel box = client.mailboxes.create({"email": "jane@acme.com", "name": "Jane Doe", "quota_mb": 2048})
print(box["temporary_password"]) Response
{
"object": "mailbox",
"email": "jane@acme.com",
"name": "Jane Doe",
"domain": "acme.com",
"active": true,
"quota_mb": 2048,
"used_bytes": 0,
"messages": 0,
"force_password_change": true,
"org_unit": { "id": 12, "name": "Sales" },
"aliases": [],
"last_sign_in_at": null,
"temporary_password": "Xy7kQ2mN9pR4sT6vW8zA"
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks Create users, or holds it only for other units than the target unit. |
| 403 | account_inactive | The company's subscription is not active. |
| 403 | validation_error | The plan's user limit is reached ("The company's plan allows up to 25 users"). |
| 409 | already_exists | The address is already a mailbox, a group or an alternate email. |
| 422 | missing_required_field | email, or both name and first_name, are missing. |
| 422 | validation_error | email is not an address, its part before @ is not allowed, its domain is not a verified domain of the company, quota_mb is not an integer from 256 to 51200, or org_unit_id is not a unit of the company. |
| 502 | mail_server_error | The mail server refused the mailbox; the message carries its error codes. |
GET /mailboxes/{email}
Returns one mailbox.
Permission: full access; the key's creator needs View users.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded; case does not matter). |
Request
curl https://send.tsmart.ai/mailboxes/jane%40acme.com \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "mailbox",
"email": "jane@acme.com",
"name": "Jane Doe",
"domain": "acme.com",
"active": true,
"quota_mb": 2048,
"used_bytes": 13002342,
"messages": 120,
"force_password_change": false,
"org_unit": { "id": 12, "name": "Sales" },
"aliases": ["j.doe@acme.com"],
"last_sign_in_at": "2026-10-12 08:15:02.123000+00"
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks View users. |
| 404 | not_found | No such mailbox in the company's domains ("Mailbox not found"). |
PATCH /mailboxes/{email}
Changes a mailbox: its name and size, suspends or restores it, or switches the forced password change. Send at least one field. Each field needs its own privilege; if one is missing, nothing changes.
Permission: full access; the key's creator needs the privilege of each field, for this mailbox.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
Body
| Name | Type | Description |
|---|---|---|
name | string | New display name (not empty, at most 120 characters). Needs Update users. |
quota_mb | integer | New size, 256 to 51200, lowered to the plan's mailbox size. Needs Update users. |
active | boolean | false suspends the mailbox: mail is still received and stored, but the user cannot sign in. true restores it. Needs Suspend users. |
force_password_change | boolean | true requires a new password at the next sign-in. Needs Reset user passwords. |
Request
curl -X PATCH https://send.tsmart.ai/mailboxes/jane%40acme.com \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Jane Smith", "quota_mb": 4096 }' await tsmart.mailboxes.update("jane@acme.com", { active: false }); // suspend client.mailboxes.update("jane@acme.com", {"active": True}) # restore Response
The mailbox after the change.
{
"object": "mailbox",
"email": "jane@acme.com",
"name": "Jane Smith",
"domain": "acme.com",
"active": true,
"quota_mb": 4096,
"used_bytes": 13002342,
"messages": 120,
"force_password_change": false,
"org_unit": { "id": 12, "name": "Sales" },
"aliases": ["j.doe@acme.com"],
"last_sign_in_at": "2026-10-12 08:15:02.123000+00"
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the privilege of a field, or holds it only for other units. |
| 404 | not_found | No such mailbox in the company's domains. |
| 422 | validation_error | No field to change ("Nothing to update: …"), an empty or non-text name, quota_mb not an integer from 256 to 51200, or active or force_password_change not a boolean. |
| 502 | mail_server_error | The mail server refused the change. |
DELETE /mailboxes/{email}
Deletes a mailbox with all its mail, its alternate emails and its directory entries (organisational unit, profile, group roles). Group memberships of the address are not changed. This cannot be undone.
Permission: full access; the key must be created by a company owner.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
Request
curl -X DELETE https://send.tsmart.ai/mailboxes/jane%40acme.com \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "mailbox",
"email": "jane@acme.com",
"deleted": true
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key was not created by a company owner. |
| 404 | not_found | No such mailbox in the company's domains. |
| 502 | mail_server_error | The mail server refused to delete the mailbox. |
POST /mailboxes/{email}/password
Sets a new 20-character temporary password and returns it once. The old password stops working at once, and the user must choose a new password at the next sign-in. The request has no body.
Permission: full access; the key's creator needs Reset user passwords for this mailbox.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
Request
curl -X POST https://send.tsmart.ai/mailboxes/jane%40acme.com/password \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "mailbox",
"email": "jane@acme.com",
"force_password_change": true,
"temporary_password": "Ab3dEf5hJk7mNp9qRs2t"
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks Reset user passwords for this mailbox. |
| 404 | not_found | No such mailbox in the company's domains. |
| 502 | mail_server_error | The mail server refused the new password. |
GET /mailboxes/{email}/aliases
Lists the alternate emails of a mailbox, ordered by address. The list is never paged (has_more is always false).
Permission: full access; the key's creator needs View users.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
Request
curl https://send.tsmart.ai/mailboxes/jane%40acme.com/aliases \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "list",
"has_more": false,
"data": [
{ "object": "alias", "address": "j.doe@acme.com", "mailbox": "jane@acme.com", "active": true }
]
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks View users. |
| 404 | not_found | No such mailbox in the company's domains. |
POST /mailboxes/{email}/aliases
Adds an alternate email to a mailbox. The mailbox receives its mail at once and may send as it.
Permission: full access; the key's creator needs Update users for this mailbox.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
Body
| Name | Type | Description |
|---|---|---|
address required | string | A free address in one of the company's verified domains, other than the mailbox's own address. The part before @ follows the same rules as for a mailbox. |
Request
curl -X POST https://send.tsmart.ai/mailboxes/jane%40acme.com/aliases \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "address": "j.doe@acme.com" }' await tsmart.mailboxes.aliases.create("jane@acme.com", { address: "j.doe@acme.com" }); client.mailboxes.aliases.create("jane@acme.com", {"address": "j.doe@acme.com"}) Response
{
"object": "alias",
"address": "j.doe@acme.com",
"mailbox": "jane@acme.com",
"active": true
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks Update users for this mailbox. |
| 404 | not_found | No such mailbox in the company's domains. |
| 409 | already_exists | The address is already a mailbox, a group or an alternate email. |
| 422 | missing_required_field | address is missing. |
| 422 | validation_error | address is not an address, its part before @ is not allowed, its domain is not a verified domain of the company, or it is the mailbox's own address. |
| 502 | mail_server_error | The mail server refused the alternate email. |
DELETE /mailboxes/{email}/aliases/{address}
Removes an alternate email from a mailbox. Mail sent to it is no longer accepted.
Permission: full access; the key's creator needs Update users for this mailbox.
Path
| Name | Type | Description |
|---|---|---|
email required | string | The mailbox address (URL-encoded). |
address required | string | The alternate email to remove (URL-encoded). |
Request
curl -X DELETE https://send.tsmart.ai/mailboxes/jane%40acme.com/aliases/j.doe%40acme.com \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "alias",
"address": "j.doe@acme.com",
"mailbox": "jane@acme.com",
"deleted": true
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks Update users for this mailbox. |
| 404 | not_found | No such mailbox ("Mailbox not found"), or the address is not one of its alternate emails ("Alternate email not found"). |
| 502 | mail_server_error | The mail server refused the change. |