HTTP server¶
The HTTP server provides an API to interact with Sentinela. The available routes are organized into two main categories, based on the deployment setup.
Important
By default the API is served at port 8000. The docker compose files also expose the port 8000, so if the port for the server changes, the compose files should be updated accordingly. Another option is to keep the server port at 8000 and changing only the compose files. Using the configuration 8080:8000, for example, will keep the server running at port 8000, but it will be accessible through the container's port 8080.
If the container is deployed with the Controller (either standalone or alongside the Executor in the same container), all routes are available, allowing interactions with Monitors, Issues, Alerts and the dashboard.
If the container is deployed with only the Executor, only base routes are available.
The HTTP server configuration variables can be set at the configs.yaml file.
Base routes¶
The following routes are always available, regardless of the deployment setup.
Status¶
GET /status
Returns the current status of the container components, along with internal metrics for system insights.
Prometheus Metrics¶
GET /metrics
Exposes Prometheus-formatted metrics, enabling external monitoring and observability of the application.
Interaction routes¶
These routes are available only when the container deployment includes the Controller component.
Command routes check http_server.commands in configs.yaml (see Configuration file). Users without the required role receive 403 {"status": "forbidden"}. Disabled commands receive 403 with Command '<command>' is disabled.
Dashboard¶
/dashboard
Serves a simple dashboard interface, providing a quick way to create, enable or disable and change the monitors code.
List monitors¶
GET /monitors/list
Returns a list of all monitors currently registered with the id, name and enabled fields for each monitor.
Response example:
[
{
"id": 123,
"name": "monitor_name",
"enabled": true,
"active_alerts": 3,
"not_acknowledged_alerts": 1
},
{
"id": 124,
"name": "another_monitor",
"enabled": false,
"active_alerts": 0,
"not_acknowledged_alerts": 0
}
]
List monitors active alerts¶
GET /monitor/{monitor_id}/alerts
Returns a list of all active alerts for the provided monitor id.
Response example:
[
{
"id": 12,
"status": "active",
"acknowledged": false,
"is_priority_acknowledged": false,
"locked": false,
"priority": 2,
"acknowledge_priority": null,
"can_acknowledge": true,
"can_lock": true,
"can_solve": false,
"created_at": "2025-01-01 12:34:56", # Already localized from UTC
},
{
"id": 34,
"status": "active",
"acknowledged": true,
"is_priority_acknowledged": true,
"locked": true,
"priority": 2,
"acknowledge_priority": 2,
"can_acknowledge": false,
"can_lock": false,
"can_solve": false,
"created_at": "2025-01-01 23:45:55", # Already localized from UTC
}
]
Get monitor¶
GET /monitor/{monitor_name}
Returns the monitor details for the monitor with the provided monitor_name.
Response example:
{
"id": 123,
"name": "monitor_name",
"enabled": true,
"queued": false,
"running": false,
"search_executed_at": "2025-01-01 09:34:56", # Already localized from UTC
"update_executed_at": "2025-11-12 10:14:15", # Already localized from UTC
"last_heartbeat": "2025-01-02 00:04:05", # Already localized from UTC
"code": "...",
"additional_files": {"file_name.txt": "..."},
"documentation": "# Monitor documentation"
}
Disable monitor¶
POST /monitor/{monitor_name}/disable
Disable the monitor with the provided monitor_name.
This request is not executed immediately, it's queued for an Executor to run.
Enable monitor¶
POST /monitor/{monitor_name}/enable
Enable the monitor with the provided monitor_name.
This request is not executed immediately, it's queued for an Executor to run.
Refresh monitor¶
POST /monitor/{monitor_name}/refresh
Queue the monitor with the provided monitor_name for refresh.
This request is not executed immediately, it's queued for an Executor to run.
Request body example:
{
"tasks": ["search", "update"]
}
The tasks field must be a non-empty list containing only search and/or update.
Response example:
{
"status": "monitor_refresh_queued",
"monitor_name": "monitor_name",
"tasks": ["search", "update"]
}
Validate monitor¶
POST /monitor/validate
Validate the monitor code provided without registering it.
For more information, check the Validating a monitor documentation.
Request body example:
{
"monitor_code": "...",
}
Response example:
{
"status": "monitor_validated"
}
Register monitor¶
POST /monitor/register/{monitor_name}
Register the monitor with the provided monitor_name.
For more information, check the Registering a monitor documentation.
Request body example:
{
"monitor_code": "...",
"additional_files": {"file_name.txt": "..."}
}
Response example:
{
"status": "monitor_registered",
"monitor_id": 123
}
Get alert¶
GET /alert/{alert_id}
Returns the details for the alert with the provided alert_id.
Response example:
{
"id": 12,
"status": "active",
"acknowledged": false,
"is_priority_acknowledged": false,
"locked": false,
"priority": 2,
"acknowledge_priority": null,
"can_acknowledge": true,
"can_lock": true,
"can_solve": false,
"created_at": "2025-01-01 12:34:56" # Already localized from UTC
}
List alert active issues¶
GET /alert/{alert_id}/issues
Returns a list of all active issues for the provided alert_id.
Response example:
[
{
"id": 123,
"status": "active",
"model_id": 456,
"data": {...},
"created_at": "2025-01-01 12:34:56" # Already localized from UTC
},
{
"id": 124,
"status": "active",
"model_id": 567,
"data": {...},
"created_at": "2025-01-01 13:34:45" # Already localized from UTC
}
]
Acknowledge alert¶
POST /alert/{alert_id}/acknowledge
Acknowledge the alert with the provided alert_id.
This request is not executed immediately, it's queued for an Executor to run.
Lock alert¶
POST /alert/{alert_id}/lock
Lock the alert with the provided alert_id.
This request is not executed immediately, it's queued for an Executor to run.
Solve alert¶
POST /alert/{alert_id}/solve
Solve the alert with the provided alert_id.
This request is not executed immediately, it's queued for an Executor to run.
Drop issue¶
POST /issue/{issue_id}/drop
Drop the issue with the provided issue_id.
This request is not executed immediately, it's queued for an Executor to run.
Auth¶
All dashboard pages and API routes require a login session, except /status, /metrics and the auth endpoints below. Unauthenticated API requests return 401 {"status": "unauthorized"} and unauthenticated dashboard pages redirect to /dashboard/login.html.
On the first startup with an empty users table, a default admin user with password admin is created. Change the password after the first login.
Sessions are signed JWTs sent as an HttpOnly cookie named sentinela_session. Changing the password revokes all existing sessions. When serving the dashboard over HTTPS, set http_server.auth.cookie_secure to true so the cookie gets the Secure flag and is never sent over plain HTTP.
Tokens are signed with the SENTINELA_AUTH_SECRET environment variable (see Configuration). If unset, an ephemeral secret is generated on startup and sessions invalidate on restart.
Login¶
POST /auth/login
Request body example:
{
"username": "admin",
"password": "admin"
}
Logout¶
POST /auth/logout
Current user¶
GET /auth/me
Returns the current user with the username, role (admin or user), require_change_password and is_active fields.
List users¶
GET /auth/users
Admin only. Returns all users with id, username, role, has_password, require_change_password and is_active.
Create user¶
POST /auth/users
Admin only. Creates a user without a password and returns a single-use invite link valid for http_server.auth.invite_expire_hours (default 1 hour).
Request body example:
{
"username": "new_user",
"role": "user"
}
Response example:
{
"status": "user_created",
"id": 2,
"username": "new_user",
"role": "user",
"invite_url": "/dashboard/set-password.html?token=..."
}
Recreate invite¶
POST /auth/users/{username}/invite
Admin only. Creates a fresh invite link for a user that hasn't set a password yet, invalidating the previous one. Returns 404 {"status": "user_not_found"} for unknown users or 400 {"status": "password_already_set"} if the user already has a password.
Validate invite¶
GET /auth/invite/validate?token=...
Returns {"status": "valid", "username": "..."}, 404 {"status": "invalid_token"} or 410 {"status": "expired_token"}.
Disable user¶
POST /auth/users/{username}/disable
Admin only. Deactivates the user and revokes all their sessions. Disabled users cannot login and their requests return 401 {"status": "unauthorized"}. Admins cannot disable themselves (400 {"status": "cannot_disable_self"}). Unknown users return 404 {"status": "user_not_found"}.
Enable user¶
POST /auth/users/{username}/enable
Admin only. Reactivates a disabled user. Unknown users return 404 {"status": "user_not_found"}.
Set password¶
POST /auth/set-password
Sets the password with an invite token (single-use) and logs the user in. Passwords must be 12-128 characters with uppercase, lowercase, digit and special character, and must not contain the username.
Request body example:
{
"token": "...",
"password": "NewStrong123!"
}
Change password¶
POST /auth/change-password
Changes the current user's password. Also clears the require_change_password flag.
Request body example:
{
"current_password": "admin",
"new_password": "NewStrong123!"
}