Add a webhook
Open Settings → Organization settings → Webhooks and choose Add webhook. Only organization administrators can manage webhooks; an agent working on a branch server cannot.- Name it after the system that receives it, so you know which one to pause later.
- Endpoint must be
https://with no username, password or fragment. Addresses on private networks, the local machine and other special-purpose ranges are refused, both when you save and again at every delivery: the name is resolved afresh each time and the connection is made only to the addresses that passed. - Project limits deliveries to one project; leave it empty to receive events from every project in the organization. Deleting a project removes the webhooks limited to it; organization-wide webhooks keep their history.
- Events: choose at least one from the list below.
Events
The two
observe.alert events come from monitors in Observe. A monitor can name
the webhooks it notifies; it then delivers only to those, and otherwise to every
webhook that subscribed to the event and covers the monitor’s project. value is null when the
condition had no row to judge, and group is empty for a monitor without
group_by.
Events describe transitions, not every change: a push that only moves a branch
forward, an edit to an issue’s title, or a CI run that is still running send
nothing. The list in the editor comes from your workspace’s control plane, so a
newly supported event appears there without a docs change.
What a delivery looks like
Each delivery is an HTTPSPOST with a JSON body, Content-Type: application/json,
the user agent ReasonOS-Webhooks/1.0 and these headers:
The body carries the event, when it happened, the organization and project, who
acted, the resource it concerns, and the fields listed above as they were at the
moment of the event:
actor.id is the acting member’s id, or empty when the platform itself acted (a
CI run finishing, a branch observed during a sync). The body is written once, when
the event happens, and never rebuilt: a retry a day later still describes the state
at that moment. Payloads are at most 256 KB and never contain secrets, issue
bodies, comments, document contents or branch-server addresses.
Verify the signature
The signed text is the value ofX-ReasonOS-Timestamp, a single ., and the raw
request body, in that order. Compute HMAC-SHA256 over it with the webhook’s
secret exactly as shown to you (the whsec_ prefix is part of the key), encode the
result as lowercase hex, and compare it in constant time with the value after
sha256=. Reject anything that does not match, and anything whose timestamp is
older than you are willing to accept — five minutes is a common choice.
Node.js
Python
false (False), without raising, for a missing header, a
timestamp such as "1760000000²" or "-5", a signature in uppercase hex, one that
is too short or long, or one with non-ASCII characters. Answer such a delivery with
a non-2xx status such as 401. ReasonOS counts it as a failed attempt and retries it
on the schedule below; every delivery ReasonOS signs has these shapes.
Answer with any 2xx status within ten seconds; do your own processing after you
have answered. Anything else, no answer, a redirect or a certificate ReasonOS
cannot verify counts as a failed attempt. ReasonOS records only the status code you
answered, never the response body.
Retries and redelivery
Each delivery gets up to five attempts. After a failed attempt ReasonOS waits 10 seconds, then 1 minute, 5 minutes and 30 minutes before the next one. After the fifth failure the delivery is marked failed. Deliveries stay visible for thirty days; an event older than that is not delivered. On the webhook’s row, the chevron opens Recent deliveries: each event, the status your receiver answered, the number of attempts and the time of the next retry. Redeliver queues another attempt of a finished delivery, delivered or failed, with five fresh attempts: it keeps the same delivery id and the same payload, so your receiver’s de-duplication onX-ReasonOS-Delivery still applies.
A delivery that is still pending cannot be redelivered; it will be retried on its
own.
Pausing a webhook stops new deliveries: events that happen while it is paused are
not delivered later, and deliveries that were already queued resume when you
resume it. Deleting a webhook discards its unsent deliveries. A request that is
already on its way cannot be recalled.