# Mailboxes

Mailboxes on your sites' domains, aliases, forwarders, the catch-all and out-of-office replies. Passwords are never returned.

## Mail of a site

`GET /sites/{site_id}/mail` · scope `mail:read`

The same as the site's Mail tab: whether PBN.LTD Mail is set up (`where` = "external" when the domain's mail is at an outside provider), whether its records are published, how many mailboxes the site may have and has, each mailbox with its size and use and out-of-office reply, the aliases, forwarders and catch-all. Never a password.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/sites/123/mail" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/mail", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`

## Set mail up for a site

`POST /sites/{site_id}/mail/set-up` · scope `mail:write`

The Mail tab's "Set up mail": makes the site's mail account and its signing keys and publishes its records where we answer DNS for the domain.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |

### Example

```bash
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/mail/set-up" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/mail/set-up", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/set-up", {
  method: "POST",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Create a mailbox

`POST /sites/{site_id}/mail/mailboxes` · scope `mail:write`

Creates a mailbox within what the site may have (402 when an extra mailbox has to be bought first - in the Mail tab). Returns the mail state; the password is never in it.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `local` | body | string | yes | The name before the @, e.g. "info". |
| `password` | body | string | no | A password of your own (at least 12 characters and strong enough for the mail server). Write-only: never returned. |
| `generate` | body | boolean | no | true = we make a strong password; the customer reads it with Show in the Mail tab. It is never returned here. Default: `False`. |

### Example

```bash
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes", {
  method: "POST",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`201`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `payment_required`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Set a new mailbox password

`PUT /sites/{site_id}/mail/mailboxes/{local}/password` · scope `mail:write`

Sets a new password (yours, or a generated one read with Show in the Mail tab). Every phone and mail program using the mailbox must then be given the new one. Never returned.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `local` | path | string | yes | The mailbox name before the @, e.g. "info". |
| `password` | body | string | no | A password of your own (at least 12 characters and strong enough for the mail server). Write-only: never returned. |
| `generate` | body | boolean | no | true = we make a strong password; the customer reads it with Show in the Mail tab. It is never returned here. Default: `False`. |

### Example

```bash
curl -s -X PUT "https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/password" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.put("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/password", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/password", {
  method: "PUT",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Delete a mailbox

`DELETE /sites/{site_id}/mail/mailboxes/{local}` · scope `mail:write` · **destructive**

Deletes the mailbox with everything in it. The site's first (included) mailbox can only go once it is the last one.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `local` | path | string | yes | The mailbox name before the @, e.g. "info". |
| `confirm` | body | boolean | yes | Must be true: the mailbox and every message in it are deleted. |

### Example

```bash
curl -s -X DELETE "https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local", {
  method: "DELETE",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `conflict`, `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Add or change an alias, forwarder or the catch-all

`PUT /sites/{site_id}/mail/aliases` · scope `mail:write`

Saves one alias, forwarder or the catch-all (the same checks as the Mail tab).

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `kind` | body | string (one of: alias, forwarder, catchall) | yes | alias = another address for one of your mailboxes; forwarder = mail passed on to another address; catchall = every address that does not exist. |
| `local` | body | string | no | The name before the @ (not for catchall). |
| `destinations` | body | array | yes | Where the mail goes: one or more addresses. |

### Example

```bash
curl -s -X PUT "https://app.pbn.ltd/api/v1/sites/123/mail/aliases" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.put("https://app.pbn.ltd/api/v1/sites/123/mail/aliases", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/aliases", {
  method: "PUT",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Remove an alias, forwarder or the catch-all

`DELETE /sites/{site_id}/mail/aliases` · scope `mail:write`

Removes one alias, forwarder or the catch-all. No mailbox or mail is touched.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `kind` | body | string (one of: alias, forwarder, catchall) | yes | alias = another address for one of your mailboxes; forwarder = mail passed on to another address; catchall = every address that does not exist. |
| `local` | body | string | no | The name before the @ (not for catchall). |

### Example

```bash
curl -s -X DELETE "https://app.pbn.ltd/api/v1/sites/123/mail/aliases" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/sites/123/mail/aliases", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/aliases", {
  method: "DELETE",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "site_id": 123,
    "domain": "example.com",
    "available": true,
    "set_up": true,
    "where": "ours",
    "refusal": "",
    "records_published": true,
    "mailboxes_allowed": 1,
    "mailboxes_in_use": 1,
    "can_add_mailbox": false,
    "why_not": "Your plan includes 1 mailbox for this site. Add another in the Mail tab.",
    "mailboxes": [
      {
        "id": 55,
        "address": "info@example.com",
        "local": "info",
        "state": "active",
        "is_default": true,
        "included": true,
        "quota_mb": 1024,
        "used_mb": 12,
        "size": "1 GB",
        "out_of_office": {
          "enabled": false,
          "subject": "",
          "body": "",
          "starts_at": null,
          "ends_at": null
        }
      }
    ],
    "aliases": [
      {
        "local": "sales",
        "destinations": [
          "info@example.com"
        ]
      }
    ],
    "forwarders": [
      {
        "local": "orders",
        "destinations": [
          "me@gmail.com"
        ]
      }
    ],
    "catch_all": null,
    "mx": [
      "mx1.pbn.ltd",
      "mx2.pbn.ltd"
    ],
    "webmail": "https://webmail.pbn.ltd/",
    "manage_url": "https://app.pbn.ltd/site/123#zinn_mail"
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`

## Out-of-office reply on or off

`PUT /sites/{site_id}/mail/mailboxes/{local}/out-of-office` · scope `mail:write`

The same as the out-of-office form on the Mail tab.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |
| `local` | path | string | yes | The mailbox name before the @, e.g. "info". |
| `enabled` | body | boolean | yes | On or off. |
| `subject` | body | string | no | The reply's subject. |
| `body` | body | string | no | The reply's text. |
| `starts_at` | body | string | no | Optional start (YYYY-MM-DD or an ISO date-time). |
| `ends_at` | body | string | no | Optional end (YYYY-MM-DD or an ISO date-time). |

### Example

```bash
curl -s -X PUT "https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/out-of-office" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.put("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/out-of-office", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/mail/mailboxes/local/out-of-office", {
  method: "PUT",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "enabled": false,
    "subject": "",
    "body": "",
    "starts_at": null,
    "ends_at": null
  }
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`, `validation_failed`
