Integrations
Webhooks
Send a signed message to another service every time a record is created, updated, or deleted. Use it for Slack alerts, CRMs, search indexes, and your own servers.
Create a webhook
- Open your Project and select Webhooks.
- Select Create webhook.
- In General, enter a name and the endpoint address. It must start with http:// or https://.
- Choose one table, or all tables.
- Choose the trigger events: create, update, delete, or any mix. At least one is required.
- In Headers, add any extra headers the receiver needs, as a JSON object.
- In Security & retries, set a signing secret, the timeout (10 seconds by default), and the number of retries (0 by default).
- Save, then select Send a test delivery to check it end to end.
Manage webhooks
The top of the page counts your endpoints, how many are active, total deliveries, and failures.
| Action | What it does |
|---|---|
View deliveries | Every attempt with its status code, request body, response, and duration |
Send a test delivery | Sends a sample event now, without changing any data |
Pause / Resume | Stops or restarts deliveries without deleting the setup |
Duplicate | Copies the webhook, for example to point a second service at the same events |
Delete | Removes the webhook after confirmation |
What the receiver gets
Each delivery is a POST with a JSON body and these headers. The header names are technical identifiers and stay as shown.
| Header | Value |
|---|---|
X-Orchbase-Event | The event: create, update, or delete |
X-Orchbase-Webhook-Id | Which webhook sent it |
X-Orchbase-Delivery-Attempt | 1 for the first try, then 2, 3 and so on for retries |
X-Orchbase-Timestamp | When it was sent, in Unix seconds |
X-Orchbase-Signature | sha256= followed by the signature, when a signing secret is set |
Check the signature
The signature is an HMAC-SHA256 of the timestamp, a dot, and the raw body, using your signing secret. Check it before trusting the message, and reject old timestamps so a copied message can't be replayed.
import { createHmac, timingSafeEqual } from "node:crypto";
export async function handle(req) {
const body = await req.text();
const ts = req.headers.get("x-orchbase-timestamp") ?? "";
const sig = req.headers.get("x-orchbase-signature") ?? "";
const expected = "sha256=" + createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(ts + "." + body)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
const valid = sig.length === expected.length &&
timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!fresh || !valid) return new Response("invalid signature", { status: 401 });
const event = JSON.parse(body);
// ... handle the event, then answer quickly
return new Response("ok");
}Receiving webhooks from other services
To accept messages from Stripe, GitHub, or any other service, create an Edge Function with an HTTP endpoint trigger. Check that service's signature first, then save or process the data.
Good practice
- Always set a signing secret, and keep it in the receiver's environment variables.
- Answer within the timeout and move slow work elsewhere, so deliveries don't fail and retry.
- A retry can send the same event twice. Use the record id and event to ignore duplicates.
- Use https:// endpoints in production.
- Watch the failure count. Pause a webhook whose receiver is down instead of letting it fail.
Fix it yourself. The link below opens this file in GitHub's editor and forks the repository for you if you need one, and your change becomes a pull request without leaving the browser.