# HTTP API The daemon serves a small JSON API used by the built-in web UI. ## General behavior - All endpoints are served from the same address as the web UI. - Responses are JSON. - Error responses use the shape `{"error":"..."}`. - Unsupported HTTP methods return `405 Method Not Allowed`. - There is no built-in authentication or TLS. ## `GET /healthz` Liveness probe. Example response: ```json { "status": "ok", "time": "2026-03-12T18:22:11Z" } ``` ## `GET /api/overview` Returns summary counters plus recent IP and recent event samples. Query parameters: - `limit` - optional - default: `50` - maximum: `1000` - `hours` - optional - default: `24` - used for the top activity leaderboards returned in the same payload Main response fields: - `total_events` - `total_ips` - `blocked_ips` - `review_ips` - `allowed_ips` - `observed_ips` - `activity_since` - `top_ips_by_events` - `top_ips_by_traffic` - `top_sources` - `top_urls` - `recent_ips` - `recent_events` ## `GET /api/events` Returns recent raw events. Query parameters: - `limit` - optional - default: `100` - maximum: `1000` Each event includes: - source and profile names - timestamps - remote and client IPs - host, method, URI, path, status, and User-Agent - decision, primary reason, all reasons, and whether it was enforced - raw Caddy JSON - current IP state and manual override ## `GET /api/ips` Returns current IP state rows. Query parameters: - `limit` - optional - default: `100` - maximum: `1000` - `state` - optional - filter by one state such as `review`, `blocked`, `allowed`, or `observed` Each row includes: - `ip` - `first_seen_at` - `last_seen_at` - `last_source_name` - `last_user_agent` - `latest_status` - `total_events` - `state` - `state_reason` - `manual_override` - `last_event_id` - `updated_at` ## `GET /api/recent-ips` Returns aggregated IP rows over a recent time window. Query parameters: - `hours` - optional - default: `24` - values less than or equal to zero fall back to `24` - `limit` - optional - default: `200` - maximum: `1000` Each row includes: - `ip` - `source_name` - `state` - `events` - `last_seen_at` - `reason` - `manual_override` - optional `bot` - `actions` `actions` contains: - `can_block` - `can_unblock` - `can_clear_override` ## `GET /api/ips/{ip}` Returns the complete details for one IP address. Response fields: - `state` - `recent_events` - `decisions` - `backend_actions` - optional `investigation` - `opnsense` - `actions` The current implementation returns up to: - 100 recent events - 100 decision records - 100 backend action records ## `POST /api/ips/{ip}/investigate` Forces a fresh investigation for the selected IP and returns the updated `IPDetails` payload. This bypasses the cached investigation for that request. No request body is required. ## Action endpoints These endpoints accept an optional JSON body: ```json { "actor": "alice@example.net", "reason": "short human-readable explanation" } ``` If omitted: - `actor` defaults to `web-ui` - `reason` defaults to an action-specific fallback All action endpoints return the updated `IPDetails` payload on success. ### `POST /api/ips/{ip}/block` - Sets a manual force-block override. - Default reason: `manual block`. - If OPNsense is enabled, the daemon adds the IP to the configured alias if it is missing. ### `POST /api/ips/{ip}/unblock` - Sets a manual force-allow override. - Default reason: `manual allow`. - If OPNsense is enabled, the daemon removes the IP from the configured alias if it is present. ### `POST /api/ips/{ip}/clear-override` - Removes the local manual override. - Default reason: `manual override cleared`. - Does not directly call OPNsense. ### `POST /api/ips/{ip}/reset` Backwards-compatible alias for `clear-override`. ## Response model details ### `investigation` When present, `investigation` may contain: - `ip` - `updated_at` - `error` - `bot` - `reverse_dns` - `registration` - `reputation` ### `bot` - `provider_id` - `name` - `icon` - `method` - `verified` ### `reverse_dns` - `ptr` - `forward_confirmed` ### `registration` - `source` - `handle` - `name` - `prefix` - `organization` - `country` - `abuse_email` ### `reputation` - `spamhaus_lookup` - `spamhaus_listed` - optional `spamhaus_codes` - optional `error` ### `opnsense` - `configured` - `present` - `checked_at` - optional `error` ## Example manual block request ```bash curl -X POST \ -H 'Content-Type: application/json' \ -d '{"actor":"cli","reason":"confirmed credential stuffing"}' \ http://127.0.0.1:9080/api/ips/203.0.113.10/block ``` ## Example recent IP query ```bash curl 'http://127.0.0.1:9080/api/recent-ips?hours=24&limit=250' ```