Integration guide for AI agents
Alarum is a centralized webhook/event hub. Scripts, CI pipelines, cron jobs and services send events over a single HTTP POST. The user reads them in a unified inbox, gets push notifications, and can re-forward them to Discord or Slack. This page explains how to integrate event-sending into a user's project.
Getting a token
Tokens are created by the human user in the Alarum UI (a project's Settings → Tokens, or its Integration tab). A token looks like alrm_… and belongs to exactly one project. You do not create tokens yourself, ask the user to create a project + token and hand you the token. Treat it as a secret: env var or CI secret, never committed.
Ingestion endpoint
POST https://alarum.me/h Authorization: Bearer <TOKEN> Content-Type: application/json (body = the event payload, JSON)
204, event accepted400, invalid payload (bad JSON, missing title, invalid level)401, unknown or revoked token429, rate limit hit (1000 events/hour/token), with aRetry-Afterheader
Payload schema
Native alarum format. Only title is required.
| Field | Type | Required | Notes |
|---|---|---|---|
| level | enum | optional | info | success | warn | error | critical, default "info" |
| title | string | required | max 256 chars |
| message | string | optional | max 8000 chars, multi-line OK |
| tags | string[] | optional | max 16, each max 32 chars, slugified |
| source | string | optional | max 64, e.g. "github-actions" |
| url | string | optional | max 1024, link shown in the event detail |
| fields | object[] | optional | max 25, { name, value, inline }, Discord-embed style |
| timestamp | string | optional | ISO 8601, event time; defaults to received time |
| footer | string | optional | max 256 |
| author | object | optional | { name, url } |
| color | string | optional | #RRGGBB hex, overrides the level color |
Levels & semantics
Pick the level that matches real severity, don't send everything as error.
Accepted formats
The format is auto-detected. alarum = the native schema above (use this). discord = a Discord webhook payload ({ "embeds": [...] }) is accepted and normalized. raw = any other JSON is stored as-is in the message field. Force it with the header X-Alarum-Format: alarum|discord|raw.
Examples in every language
Pick a language or runner. The snippet auto-fills with a sample payload; replace <YOUR_TOKEN> with a real token the user gives you.
curl -X POST 'https://alarum.me/h' \
-H 'Authorization: Bearer <YOUR_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{"level":"success","title":"Deploy succeeded","message":"v1.2.3 shipped to production","source":"github-actions"}'11 ready-made examples: cURL, GitHub Actions, GitLab CI, Codeberg CI, JavaScript (fetch + axios), Python, PHP, Go, Ruby, PowerShell, generic Bash. Same payload schema across all of them. Pick yours in the dropdown above.
Reading events back
Everything above sends events. There is also a read API, for a client that shows a user's events outside the browser: a terminal panel, a status line, a CLI.
It takes a different kind of token, scoped to the account rather than to one project, created by the human under Settings → Your agent. It reads every project that account can reach and can mark events read. It is a paid-plan feature: on Discover every call answers 403 plan_required.
alrm_… is an ingestion secret bound to one project and can only POST to /h. alrm_at_… can read everything its owner can see, so it never belongs in a CI job. GET https://alarum.me/api/v1/events?limit=20 Authorization: Bearer alrm_at_...
GET /api/v1/me, who the token belongs to, the plan and the rate limit. One call to check a token at startup.GET /api/v1/events, newest first. Filters:project,workspace,level,tag,source,unread=1,from,to,limit(1-200),before(the cursor). Answers{ events, nextCursor, hasMore }, each event carrying its project and awebUrl.GET /api/v1/events/<id>, one event plus its raw payload.POSTorDELETE /api/v1/events/<id>/read, mark it read or unread. Idempotent, and recorded as the token's owner, so the web inbox stays in step.GET /api/v1/projectsand/api/v1/workspaces, what the token can reach, with unread counts, to offer a scope selector. Each project also carriespush, the levels the account asked to be notified about for it: announce on those rather than inventing your own threshold.
Polling: keep the receivedAt of the newest event you have seen and ask for from=<that>+1, so the steady state is an empty list. 30 seconds is the cadence the web app itself uses; faster buys nothing (events are not pushed to this API) and eats into the per-minute cap, which answers 429 with a Retry-After.
Best practices
- Send events at meaningful checkpoints: deploy done, build failed, backup completed, cron ran, error caught.
- One token per source, the user can revoke a token without affecting others.
- Give a clear, human-readable
title, it's what shows in the inbox list and the push notification. - Use
sourceto identify where the event came from; usetagsfor filtering. - Don't spam, the limit is 1000 events/hour/token. Batch or throttle noisy sources.
- The token is a secret. Env var / CI secret only, never commit it.
No management API (yet)
Events can be sent (/h) and read (/api/v1), but nothing can be created or configured through an API: no projects, no tokens, no forwarders, no notification rules. All of that is managed by the human in the Alarum UI. If you need a project or a token, ask the user to create it and give it to you.