Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.simplefunctions.dev/llms.txt

Use this file to discover all available pages before exploring further.

This page covers the receiver side: how to write code that accepts SF webhook deliveries, verifies them, and handles retries safely.

Headers

Every delivery includes:
X-SF-Signature: t=<unix_ts>,v1=<hex_hmac>
X-SF-Endpoint-Id: we_...
X-SF-Delivery-Id: del_...
X-SF-Event: alert.fired
Content-Type: application/json

Receiver implementations

import express from 'express'
import crypto from 'crypto'

const app = express()
const SECRET = process.env.SF_WEBHOOK_SECRET!
const seen = new Set<string>()  // replace with Redis in prod

app.post('/sf-hook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.header('x-sf-signature') ?? ''
  const deliveryId = req.header('x-sf-delivery-id') ?? ''
  if (!verify(SECRET, sig, req.body)) return res.status(401).send('bad sig')
  if (seen.has(deliveryId)) return res.status(200).send('ok (dedupe)')
  seen.add(deliveryId)

  const event = JSON.parse(req.body.toString('utf8'))
  console.log(event.type, event.data)
  res.status(200).send('ok')
})

function verify(secret: string, sigHeader: string, body: Buffer): boolean {
  const [tPart, v1Part] = sigHeader.split(',')
  const t = tPart?.split('=')[1]
  const v1 = v1Part?.split('=')[1]
  if (!t || !v1) return false
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${body.toString()}`).digest('hex')
  if (Math.abs(Date.now()/1000 - Number(t)) > 300) return false
  return crypto.timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(expected, 'hex'))
}

Replay

If your endpoint went down, SF persists failed deliveries in alert_deliveries. Replay:
sf deliveries --json --status failed
# pick a delivery id
curl -X POST -H "Authorization: Bearer $SF_API_KEY" \
  https://simplefunctions.dev/api/alert-deliveries/<delivery-id>/retry

Idempotency

Always idempotency-key on X-SF-Delivery-Id. SF retries on 5xx and timeouts up to 5 attempts; same delivery id is reused.

Auto-pause

Endpoints that 5xx more than 50% across a 24h window get auto-paused. Re-enable:
sf webhooks resume <endpoint-id>

See also

Webhook events

Payload schemas per event type.

Watch + alerts API

Endpoints for managing watched objects, rules, endpoints.