Alarum

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.

A plain machine-readable version of this guide lives at /llms.txt . Fetch that directly.

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 accepted
  • 400, invalid payload (bad JSON, missing title, invalid level)
  • 401, unknown or revoked token
  • 429, rate limit hit (1000 events/hour/token), with a Retry-After header

Payload schema

Native alarum format. Only title is required.

FieldTypeRequiredNotes
levelenumoptionalinfo | success | warn | error | critical, default "info"
titlestringrequiredmax 256 chars
messagestringoptionalmax 8000 chars, multi-line OK
tagsstring[]optionalmax 16, each max 32 chars, slugified
sourcestringoptionalmax 64, e.g. "github-actions"
urlstringoptionalmax 1024, link shown in the event detail
fieldsobject[]optionalmax 25, { name, value, inline }, Discord-embed style
timestampstringoptionalISO 8601, event time; defaults to received time
footerstringoptionalmax 256
authorobjectoptional{ name, url }
colorstringoptional#RRGGBB hex, overrides the level color

Levels & semantics

infoNeutral informational event. Push OFF by default.
successSomething completed OK. Push ON by default.
warnNeeds attention but not broken. Push ON.
errorSomething failed. Push ON.
criticalUrgent failure. Push ON; can bypass quiet hours.

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.

Do not confuse the two. 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 a webUrl.
  • GET /api/v1/events/<id>, one event plus its raw payload.
  • POST or DELETE /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/projects and /api/v1/workspaces, what the token can reach, with unread counts, to offer a scope selector. Each project also carries push, 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 source to identify where the event came from; use tags for 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.