Firewall, mail and notifications API
Firewall
Section titled “Firewall”The host’s ufw. Every route needs a superuser. Responses are camelCase. See Change the firewall safely for how changes are applied and rolled back.
| Method | Path | Body | Returns |
|---|---|---|---|
GET |
/firewall/ |
State: available, active, defaultIncoming, sshPorts, rules, webSources, refreshedAt, confirmWindow (seconds), open (the change in progress, or null), recent (last 20 changes) |
|
GET |
/firewall/pending |
{open}: the change in progress, or null. The UI polls this from every page. |
|
POST |
/firewall/refresh |
{detail: "Refresh requested."}. The state is also re-read every minute. |
|
POST |
/firewall/rules |
Rule body | The change (201), or 409 while another change is in progress |
POST |
/firewall/rules/remove |
Rule body, matching a rule with origin: "panel" |
The change |
POST |
/firewall/web-sources |
{preset: "cloudflare"} or {sources: "<list>"} |
The change |
POST |
/firewall/enable |
The change | |
POST |
/firewall/disable |
The change | |
GET |
/firewall/changes/{id} |
The change | |
POST |
/firewall/changes/{id}/confirm |
The change. Only the requester, before confirmBy. |
|
POST |
/firewall/changes/{id}/revert |
The change. Puts the old rules back now. |
Rule body
Section titled “Rule body”| Field | Values |
|---|---|
action |
Required: allow, deny, reject, limit. |
proto |
tcp, udp, any. |
port |
"22", "8000:8100", or empty for every port. |
from |
any, an IP address, or a CIDR. |
note |
Up to 60 characters. |
Each rule in the state has action, proto, port, from, comment,
families and origin (panel, base, web or other). Only panel
rules can be removed here.
sources for /web-sources is a list of IPs and CIDRs separated by commas,
spaces or newlines. An empty list or any opens 80 and 443 to everyone. The
request is refused if your address isn’t among the sources, or another rule
still lets everyone in on 80 or 443.
Change object
Section titled “Change object”id, op (add, delete, web-sources, enable, disable), rule,
status, error, requestedBy, requestedByEmail, requesterIp,
confirmBy, createdAt, finishedAt.
status: queued, applying, awaiting_confirmation,
confirm_requested, revert_requested, applied, rolled_back, failed.
When to use: add the rule, wait for awaiting_confirmation, then confirm
from a client that reaches the panel through the new rules. If you don’t
confirm within FIREWALL_CONFIRM_MINUTES (default 5), the agent restores the
old rules on its own.
Every route needs a superuser. Responses are camelCase.
| Method | Path | Body | Returns |
|---|---|---|---|
GET |
/mail/status |
{installed} |
|
POST |
/mail/install |
{detail: "Installation queued."} |
|
GET |
/mail/health |
Cached health of the stack, with detail and the last repair’s lastRepairAt, lastRepairStatus, lastRepairDetail, lastRepairSteps |
|
POST |
/mail/repair |
{detail: "Repair queued."} |
|
GET |
/mail/domains |
{results} |
|
POST |
/mail/domains |
{domain} (the apex, ≤ 253 characters) |
The domain |
PATCH |
/mail/domains/{id} |
{mailHostname?, dmarcPolicy?}. dmarcPolicy is none, quarantine or reject. |
The domain |
DELETE |
/mail/domains/{id} |
{detail}. Removes its mailboxes too. |
|
GET |
/mail/domains/{id}/dns |
{domain, mailHostname, publicIp, dkimConfigured, records} |
|
POST |
/mail/domains/{id}/sync |
{detail: "Sync queued."} |
|
GET |
/mail/domains/{id}/accounts |
{results}: mailboxes |
|
POST |
/mail/domains/{id}/accounts |
{localPart, password, quotaMb?} |
The mailbox |
PUT |
/mail/accounts/{id}/password |
{password} |
The mailbox |
DELETE |
/mail/accounts/{id} |
{detail: "Mailbox deleted."} |
Domain fields: id, domain, mailHostname (default mail.<domain>),
dkimSelector, dkimConfigured, dmarcPolicy, publicIp, isActive,
createdAt. Mailbox fields: id, mailDomainId, address, quotaMb,
isActive, createdAt, updatedAt, and connection with host,
username and the smtp, imap and pop3 ports and security modes.
Password hashes are never returned.
See Run a mail server.
Notifications
Section titled “Notifications”SMTP settings
Section titled “SMTP settings”The panel’s own outbound mail for alert emails. Superuser. Responses are
rows (snake_case) without smtp_password.
| Method | Path | Body | Returns |
|---|---|---|---|
GET |
/notifications/settings/smtp |
The settings | |
PUT |
/notifications/settings/smtp |
Any of {smtpHost, smtpPort, smtpUsername, smtpPassword, smtpSecurity, fromEmail, fromName, emailEnabled, alertEmail}. An empty smtpPassword keeps the stored one. |
The settings |
POST |
/notifications/settings/smtp/test |
{toEmail} |
{detail: "Test email sent."} |
Host stats
Section titled “Host stats”| Method | Path | Permission | Returns |
|---|---|---|---|
GET |
/notifications/host-stats |
Superuser | {snapshot}: the latest whole-host CPU, memory and disk sample |
Alert rules and events
Section titled “Alert rules and events”Rules with scope: "app" follow the app’s team roles: any member can read
them, a Developer can write them. Every other scope is superuser-only.
Responses are rows (snake_case).
| Method | Path | Body / query | Returns |
|---|---|---|---|
GET |
/notifications/rules |
Query scope?, appId?, postgresInstanceId?, mongoInstanceId?, managedServiceId?, applicationId? |
{results} |
GET |
/notifications/rules/{id} |
The rule | |
POST |
/notifications/rules |
Rule fields | The rule |
PUT |
/notifications/rules/{id} |
{metric?, comparison?, thresholdPercent?, severity?, cooldownMinutes?, enabled?, notifyEmail?}. Scope and target can’t change. |
The rule |
DELETE |
/notifications/rules/{id} |
{detail} |
|
GET |
/notifications/events |
Same filters as rules, plus limit (default 50) |
{results}: fired alerts |
Rule fields
Section titled “Rule fields”| Field | Values |
|---|---|
scope |
Required: app, system, postgres, mongo, mail, service, runtime. |
| Target | appId (app), postgresInstanceId (postgres), mongoInstanceId (mongo), managedServiceId (service), applicationId (runtime). system and mail take none. |
metric |
Required: cpu_percent, memory_percent, disk_percent, connections_percent, status_down. |
thresholdPercent |
Required except for status_down. 0 to 100, or 0 to cores × 100 for cpu_percent. |
comparison |
Default gte. |
severity |
Default warning. |
cooldownMinutes |
1 to 1440, default 15. |
enabled |
Default true. |
notifyEmail |
Default true. |
App alerts notify every member of the app’s team. Other scopes notify every active superuser.
Your own notifications. Authenticated. Rows (snake_case).
| Method | Path | Query | Returns |
|---|---|---|---|
GET |
/notifications/inbox |
unreadOnly?, limit? (default 50), offset? |
{results, count} |
GET |
/notifications/inbox/unread-count |
{count} |
|
POST |
/notifications/inbox/{id}/read |
Marks one as read | |
POST |
/notifications/inbox/read-all |
Marks all as read |