Skip to main content

Workspace Webhooks

A webhook tells a system you own that a review needs an answer, or that a verdict was recorded. RateLoop signs every delivery, retries a failing one, and pins the address it resolved so nothing can move the destination out from under a request in flight.

Where to set one up

Open Settings → Integrations and use the Webhooks section. Owners and admins can add and disable endpoints; other members cannot. The signing secret is shown once, at creation, and is never readable again.

An endpoint cannot be re-keyed in place, and disabling one keeps its URL claimed, so adding the identical URL back is refused. To replace a lost secret, register the destination under a different URL and disable the old endpoint.

A registered endpoint is a target for the workspace, not for one review. Every event you subscribe it to is delivered to it, and disabling it stops future deliveries without touching the evidence RateLoop keeps.

Test and recover

Workspace settings can queue a signed synthetic event to an existing active endpoint. The event is clearly marked as synthetic, uses that endpoint's real signing secret, and passes through the same address-pinned delivery worker as review events. It does not create or change review state.

Delivery activity shows only the event type, delivery ID, state, attempt count, HTTP status, and update time. It never shows endpoint paths, payloads, response bodies, signing details, reviewer content, or identities.

A manual retry is available only after a delivery has reached its terminal failed state. It resends the immutable stored body to the same active endpoint with the same delivery ID. Duplicate receipt is possible, so receivers must deduplicate by rateloop-delivery-id.

What a workspace can send

Pick the events you want at registration. An event you did not subscribe to is still recorded in RateLoop; it is simply not delivered to you.

ai.rateloop.review.decision_neededA review is open and its named reviewers can now answer.
ai.rateloop.review.verdictA sign-off was recorded. The written reason stays in RateLoop.
ai.rateloop.review.completedThe review reached its result and closed.
ai.rateloop.review.failedThe review ended without a result for some other reason.
ai.rateloop.review.expiredNobody answered in time, or every assignment lapsed.
ai.rateloop.review.inconclusiveThe panel answered but did not reach the agreement the template requires.
ai.rateloop.review.cancelledSomebody with the rights to do so stopped the review.
ai.rateloop.packet.anchoredThe evidence packet for a finished review was written and fixed.
ai.rateloop.gate.blockedA review requirement refused an action because no valid review backed it.

The envelope

The body is one CloudEvent in JSON. It carries the digest of what happened — the workspace, the subject, the lifecycle state, the reason codes — and never the reviewers' written reasons, their identities, or the contents of the evidence packet. Those stay behind an authenticated read, where the reader's own session decides what they may see.

content-typeapplication/cloudevents+json for every event in the table above.
rateloop-signaturev1= followed by the hex HMAC-SHA256.
rateloop-timestampUnix seconds. Signed together with the body.
rateloop-delivery-idStable per delivery, unchanged across every retry. Deduplicate on this.
rateloop-event-idStable per event, shared by every endpoint subscribed to it.

Verify before you act

The signature is an HMAC-SHA256 over the timestamp, a period, and the exact raw body, keyed with the secret you were given at registration. Compute it over the bytes you received, not over a re-serialized object, and compare it in constant time. Reject a delivery whose timestamp is outside the window you are willing to accept, and treat a repeated rateloop-delivery-id as the retry it is.

const expected = "v1=" + createHmac("sha256", secret)
  .update(`${headers["rateloop-timestamp"]}.${rawBody}`)
  .digest("hex");

The n8n helper package is not publicly installable yet. Use the complete receiver on the Integration recipes page in your own service.

The n8n node and its verifier helper are not publicly installable yet. Use the complete raw-body signature receiver in the integration recipe until a compatible package is published.

Retries, and when RateLoop gives up

Answer within ten seconds with any 2xx status. Anything else counts as a failure. RateLoop makes at most eight attempts in total, waiting 30 seconds after the first failure and then doubling to a ceiling of one hour. After the eighth failed attempt, the delivery enters the dead-letter state and automatic retries stop. The endpoint stays active for later events. A redirect is not followed — it is a failure, so that a moved endpoint is a thing you notice rather than a thing that quietly happens.

Review events are recorded first. A maintenance worker then projects them into deliveries and evaluates the subscriptions active at projection time, so a new event can take several minutes to reach the delivery queue. Projection is idempotent and does not change the recorded event. A failed delivery changes nothing inside RateLoop: the review, the verdict, and the evidence are unaffected by whether your service was reachable.

What a URL has to be

The endpoint must be HTTPS, carry no username, password, or fragment, and, in production, use the standard HTTPS port. It must not resolve to a private, loopback, or otherwise non-routable address.

Validating the hostname once would not be enough on its own, because the answer can change between the check and the request. RateLoop resolves the hostname on every attempt, refuses the delivery if any returned address is not globally routable, and then opens the connection to that exact address while keeping your hostname for TLS and the Host header. A rebinding cannot steer a delivery at something on our side of a network boundary.

If you want to be told, not to receive

A person watching a channel does not need any of this. RateLoop posts a card into Microsoft Teams or Slack for the two events that address a human, with one button that opens the review. See Teams & Slack for the setup. Those channel URLs carry no signature a receiver could check, which is exactly why a system that has to trust what it received uses a webhook instead.

Read the Evidence reference for what a packet contains and how to check it.

Webhooks | RateLoop