HTTP reference

Webhook rebuild & CDN purge

Use outbound webhooks when headless content changes should rebuild a static host or purge a CDN. Prefer a thin receiver that verifies HMAC, then calls the platform API — do not expose unsigned deploy hooks on the public internet.

Event picks

GoalListen for
Content changed (draft saved)item.created / item.updated
Only when liveitem.published (manual or scheduled)
Collection schema changecollection.updated
Smoke testping from Project settings

Filter in Make/n8n/your code on JSON type.

Pattern A — HMAC receiver → deploy hook

  1. Externa → your HTTPS URL (secret set in Project settings).
  2. Receiver verifies X-Externa-Signature (see Webhooks).
  3. If type matches, POST the platform Deploy Hook / Build Hook (no body required for Vercel/Netlify hooks).

Vercel Deploy Hook

# After HMAC OK:
curl -fsS -X POST "$VERCEL_DEPLOY_HOOK_URL"

Create the hook in Vercel → Project → Settings → Git → Deploy Hooks.

Netlify Build Hook

curl -fsS -X POST "$NETLIFY_BUILD_HOOK_URL"

Site settings → Build & deploy → Build hooks.

Do not paste the hook URL into Externa directly (prod)

Deploy hooks usually ignore Externa’s HMAC. Anyone with the URL can trigger builds. Staging-only exception is OK; production should verify signature first.

Minimal Node receiver sketch

import crypto from 'node:crypto'
import http from 'node:http'

const secret = process.env.EXTERNA_WEBHOOK_SECRET
const deployHook = process.env.VERCEL_DEPLOY_HOOK_URL

http
  .createServer(async (req, res) => {
    const chunks = []
    for await (const c of req) chunks.push(c)
    const raw = Buffer.concat(chunks)
    const expected =
      'sha256=' + crypto.createHmac('sha256', secret).update(raw).digest('hex')
    if (req.headers['x-externa-signature'] !== expected) {
      res.writeHead(401)
      return res.end()
    }
    const body = JSON.parse(raw.toString('utf8'))
    if (['item.published', 'item.updated'].includes(body.type)) {
      await fetch(deployHook, { method: 'POST' })
    }
    res.writeHead(204)
    res.end()
  })
  .listen(8787)

Pattern B — Cloudflare cache purge

After publish (or rebuild), purge paths or tags via Cloudflare API (token with Cache Purge).

curl -fsS -X POST \
  "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/purge_cache" \
  -H "Authorization: Bearer ${CF_API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"files":["https://www.example.com/","https://www.example.com/blog/"]}'

Purge everything (use sparingly):

curl -fsS -X POST \
  "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/purge_cache" \
  -H "Authorization: Bearer ${CF_API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"purge_everything":true}'

Wire this in the same receiver after HMAC + type filter (often only item.published). Map collection / item slug from the webhook payload to URLs your frontend uses.

Make / n8n shortcut

  1. Webhook trigger URL → Externa Project settings + secret.
  2. Filter: type equals item.published (or list).
  3. HTTP Request → Deploy Hook URL or Cloudflare purge endpoint with Bearer token.

Same as Webhooks recipes, with explicit purge step.

Previous
Outbound webhooks