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
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

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:

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:

Node.js (Express)
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.