Skip to main content
Most operators use the web UI for daily work. This guide is for automation: scripting repetitive tasks, integrating with CI/CD pipelines, or building custom tooling on top of OpenWatch. OpenWatch exposes 80+ REST endpoints under the /api prefix. All endpoints require JWT Bearer tokens unless noted otherwise.
For the full schema reference, see the Swagger UI at http://localhost:8000/api/docs (available when OPENWATCH_DEBUG=true).

Authentication

Log in

TOKEN=$(curl -s -X POST http://localhost:8000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"yourpassword"}' | jq -r '.access_token')
Response includes access_token (1 hour) and refresh_token (7 days).

Refresh token

curl -s -X POST http://localhost:8000/api/auth/refresh \
  -H "Authorization: Bearer $TOKEN"

Log out

curl -s -X POST http://localhost:8000/api/auth/logout \
  -H "Authorization: Bearer $TOKEN"
All subsequent examples assume -H "Authorization: Bearer $TOKEN".

Hosts

MethodEndpointPurpose
GET/api/hosts/List all hosts
POST/api/hosts/Add a host
GET/api/hosts/{id}Get host details
PUT/api/hosts/{id}Update host
DELETE/api/hosts/{id}Delete host
POST/api/hosts/validate-credentialsTest SSH connectivity

Add a host

curl -s -X POST http://localhost:8000/api/hosts/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "rhel9-web01.example.com",
    "ip_address": "10.0.1.50",
    "port": 22,
    "username": "openwatch",
    "auth_method": "key",
    "ssh_private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n..."
  }'

Host groups

MethodEndpointPurpose
GET/api/host-groups/List groups
POST/api/host-groups/Create group
PUT/api/host-groups/{id}Update group
DELETE/api/host-groups/{id}Delete group
POST/api/host-groups/{id}/hostsAssign hosts
POST/api/host-groups/{id}/scanStart group scan

Scanning

Start a compliance scan

curl -s -X POST http://localhost:8000/api/scans/kensa/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "host_id": "550e8400-e29b-41d4-a716-446655440000",
    "framework": "cis-rhel9-v2.0.0"
  }'
Optional fields: framework, severity (list), category.

Scan endpoints

MethodEndpointPurpose
GET/api/scans/kensa/healthEngine health
GET/api/scans/kensa/frameworksAvailable frameworks
GET/api/scans/kensa/compliance-state/{host_id}Latest compliance state
GET/api/scans/List all scans
GET/api/scans/{scan_id}Scan details
GET/api/scans/{scan_id}/resultsScan results
GET/api/scans/{scan_id}/failed-rulesFailed rules only
GET/api/scans/{scan_id}/report/jsonJSON report
GET/api/scans/{scan_id}/report/csvCSV report
GET/api/scans/{scan_id}/report/htmlHTML report

Compliance posture

MethodEndpointPurpose
GET/api/compliance/posture?host_id={id}Current posture
GET/api/compliance/posture?host_id={id}&as_of=2026-01-15Historical posture
GET/api/compliance/posture/history?host_id={id}&start_date=...&end_date=...Posture over time
GET/api/compliance/posture/drift?host_id={id}&start_date=...&end_date=...Drift detection
POST/api/compliance/posture/snapshotCreate manual snapshot

Compliance exceptions

MethodEndpointPurpose
GET/api/compliance/exceptionsList exceptions
GET/api/compliance/exceptions/summaryException statistics
POST/api/compliance/exceptionsRequest new exception
GET/api/compliance/exceptions/{id}Exception details
POST/api/compliance/exceptions/{id}/approveApprove (admin)
POST/api/compliance/exceptions/{id}/rejectReject (admin)
POST/api/compliance/exceptions/{id}/revokeRevoke (admin)
POST/api/compliance/exceptions/checkCheck if rule is excepted

Create exception request

curl -s -X POST http://localhost:8000/api/compliance/exceptions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rule_id": "sshd-strong-ciphers",
    "host_id": "550e8400-e29b-41d4-a716-446655440000",
    "justification": "Legacy system requires weak cipher for 30 days",
    "duration_days": 30
  }'

Alerts

MethodEndpointPurpose
GET/api/compliance/alertsList alerts
GET/api/compliance/alerts/statsAlert statistics
GET/api/compliance/alerts/{id}Alert details
POST/api/compliance/alerts/{id}/acknowledgeAcknowledge
POST/api/compliance/alerts/{id}/resolveResolve
GET/api/compliance/alerts/thresholdsGet thresholds
PUT/api/compliance/alerts/thresholdsUpdate thresholds
Query parameters: status, severity, alert_type, host_id, page, per_page.

Remediation

MethodEndpointPurpose
POST/api/compliance/remediationCreate remediation job
POST/api/compliance/remediation/planPreview plan (dry-run)
POST/api/compliance/remediation/check-rulesCheck rule remediation support
GET/api/compliance/remediationList jobs
GET/api/compliance/remediation/summaryJob statistics
GET/api/compliance/remediation/{job_id}Job details with results
GET/api/compliance/remediation/{job_id}/results/{result_id}/stepsStep-level results
POST/api/compliance/remediation/{job_id}/cancelCancel job
POST/api/compliance/remediation/rollbackRollback completed job

Create remediation job

curl -s -X POST http://localhost:8000/api/compliance/remediation \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "host_id": "550e8400-e29b-41d4-a716-446655440000",
    "rule_ids": ["sshd-disable-root-login", "sshd-strong-ciphers"]
  }'
Returns HTTP 202. The job executes asynchronously via Celery.

Audit and export

Saved queries

MethodEndpointPurpose
GET/api/compliance/audit/queriesList saved queries
POST/api/compliance/audit/queriesCreate saved query
GET/api/compliance/audit/queries/{id}Get query
PUT/api/compliance/audit/queries/{id}Update query
DELETE/api/compliance/audit/queries/{id}Delete query
POST/api/compliance/audit/queries/previewPreview results
POST/api/compliance/audit/queries/{id}/executeExecute saved query

Exports

MethodEndpointPurpose
GET/api/compliance/audit/exportsList exports
POST/api/compliance/audit/exportsCreate export (json, csv, pdf)
GET/api/compliance/audit/exports/{id}Export details
GET/api/compliance/audit/exports/{id}/downloadDownload file
curl -s -X POST http://localhost:8000/api/compliance/audit/exports \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query_id": "uuid-of-saved-query", "format": "csv"}'

Rules reference

MethodEndpointPurpose
GET/api/rules/referenceList rules (search, filter, paginate)
GET/api/rules/reference/{rule_id}Full rule details
GET/api/rules/reference/statsRule statistics
GET/api/rules/reference/frameworksList frameworks
GET/api/rules/reference/categoriesList categories
GET/api/rules/reference/variablesConfigurable variables
Query parameters: search, framework, category, severity, has_remediation, page, per_page.

Administration

User management

MethodEndpointPurpose
GET/api/users/List users
POST/api/users/Create user (SUPER_ADMIN)
GET/api/users/{id}Get user
PUT/api/users/{id}Update user
DELETE/api/users/{id}Delete user

SSH configuration

MethodEndpointPurpose
GET/api/ssh/settings/policyGet SSH policy
POST/api/ssh/settings/policyUpdate SSH policy
GET/api/ssh/settings/known-hostsList known hosts
POST/api/ssh/settings/known-hostsAdd known host
DELETE/api/ssh/settings/known-hosts/{hostname}Remove known host
GET/api/ssh/settings/test-connectivity/{host_id}Test connectivity

System endpoints

MethodEndpointAuthPurpose
GET/healthNoneApplication health
GET/security-infoAdminFIPS mode and encryption config
GET/metricsNonePrometheus metrics

Error responses

CodeMeaning
400Bad request — invalid input or business rule violation
401Unauthorized — missing or expired token
402Payment required — OpenWatch+ license needed
403Forbidden — insufficient role or permission
404Not found
422Validation error — field-level detail included
429Rate limit exceeded
500Internal server error

Rate limits

  • 100 requests per minute per authenticated user
  • 1,000 requests per minute per source IP