n8n
In obserae: create a Webhook output with a signing secret. There is no n8n output type — the n8n node runs inside n8n, and its trigger listens to that webhook.
That sentence is the one people miss. Looking for “n8n” in the obserae output list will not find anything, and nothing is wrong.
| Where to get it | npm: n8n-nodes-obserae |
| Alert contract | obserae.alert/2 |
| SOAR profile | 1.0.0 |
| Requires | n8n 1.x |
The node is versioned against those two contracts, never against an obserae release: adding a field to the alert is not a breaking change and does not need a new node.
Install
Community nodes (self-hosted n8n): Settings → Community Nodes → Install →
n8n-nodes-obserae. Restart n8n.
Credential
obserae API takes your instance’s base URL and an API token. Mint the token
in obserae under Identity & Access → Users → + New token, on a user whose
group holds sessions:read, alerts:read, alerts:ack, cartography:read
and rules:read — see a token for a playbook.
Click Test: it calls GET /api/status and must go green.
The trigger — receiving alerts
- Add the obserae Trigger node and copy its production URL.
- In obserae, Connectors → Outputs → + New output, type Webhook, URL = that address, and set a signing secret.
- Paste the same secret into the node.
The node recomputes the HMAC over "<timestamp>.<rawBody>", compares it in
constant time, and answers 401 with no detail when it does not match — an
error naming which part was wrong tells a prober how close they are. It reads
the raw body before parsing: re-serialising JSON changes the bytes and the
signature would never match again.
It refuses to run at all with no secret configured. A trigger that accepts an unverified body is an endpoint anyone on the internet can start your incident response with.
What reaches the workflow is the alert document plus five fields lifted from the headers, so a branch can route without parsing:
signatureVerified: true
eventType: alert.fired | alert.resolved | alert.acknowledged | test
deliveryId: unique per delivery — deduplicate on it
schemaVersion: obserae.alert/2
instanceId: which obserae sent it
The node — asking obserae questions
Eight actions, covering the inbound half of the SOAR profile:
| Resource | Operation | Calls |
|---|---|---|
| Enrichment | Lookup | GET /api/enrichment/lookup — one address or up to 50 |
| Context | Get Host Context | GET /api/context/host |
| Context | Get Peers | POST /api/context/peers |
| Policy | Check | POST /api/policy/check |
| Alert | Get Many | GET /api/alerts |
| Alert | Get | GET /api/alerts/{id} |
| Alert | Set Status | POST /api/alerts/{id}/status |
| Indicator | Export | GET /api/indicators |
Three details are worth knowing before building on them.
Enrichment takes a batch. Put several addresses in the field, separated by commas, and they go out as one call. Above 50 obserae refuses the request rather than truncating it — a workflow handed part of its batch would decide on part of its evidence.
As Of is how you look at the past. Every window (1h, 24h, 7d) is a
closed vocabulary, because it is what bounds the scan on the server. To ask what
a host was doing when an alert fired, keep the window and set As Of to the
alert’s fired_at. To compare against a baseline, move As Of back a week and
keep everything else identical.
The Indicator action carries If-None-Match. Store the ETag you got, send
it back on the next poll, and act only on a 200.