Skip to content

Daemon API

The daemon exposes a Fastify REST API on 127.0.0.1:8475 (default). The panel's DaemonClient is the only caller in normal operation — this reference is for debugging and custom integrations.


Authentication

Three layers, all required for every endpoint except /api/v1/health:

  1. IP allowlistallowedIps in config.json (default 127.0.0.1 only)
  2. Bearer tokenAuthorization: Bearer <64-hex> (constant-time compare)
  3. HMAC signature — mutations require:
X-PFW-Signature: hex(HMAC-SHA256(token, METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + sha256(body)))
X-PFW-Timestamp: <unix seconds>   # must be within timestampDriftSec (60s) of daemon time

Rate limits apply per scope (health 60/min, reads 120/min, mutations 30/min). Responses use a {success, data, error, meta} envelope, and every request gets an X-Correlation-ID.

Read-only shortcut

GET endpoints need only layers 1–2 (bearer, no HMAC) — handy for debugging:

bash
curl -s -H "Authorization: Bearer $(sudo cat /etc/panel-firewall/token)" \
  http://127.0.0.1:8475/api/v1/state | jq

Health & state

MethodPathAuthPurpose
GET/api/v1/healthnoneLiveness, version, capability probe (iptables/ipset present), degraded flag
GET/api/v1/statebearerFull tracked state: chains, ipsets, rule counts, ownership registry

Firewall control

MethodPathAuthPurpose
POST/api/v1/firewall/planHMACDry-run: returns the desired-state plan (chains/rules/ipsets) without applying
POST/api/v1/firewall/applyHMACTransactional apply: checkpoint → atomic iptables-restore → verify → arms the 60s confirm window
GET/api/v1/firewall/pending/:idbearerPoll a pending apply (confirmed / rolled_back / expired)
POST/api/v1/firewall/confirmHMACConfirm the apply (blocked until confirmDelaySec after apply)
POST/api/v1/firewall/rollbackHMACRoll back to the pre-apply checkpoint
GET/api/v1/firewall/checkpointsbearerList checkpoints (id, createdAt, reason, hash fields, size)
GET/api/v1/firewall/reconcile/statusbearerDrift status between desired and kernel state
POST/api/v1/firewall/reconcileHMACForce a reconcile (auto-repairs drift when autoRepair is on)
POST/api/v1/firewall/safe-mode/clearHMACClear SAFE_MODE after a failed rollback — explicit admin recovery
GET/api/v1/firewall/auditbearerDaemon audit log entries

Apply payload

json
{
  "globalEnabled": true,
  "protectedPorts": { "http": 80, "https": 443 },
  "preset": "medium",
  "adminWhitelist": ["203.0.113.10/32"],
  "permanentBlacklist": [],
  "smart": { "enabled": true, "alpha": 0.1, "beta": 0.05, "anomalyDeviation": 4 },
  "l7": {
    "enabled": true, "logPaths": [], "rateLimitRpm": 600, "windowSec": 60,
    "banDurationSec": 900, "excludePrivate": true, "maxBansPerMinute": 20
  }
}

All CIDRs are strictly validated (zCidr: real octets, prefix 0–32, no leading zeros); logPaths is capped at 16 × 256 chars. A successful apply returns pendingApplyId, appliedAt, expiresAt, and confirmAvailableAt.

Lists

MethodPathAuthPurpose
POST/api/v1/lists/whitelistHMACAdd whitelist CIDR (normally managed via the panel + apply)
POST/api/v1/lists/blacklistHMACAdd permanent blacklist CIDR
POST/api/v1/lists/temporary-banHMACTemp-ban an IP (durationSec, reason)
GET/api/v1/lists/temporary-bansbearerActive temp bans with expiry and reason

SMART

MethodPathAuthPurpose
GET/api/v1/smart/statebearerSMART status: mitigation level, EWMA snapshot, active bans, and the l7 block (enabled, watchedFiles, trackedIps, bannedTotal, recentBans)
POST/api/v1/smart/presetHMACSwitch the runtime preset

Analytics

MethodPathAuthPurpose
GET/api/v1/analytics/series?metrics=pps_in,cps_in,l7_requests_per_min&range=1hbearerTimeseries buckets (10s) for graphs. Metrics: pps_in, cps_in, syn_per_sec, conntrack_pct, conntrack_count, l7_requests_per_min, l7_banned_total, l7_tracked_ips, l7_dropped_offenses
GET/api/v1/analytics/summarybearerAggregates: mitigations, bans, EWMA state, audit counts

Webhooks & import/export

MethodPathAuthPurpose
POST/api/v1/webhooks/syncHMACReplace the daemon's webhook set (from the panel DB)
GET/api/v1/webhooks/logbearerDelivery log (at, event, url, statusCode, outcome)
GET/api/v1/exportbearerExport bundle (format pterodactyl-panel-firewall v1)
POST/api/v1/importHMACImport a bundle (dry-run supported)

Error codes worth knowing

CodeMeaning
400 validation_errorPayload failed zod validation (bad CIDR, oversize logPaths, …)
401Bad/missing bearer token or IP not in allowedIps
403Bad HMAC signature or timestamp outside the drift window
423 SAFE_MODE_ACTIVEDaemon is in safe mode — mutation frozen until /firewall/safe-mode/clear
425Confirm attempted before confirmDelaySec elapsed
429Rate limited