POST requests to one endpoint. A self-hosted app
receives them at the endpoint URL it declares; a hosted app receives them inside Reintersect’s
runtime. The SDK verifies and routes every request for you. This page explains what it checks, so you
can reason about failures and implement the protocol yourself if you need to.
Two lanes
The full list of interactive delivery types and their payloads is in the
delivery protocol.
Signatures
Every request follows the Standard Webhooks specification and carries these headers:
Your app’s signing secret is in Settings → Developer → Apps → your app, under the app’s
credentials. Rotating it starts a 24 hour grace period in which Reintersect signs with both the old
and the new secret, so you can deploy the new value without dropping requests. Hosted apps are
redeployed with the new secret automatically.
Verification in the SDK
The SDK verifies every request before your code runs, with WebCrypto, on every runtime it supports. It rejects a request when:- the signature doesn’t match any signature in
webhook-signature, or webhook-timestampis more than 5 minutes away from the current time.
401 response and never reach your handlers. The SDK also remembers each
webhook-id for 10 minutes on the same instance. A repeated lifecycle delivery is answered with
{ "duplicate": true } without running your handler again, and a repeated interactive delivery,
such as a replayed button click, is refused with a 400 (replayed).
Where the secret comes from:
Verifying without the SDK
Any Standard Webhooks library works. With thestandardwebhooks package:
verify throws when the signature or timestamp is invalid. Verify the raw body before you parse it;
re-serialized JSON doesn’t match the signature.
Interactive deliveries
When a member clicks a button, Reintersect sends ablock.action delivery and waits up to 5 seconds.
Your app answers in one of two ways.
Answer within 5 seconds
Respond200 with the result: the next state, a notice, field errors and so on. With the SDK, that is
whatever your action handler returns; the SDK merges the state, renders the block and sends both back
in the same response. The member sees the new block as soon as the response arrives.
If your app doesn’t answer in time, answers with an error, or returns a result that fails
validation, Reintersect keeps the last good version of the block and shows the member an inline
error. Interactive deliveries are never retried, because the member may already have moved on or
clicked again.
Defer and push later
When the work takes longer, such as a deployment, acknowledge first and push the result when it is ready. With the SDK, return a quick result and continue inwaitUntil:
reintersect is authorized by the delivery’s interaction token, so the push
works without extra credentials.
Without the SDK, respond 202 Accepted with an empty body, then push the result within 15 minutes.
The block.action payload includes an interactionToken. Send it as a bearer token to
update or replace that block’s
state:
blocks:write scope.
Commands and message actions
Slash commands and message actions defer the same way, except the202 body says who sees your app thinking: { "visibility": "private" } for only the member who ran
it, or { "visibility": "public" } for everyone there. Then send the answer within 15 minutes to
POST /v0/invocations/respond with the delivery’s
interactionToken in the body and your install token as the credential. With the SDK, return
defer(task, { visibility }) from the handler, or defer() and call
reintersect.invocations.respond when your work finishes. A run takes one answer; the token is refused after that or after 15 minutes.
Idempotency
Authorization
Before it sends an action, Reintersect checks that:- the member can see and write in the circle;
- the block’s audience includes them;
- the block isn’t final;
- the action is rendered in the block’s current revision;
- the install is active.
actor in the signed body.
Your app still decides what that member may do in your own system. Use actor.memberId to look up
the matching account on your side before you deploy, delete or pay for anything. audience hides
components from people; it doesn’t stop a crafted request, and your server is the last check.
Network rules
- Self-hosted endpoints must use HTTPS on the default port. Reintersect doesn’t deliver to private, loopback or link-local addresses.
- Reintersect doesn’t follow redirects. An endpoint that answers
3xxfails the delivery. - Reintersect never sends your app its cookies or a member’s session. The only credentials in a
request are the signature headers, a short-lived install token in the body (
installToken, valid for one hour) and, for actions, an interaction token for that block. - Hosted apps can only call the hosts they list in
egress. Reintersect’s gateway sets the install token on their calls to the Reintersect API. See Reintersect-hosted apps.
Reintersect-signed tokens
Webhook deliveries are always signed with Standard Webhooks. Separately, MCP servers can opt in to receive a short-lived JWT that Reintersect signs for each tool call, so they can identify the member without running their own OAuth. See MCP authentication. Context that Reintersect adds to MCP calls under_meta is a convenience hint and doesn’t prove identity, so
authorize with the verified token and never with _meta.