2
Files
caddy-opnsense-blocker/docs/api.md

301 lines
5.3 KiB
Markdown

# 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, chart data, and dashboard leaderboards.
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`
- `activity_buckets`
- `methods`
- `bots`
- `top_bot_ips_by_events`
- `top_non_bot_ips_by_events`
- `top_bot_ips_by_traffic`
- `top_non_bot_ips_by_traffic`
- `top_sources`
- `top_urls`
- `recent_ips`
- `recent_events`
## `GET /api/events`
Returns a paginated slice of recent raw events.
Query parameters:
- `limit`
- optional
- default: `100`
- maximum: `1000`
- `page`
- optional
- default: `1`
- one-based page number
- `show_known_bots`
- optional
- default: `true`
- when `false`, verified bots are hidden from the log
- `show_allowed`
- optional
- default: `true`
- when `false`, rows whose current IP state is `allowed` are hidden
- `review_only`
- optional
- default: `false`
- when `true`, only requests whose current IP state is `review` are returned
Main response fields:
- `items`
- `page`
- `limit`
- `has_prev`
- `has_next`
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'
```