HF PanelDocsv1.0.0

API: email

Mailboxes, passwords and quotas, forwarders, autoresponders, sending limits and email checks through the token API.

These endpoints manage one hosting account's email, like the Email accounts screen in Control Panel: the same checks, limits and messages, the same activity log lines, and the changes are made on the mail server at once.

bash
A=https://api.yourdomain.com:2087/v1
H="Authorization: Bearer hf_xxx"

The path names the account (/v1/accounts/{username}/email/…); the rules are those of every per-account endpoint. Addresses go in the path as they are, for example /mailboxes/info@example.com (%40 for @ works too).

List mailboxes

GET /v1/accounts/{username}/email/mailboxes

json
{
    "ok": true,
    "data": [
        {
            "address": "info@example.com",
            "quota_mb": 1024,
            "used_mb": 12,
            "send_only": false,
            "created_at": "2026-05-02 09:30:11"
        }
    ]
}

Create a mailbox

POST /v1/accounts/{username}/email/mailboxes. 201 with the mailbox and its password, shown only in this answer.

bash
curl -s -X POST -H "$H" -H "Content-Type: application/json" \
  -d '{"address":"info@example.com","quota_mb":1024}' $A/accounts/sarahbakes/email/mailboxes
Field What it does
address required; the full address. The domain must be one of the account's, with email switched on
password empty = a random one
quota_mb 0 = no limit; at most 102400

The package's mailbox limit applies ("Mailbox limit reached for this package."), and an address that is already a mailbox or a forwarder answers 422.

Change a password or quota

bash
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"password":"Correct-Horse-9"}' \
  $A/accounts/sarahbakes/email/mailboxes/info@example.com/password
curl -s -X POST -H "$H" -H "Content-Type: application/json" -d '{"quota_mb":2048}' \
  $A/accounts/sarahbakes/email/mailboxes/info@example.com/quota

password empty makes a random one; the answer has address and password. The quota answer is the mailbox. PUT works as well as POST.

Delete a mailbox

DELETE /v1/accounts/{username}/email/mailboxes/{address} deletes the mailbox and all its messages.

Autoresponder

Switch it on with POST (or PUT) and off with DELETE on /v1/accounts/{username}/email/mailboxes/{address}/autoresponder.

bash
curl -s -X PUT -H "$H" -H "Content-Type: application/json" \
  -d '{"subject":"Out of office","body":"Back on Monday.","days":1,"start":"2026-12-20","end":"2027-01-02"}' \
  $A/accounts/sarahbakes/email/mailboxes/info@example.com/autoresponder
Field What it does
subject, body required to switch it on
days days before the same sender gets the reply again; default 1
start, end optional first and last day, YYYY-MM-DD

The answer is {"address": "info@example.com", "autoresponder": true} (or false after DELETE).

Forwarders

bash
curl -s -H "$H" $A/accounts/sarahbakes/email/forwarders
curl -s -X POST -H "$H" -H "Content-Type: application/json" \
  -d '{"source":"sales@example.com","destinations":["sarah@example.net","team@example.net"]}' \
  $A/accounts/sarahbakes/email/forwarders
curl -s -X DELETE -H "$H" $A/accounts/sarahbakes/email/forwarders/sales@example.com
json
{
    "ok": true,
    "data": {
        "source": "sales@example.com",
        "destinations": [
            "sarah@example.net",
            "team@example.net"
        ],
        "created_at": "2026-05-02 09:31:40"
    }
}
Field What it does
source required; the address, or *@example.com for every address that has no mailbox or forwarder
destinations required; 1–10 addresses, as a list or one text separated by commas

Adding a forwarder for a source that already has one replaces its destinations.

Sending limits

GET /v1/accounts/{username}/email/limits — the emails per hour and per day that apply (0 = unlimited) and where each comes from (account, package or server), the account's own values (null = the package's), what was sent this hour and in the last 24 hours, whether sending is on hold, and the limit events of the last 24 hours.

bash
curl -s -H "$H" $A/accounts/sarahbakes/email/limits
curl -s -X PUT -H "$H" -H "Content-Type: application/json" -d '{"per_hour":200,"per_day":null}' \
  $A/accounts/sarahbakes/email/limits
curl -s -X POST -H "$H" $A/accounts/sarahbakes/email/limits/release
json
{
    "ok": true,
    "data": {
        "per_hour": 200,
        "per_day": 1000,
        "per_hour_from": "account",
        "per_day_from": "package",
        "own_per_hour": 200,
        "own_per_day": null,
        "package_per_hour": 100,
        "package_per_day": 1000,
        "sent_hour": 12,
        "sent_day": 340,
        "refused_hour": 0,
        "paused": false,
        "held": false,
        "events": []
    }
}

Changing the limits (PUT or PATCH: per_hour, per_day; a field left out keeps its value) and POST …/limits/release (let the account send again after a limit or a hold) need an administrator token. See Sending limits.

Email checks

GET /v1/accounts/{username}/email/checks/{domain} runs the deliverability checks of a mail domain: score (in %), dns_managed (this server runs the domain's DNS) and checks, each with key (mx, spf, dkim, dmarc, ptr, tls, blacklist), status (pass, warn, fail), the message (msg with args), the fix (fix with fixArgs), the record to add (name, type, value, or null) and auto (it can be fixed here).

POST /v1/accounts/{username}/email/checks/{domain}/fix with {"check":"spf"} (or mx, dkim, dmarc; DMARC takes report_to, the address for the reports) writes the record into this server's DNS zone. It answers 422 when the check passes or the domain's DNS is run elsewhere.