Webhooks
Register an HTTPS URL and FiniteBase will POST it a signed JSON payload whenever a subscribed event happens in your project — the push counterpart to the pull-based sync feed. Webhook management needs a server key.
Register a webhook
curl -X POST "https://base.finiteskills.com/v1/webhooks" -H "X-Appwrite-Project: <YOUR_PROJECT_ID>" \
-H "X-Appwrite-Key: <API_KEY>" -H "Content-Type: application/json" \
-d '{"name":"order-sync","url":"https://example.com/hooks/fb",
"events":["documentCreated","documentUpdated"]}'
# -> { "$id":"...", "signingSecret":"whsec_...", ... }
The signingSecret is returned once, on creation — store it now; it is never
shown again. Manage webhooks with GET /webhooks, GET /webhooks/{id} and
DELETE /webhooks/{id}.
Subscribable events
documentCreated documentUpdated documentDeleted
fileCreated fileDeleted
sessionCreated sessionDeleted
* // subscribe to every event
Delivery format
Each delivery is a POST whose body is the JSON event payload, with these headers:
X-FiniteBase-Event: documentCreated # the event name
X-FiniteBase-Webhook-Id: <your webhook id>
X-FiniteBase-Signature: <hex HMAC-SHA256> # see below
Inspect recent attempts (status code, ok, error) with
GET /webhooks/{id}/deliveries.
Verifying the signature
X-FiniteBase-Signature is the hex HMAC-SHA256 of the raw request body keyed by your
signing secret. Compute the same HMAC over the bytes you receive and compare in constant time — reject the
request if it doesn't match:
const crypto = require('crypto');
// Capture the RAW body: express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } })
app.post('/hooks/fb', (req, res) => {
const expected = crypto
.createHmac('sha256', process.env.FB_WEBHOOK_SECRET) // whsec_...
.update(req.rawBody)
.digest('hex');
const sig = req.get('X-FiniteBase-Signature') || '';
const ok = expected.length === sig.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
if (!ok) return res.status(401).end();
// trusted: handle req.get('X-FiniteBase-Event') + JSON.parse(req.rawBody)
res.status(200).end();
});
Respond 2xx to acknowledge. Non-2xx responses (and timeouts) are recorded on the delivery so you
can diagnose failures.