Conventions
API conventions
There is no generated OpenAPI/Swagger contract. Do not invent one. Field names in this book are taken from request/response JSON actually returned by the Manager.
Base URL (Enterprise example Manager TLS listen):
https://manager.example.com:8443/api/v1Community example YAML and zwallctl still default to http://localhost:8080. Match the live Manager listener, not folklore.
Authentication
Scroll sideways to see the full table. Use the arrow keys when focused.
| Client | How |
|---|---|
Administrator XHR / zwallctl | Authorization: Bearer <jwt> from POST /api/v1/auth/login |
| Browser console | HttpOnly session cookie issued on login (session_token is not returned in the login JSON body) |
| Agent runtime | Agent JWT from POST /api/v1/agents/register or later refresh; Enterprise also applies capability middleware and optional mTLS |
Most admin groups use AdminAuth() + RoleAuth("admin"). Viewer and other roles exist on the admin model; they are not a substitute for admin on these operator routes.
Send JSON as Content-Type: application/json unless a handler documents otherwise (license import is still JSON with artifact_b64; Prometheus scrape is not JSON).
Response envelopes
Handlers are not uniform. Parse by family:
Scroll sideways to see the full table. Use the arrow keys when focused.
| Name | Shape | Used by |
|---|---|---|
| AUTH_ERR | {"error": "<string>"} | AuthHandler and many older handlers |
| V1ERR | {"success": false, "error": "...", "message": "...", "code": "..."} | utils.ResponseHelper.RespondError (BAD_REQUEST, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, CONFLICT, INTERNAL_ERROR, plus handler-specific codes) |
| V1OK | {"success": true, "message": "...", "data": ...} | ResponseHelper.RespondSuccess / RespondOK / RespondCreated |
| License 403 | {"success": false, "code": "...", "message": "...", "license": { ... }} | Enterprise licensegate.Gate (LicenseErrorResponse) |
| Community agent limit 403 | {"success": false, "error": "COMMUNITY_AGENT_LIMIT_REACHED", "code": "COMMUNITY_AGENT_LIMIT_REACHED", "message": "ZWall Community supports up to 3 agents", "limit": 3, "current_agents": <n>} | Community AgentHandler.respondCommunityAgentLimit |
Ad-hoc successes also appear: {"message": "..."}, {"success": true, "message": "..."}, or a bare domain object.
zwallctl CheckSuccess treats a JSON object with "success": false as failure when that key is present. Some list endpoints (GET /api/v1/agents) return {"agents": [...]} with no success flag.
Pagination (common, not universal)
Do not claim every list uses the same pair. Verified defaults:
Scroll sideways to see the full table. Use the arrow keys when focused.
| Param | Typical default | Typical cap | Source |
|---|---|---|---|
limit | 100 | 1000 | SecurityHandler.ListSecurityLogs and several list handlers |
offset | 0 | — | same |
audit-log limit | 20 (cap 1000) | GET /api/v1/auth/audit-logs | |
notifications list limit | 50 when omitted | NotificationHandler.GetNotifications | |
Hosting events limit | 50 (allowed 1–100) | GET /api/v1/agents/:id/hosting/events | |
updater page / per_page | 1 / 20 | in-product updater (not production upgrade) |
Invalid numeric limit/offset on security logs fall back to 100/0 rather than 400, except log_id which is 400 when unparsable.
Path parameters
Integer IDs (:id, :agent_id, :rule_id, :vm_id when numeric) are parsed with strconv.Atoi. Non-integers typically return 400 {"error":"Invalid ... ID"}. VM IDs in virtualization are opaque strings from libvirt inventory.
Idempotency and unknown JSON fields
Standard Go encoding/json ignores unknown fields. Extra keys sent by zwallctl (name, action, direction, enabled on allow/deny) are not the Manager contract.
Security-log ingest with a client event_id can return 200 + idempotent_replay: true instead of 201 when the row already exists. Empty event_id is assigned server-side and is not safely retryable.
TLS and cookies
Login issues the session cookie only when cookiePolicy.ValidateIssuance accepts the request (HTTPS / configured cookie transport). Failure is 400 {"error":"Secure HTTPS session required"}, not a JWT-only fallback in this handler.
v2 API
If V2 were compiled (//go:build v2api) and setupV2Router uncommented, code mounts /v2/..., not /api/v2. Default binaries do not expose it. Not a GA customer contract.
Security notes (shared)
- Never log passwords, JWTs, bootstrap tokens, 2FA secrets, backup codes, Cloudflare API tokens, captcha secrets, or license artifacts.
- Prefer
zwallctl logininteractive password prompt over--password. - Agent-facing URLs are for Agent runtimes, not browser mashups, even when the edition is SHARED.
- Rate limiters exist on login and Agent registration.
- SPA fallback for unknown
/api/paths returns{"error":"Endpoint not found","path":"..."}.