Flat reference of every route the panel exposes. Authoritative source: backend/internal/server/server.go — if drift shows up between this page and the binary, the code wins.
Response shape for errors is uniformly {"error":"<message>"} with an HTTP status in 4xx/5xx. Success responses are per-endpoint; listings return [...] arrays (never null), single-row GETs return an object.
Update (full replace; partial fields take a *bool shape).
DELETE
/api/hosts/{id}
Delete.
POST
/api/hosts/{id}/toggle
Toggle the enabled flag.
The host record carries (most relevant for v1.3.18+):
lan_only (v1.3.18) — when true, Caddy gates the host with a remote_ip matcher that returns 403 to public IPs.
true_detect_mode (v1.3.19, activated v1.3.29) — when true, the panel writes a profiles.yaml entry that suppresses LAPI decision creation for AppSec alerts whose target_fqdn matches this host. Useful for hosts whose legitimate traffic triggers AppSec false positives (socket.io polling, monitoring tools). See Per-host true_detect_mode and the v1.3.29 release notes for the profiles.yaml splice protocol.
tls_acme_ca_url (v1.3.7) — per-host override of the global ACME CA URL.
tls_challenge (v1.3.7) — dns / http / tls-alpn.
tls_dns_provider (v1.3+) — names the dns_providers row this host pulls credentials from when tls_challenge='dns'.
For the broader /api/security/* namespace (decisions, whitelist, scenarios management, drift detection, country bans), see the Security tabs section below.
List all operator-uploaded certs (metadata only; never the key).
GET
/api/manual-certs/{host_id}
One cert's metadata. 404 when the host has no manual cert.
POST
/api/manual-certs/{host_id}
Multipart upload: cert_pem, key_pem, optional chain_pem. Validates + encrypts the key + writes files to the shared volume + flips the host to tls_mode=manual.
DELETE
/api/manual-certs/{host_id}?revert=auto\|none
Remove the cert + files, revert the host's TLS mode (default auto).
GET
/api/manual-certs/{host_id}/download
Stream cert + chain PEM for inspection (key is never served).
See Manual certificates for validation semantics and the manual_cert_expiring_soon notification event.
Full surface under /api/logs/... — list, stream (SSE tail), stats, timeseries, single row. Wired via h.RouteLogsMux(r); the exact shape is in internal/api/logs.go.
The legacy /api/threats/* paths were retired in v1.3.24 in favour of one consolidated /api/security/* namespace that maps 1:1 to the panel's /security tab strip.
Active decisions list. Filters: substring q (matches value or scenario), scope (Ip/Range/Country/AS), origin (e.g. cscli, argos-country-BR, CAPI). Cached for 15s.
DELETE
/api/security/decisions/{id}
Unban a single decision. Idempotent (404 from LAPI = already gone, returns success).
POST
/api/security/decisions/unban-ip
Body: {ip: "..."}. Removes every active decision for that IP.
GET
/api/security/whitelist
List manual whitelist entries. Returns {entries: [...]}.
List installed scenarios. Returns {scenarios: [{short_name, source, canonical_name, path, disabled, description?}], is_available, mount_path, disabled_count, last_modified_at?}. The description field (v1.3.30) carries the hub-catalogue summary for the tooltip; empty when the slimmed argos-scenarios-index.json hasn't been emitted yet.
PATCH
/api/security/scenarios/{name}
Body: {disabled: bool}. Toggles the operator-disabled set. The name segment is URL-encoded (crowdsecurity%2FCVE-2017-9841); chi v5 captures the encoded form, the handler url.PathUnescapes before persisting. Writes argos-disabled-scenarios.txt sentinel.
The mark-applied endpoints (/api/security/scenarios/mark-applied, /api/security/appsec-tuning/mark-applied) shipped in v1.3.25 were retired in v1.3.27 along with the operator-trust model.
Country bans (v1.3.21+ + v1.3.31 async + v1.3.33 reconciler)¶
Method
Path
Purpose
POST
/api/security/countries/{cc}/expand
v1.3.31 path-based shape. Body: {duration: "168h", reason?: ""}. Returns 202 + the new job row (state=pending). Worker goroutine drives the LAPI POST chunk-by-chunk; poll /api/security/jobs/{id} for progress.
GET
/api/security/countries
List active expansions. Each row carries the v1.3.33 state field (active | drifted).
DELETE
/api/security/countries/{cc}
Synchronous revoke: DELETE /v1/decisions?origins=argos-country-XX to LAPI + DELETE FROM country_ban_expansions panel-side.
The pre-v1.3.31 body-based POST /api/security/countries/expand endpoint is removed.
List recent jobs. Empty country returns cross-country recent. limit defaults 20, max 200.
The /api/security/jobs path is intentionally top-level under /security/ (not nested under /countries) to leave room for future job types (audit retention sweeps, scenario re-installs, etc.) without further URL churn.