API reference
All endpoints are under the same HTTPS address as the UI.
| Endpoint | Who | Purpose |
|---|---|---|
POST /api/v1/logs |
access token, or admin | Raw log text, one entry per line, read with the source's parser. Optional source (program name) and severity query params. |
POST /api/v1/events |
access token, or admin | JSON array of OCSF events (up to 10,000 per request). |
GET /api/v1/search |
any signed-in user | q, start, end (RFC3339 or epoch ms), severity, category, class, src_ip, dst_ip, user, source (program), source_id, host, country, asn, threat=true, limit (max 1000), offset. Newest first. Each event includes its parsed message, its source_name, extra parsed fields and enrichment, and raw_data, the original line (empty once it has been removed, 24 hours after the event arrived). |
GET /api/v1/stats?hours=24 |
any signed-in user | Dashboard figures for the last 1-2160 hours. |
GET /api/v1/sources |
any signed-in user | Admins get every source; others get the names of the sources they can see. |
POST /api/v1/sources, PATCH/DELETE /api/v1/sources/{id} |
admin | Create an access token ({"name", "parser_id", "parser_none"}), rename, set how its lines are read ("parser_id": 3 for a parser, "parser_id": null for Automatic, "parser_none": true for None; not both together), and switch a token on or off ("enabled": true or false; to disable a token use PATCH, not DELETE). DELETE removes the source and its token for good (it used to revoke the token); it returns 409 naming the alert rules that are scoped to the source, and 400 for built-in sources. Only access tokens can be enabled, disabled or deleted. A source shows parser_none and enabled in its JSON (revoked_at is set while it's disabled). |
GET/POST /api/v1/users, PATCH/DELETE /api/v1/users/{id}, POST /api/v1/users/{id}/password |
admin | Manage users: {"username", "password", "role", "limited", "sources"}. A limited standard user sees only sources. Updates change only the fields sent. |
GET/POST /api/v1/parsers, GET/PUT/DELETE /api/v1/parsers/{id}, GET /api/v1/parsers/templates, GET /api/v1/parsers/severity-defaults |
admin | Manage parsers; the templates, and the default keyword rules for a parser's severity. |
GET /api/v1/alerts?status=open |
any signed-in user not limited to some sources | Alerts (open, acknowledged, closed or all) and the count in each state. |
PATCH /api/v1/alerts/{id} |
same | Acknowledge, close or reopen: {"status": "acknowledged"}. |
GET /api/v1/rules, POST /api/v1/rules, PUT/DELETE /api/v1/rules/{id} |
any signed-in user (list), admin | Alert rules: {"name", "description", "enabled", "severity", "query", "min_severity", "threat_only", "source_id", "group_by", "threshold", "window_minutes", "kind"}. kind is match (the default), or volume_over / volume_under to alert when the source in source_id (required) sends more than / fewer than threshold events in window_minutes; those ignore query, min_severity, threat_only and group_by. |
GET /api/v1/system |
admin | Database size and version, uptime, backups folder and free space. |
GET/PUT /api/v1/system/tls, POST /api/v1/system/tls/check |
admin | The HTTPS certificate: {"mode": "self-signed"/"letsencrypt", "domain"}; the reply describes the certificates, whether one is being obtained, the last error and what the domain resolves to. The check ({"domain"}) says whether that name on port 443 reaches this SIEMLite. |
GET /.well-known/siemlite-check/{token} |
public | Answers the check above with its one-time token. |
GET /api/v1/integrations |
admin | The built-in integrations and their state: {"integrations": [{"id", "name", "description", "state": "needs_setup"/"off"/"on"/"error", "summary", "configured", "enabled"}]}. |
POST /api/v1/integrations/{id}/enabled |
admin | Turn an integration on or off, keeping its settings: {"enabled": true}. Refused until it is set up. |
GET/PUT /api/v1/integrations/email, POST /api/v1/integrations/email/test |
admin | The email settings ({"host", "port", "security": "starttls"/"tls"/"none", "username", "password", "from_address", "from_name", "skip_verify"}; the password is write-only, and leaving it out keeps the saved one) and a test send (the same fields plus "to"). These were /api/v1/system/email in v0.10, which still works. |
GET/PUT /api/v1/integrations/entra, POST /api/v1/integrations/entra/test, POST /api/v1/integrations/entra/sync |
admin | The Microsoft Entra ID settings ({"tenant_id", "client_id", "client_secret", "public_url", "access_group_id", "admin_group_id"}; the client secret is write-only, and leaving it out keeps the saved one, but only for the same tenant and app), a connection test (the same fields; reports the groups it can read), and an immediate membership check. |
GET /api/v1/auth/providers, GET /api/v1/auth/entra/start, GET /api/v1/auth/entra/callback |
public | The sign-in page's "Continue with Microsoft": which buttons to show, where the browser is sent to sign in, and where Microsoft sends it back. Not for scripts. |
GET/POST /api/v1/backups, PUT /api/v1/backups/settings, POST /api/v1/backups/upload |
admin | List backups and the job status, start a backup, set the schedule ({"interval_hours": 0/6/24/168, "keep"}), upload a backup file. |
GET/DELETE /api/v1/backups/{name}, POST /api/v1/backups/{name}/restore |
admin | Download or delete a backup; restore it (SIEMLite restarts). |
GET/PUT /api/v1/integrations/ai, POST /api/v1/integrations/ai/test, GET /api/v1/integrations/ai/cloud-models |
admin | The AI Parsers settings ({"provider": "local"/"openrouter"/"anthropic"/"google"/"openai"/"nvidia", "ollama_url", "local_model", "cloud_model", "send_addresses", "api_key", "key_for"}; api_key is write-only and is for the service key_for (or provider): leaving it out keeps the saved one and "" removes it; openrouter_key from v0.19 still works), with this server's hardware, the recommended model and the download's progress; a connection test (the same fields); and a service's models with the ones recommended (GET ?provider= uses the saved key, POST {"provider", "api_key"} the one given). |
POST /api/v1/parsers/test, POST /api/v1/parsers/draft, POST /api/v1/parsers/suggest |
admin | Run a parser over {"definition", "lines"}; draft a parser with no AI model from {"text"} (pasted text; pretty-printed JSON is split into objects) or {"lines"}, answering the definition, how many samples it reads, and the samples as lines; ask the AI model for a parser for {"lines"}. |
POST /api/v1/login, POST /api/v1/logout, GET /api/v1/me |
Browser sign-in, sign-out and current session (/me includes auth_provider: local or entra, and display_name for a Microsoft account). A password sign-in refused by a sign-in restriction gets 403. |
|
GET/PUT /api/v1/system/retention |
admin | How long events are kept: {"days"} (1 to 3650). The answer also gives the default, whether the page has set it, and the late-ingestion thresholds; shortening it deletes the events now too old, at once. |
GET/PUT /api/v1/system/signin |
admin | The sign-in restrictions: {"admin_local_only", "entra_only"} (send either). The answer also says what is enforced now, the local port, and whether the request came in on it. Turning either on is refused without a local port; Microsoft-only also needs sign-in with Microsoft on and a local Admin account named admin. |
POST /api/v1/me/password |
any signed-in user | Change your own password: {"current_password", "new_password"}. After 10 wrong current passwords in 15 minutes the account can't try again for the rest of the window (a limit of its own, separate from signing in); your other sessions end, this one continues. Refused for Microsoft accounts. |
GET /health |
public | Up/down only. When signed in it also returns event count, database size, ingest queue state, indicator count and syslog counters. |
Applications authenticate with Authorization: Bearer <token>. A missing or disabled token, or one whose source was deleted, returns 401; a token used
for anything but sending logs returns 403.
Events are stored under their own date, however late they arrive, as long as it is within the retention period (two years by default; see Keeping events) and no more than a day ahead (a sender's clock can run a little fast). Others are refused and counted as rejected, with the reason, since each day's events are kept in their own file.
Log parsing
/api/v1/logs converts each line into an OCSF event: syslog (RFC 3164 and 5424) headers give the time and hostname,
the first two IPv4 addresses become source and destination, a user is picked up from patterns like for user alice,
and severity comes from the syslog priority or keywords (error, failed, warning, ...). JSON objects that already
contain category_uid are stored as OCSF; other JSON uses its message, level and timestamp fields. The detection
is heuristic; use ?severity= to override it, or give the source a parser. The message stored with an event is the
text after the syslog header (the whole line when there isn't one). A line that only starts with a timestamp, such as
2026-10-04T13:42:07Z ERROR payment failed, gets its time from it but no hostname.
This is the Automatic setting of a source. None skips detection: each line is stored as it is, with the line as
its message, the time it arrived, Informational severity and no addresses, user or host. ?source= and ?severity=
still apply, and threat intel still checks the line.