Skip to main content

API and events

Everything the web interface does goes through the same REST API, so scripts can do it too.

  • Interactive documentation: /docs (Swagger) and /redoc.
  • The OpenAPI schema: /openapi.json.
  • Application endpoints live under /v1/api; sign-in and first-admin setup under /v1/auth.

The OpenAPI documentation of the server you run is the exact reference for that version.

Authenticate​

Create an API key and send it in the X-Minipam-Api-Key header. The key acts with its user's role.

export MINIPAM=https://minipam.example.com
export MINIPAM_API_KEY=...

curl -fsS -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" "$MINIPAM/v1/api/sites/"

Keep keys out of source control and shell history on shared machines.

An invalid or revoked key gets 401 (E2401), even when the request also carries a valid session cookie. MiniPAM does not fall back from a bad key to the cookie.

Browser sessions and CSRF​

The web interface signs in with POST /v1/auth/login and gets two cookies: the session cookie (minipam_session by default, set by cookie-name) and a CSRF cookie with the same name plus _csrf. Scripts that use a session instead of an API key must follow the same rule:

  • POST, PUT, PATCH, and DELETE requests need the header X-Minipam-CSRF, with the same value as the CSRF cookie. Otherwise they fail with 403 and "The CSRF token is missing or invalid".
  • GET /v1/auth/csrf returns the current token as {"csrf_token": "…"} and sets the cookie again.
  • Requests with an API key need no CSRF token. For scripts, an API key is simpler.

Which role an endpoint needs​

Every operation in /openapi.json carries an x-minipam-authorization field. It holds the lowest role that may call it (viewer, editor, or admin), or "public": true for the few that need no sign-in:

curl -fsS "$MINIPAM/openapi.json" | jq '.paths["/v1/api/sites/"].post["x-minipam-authorization"]'
{ "minimum_role": "admin", "policy": null }

/openapi.json, /docs, and /redoc need no sign-in.

Lists, filters, and paging​

List endpoints accept offset and limit (1 to 500, default 100), most accept site_id, and many accept search and a structured filter:

curl -fsS -G -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" "$MINIPAM/v1/api/networks/" \
--data-urlencode "site_id=1" \
--data-urlencode "filter=vlan_id:gt:10" \
--data-urlencode "limit=50"

They return the page and the total:

{
"offset": 0,
"limit": 50,
"count": 2,
"total": 2,
"items": [{ "id": 10001, "network_name": "Servers", "network_cidr": "192.168.10.0/24" }]
}

The filter syntax is the one from structured filters.

Services and gateways created without a site_id are global: templates in every site can read them. The web interface only creates site-scoped ones.

Errors​

Errors have a stable error code and a human-readable description. Match on the code, not the text:

{ "code": 404, "error": "E1404", "description": "Site 7 was not found." }
CodeHTTPMeaning
E1404404The resource was not found.
E2400400The request body or parameters are invalid. The description says which.
E2401401Not signed in, or the session or API key is invalid. Also wrong sign-in credentials.
E2403403Your role is too low, or the CSRF token is missing or invalid. Read the description.
E2409409Conflicts with an existing record or the current state. May include a conflict object.
E2410400Refers to a related record that does not exist.
E2411409The job cannot move to the requested status.
E2413413The uploaded file is too large. Import files are limited to 20 MB.
E5000500Unexpected server error. The server log has the details.

A few features return their own codes. Template rendering, for example, returns TEMPLATE_RENDER_TIMEOUT (408) and TEMPLATE_RENDER_CAPACITY (429). See A template render or download fails.

Common tasks​

Fetch the published output of a template, for example from a cron job:

curl -fsS -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" \
-o nginx.conf "$MINIPAM/v1/api/configuration-templates/42/outputs/download"

The response's X-MiniPAM-Output-Version header says which output you got. A specific version is at …/outputs/{version}/download.

Read the asset integrity summary for a site, or run all inventory checks (editor role):

curl -fsS -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" "$MINIPAM/v1/api/asset-integrity/summary?site_id=1"
curl -fsS -X POST -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" "$MINIPAM/v1/api/asset-integrity/run?site_id=1"

Search across all sites, like Ctrl+K in the interface:

curl -fsS -G -H "X-Minipam-Api-Key: $MINIPAM_API_KEY" "$MINIPAM/v1/api/search/" --data-urlencode "q=ip: 192.168.10."

Live events​

The interface listens to server-sent events at /sse/ for job, log, and data changes. Any signed-in user (viewer role) can subscribe. Each event's data is JSON with a stream_type and a payload:

EventSent when
connected (system.connected)Once, when you subscribe
heartbeat (system.heartbeat)After 15 seconds without other events
job.statusA job is created or changes status
job.logA job gets a new log entry
agent.statusAn agent goes online or offline
agent.request.statusA request that is not stored as a job changes status
agent.request.outputSuch a request returns output
discovery.review.changedThe review queue changed
discovery.rules.changedReview rules changed
discovery.subjects.changedDiscovered devices changed
discovery.introspection.changedDevice scans start, or their policy changes
discovery.controls.changedA field is set to Manual or Managed through the controls API

Treat an event as a hint to re-read the REST resource, not as a record you must not miss:

  • Each subscriber has a queue of 128 events. When a slow client falls behind, the oldest events are dropped.
  • Nothing is replayed after a reconnect. Re-read what you show after every reconnect.
  • Events are not filtered by site. Check payload.site_id where it is present.
  • Events live in the server process. They are lost on restart.

Agents​

Agents connect to /ws/agent over a WebSocket, authenticated with their token. That protocol is for the MiniPAM agent only; integrations should use REST and events. To see how it works, read Server and agent architecture.

Health​

GET /health needs no authentication and returns {"status": "ok"} when the server is up. It does not check agents, scans, or scheduled jobs.