Your own server
A complete receiver: webhooks for speed, a poll every 5 minutes as backup, and status updates back. Node.js 20+, no extra packages beyond Express.
import crypto from 'node:crypto';
import express from 'express';
const BASE = 'https://zqawbbylldymdfzineqq.supabase.co/functions/v1/pro-api/v1/leads';
const KEY = process.env.LEADS_KEY, SECRET = process.env.WEBHOOK_SECRET;
const seenEvents = new Set(); // use your database in production
const leads = new Map(); // id -> lead, use your database in production
let since = null;
function verify(raw, header) {
const p = Object.fromEntries(String(header || '').split(',').map((x) => x.split('=', 2)));
if (!p.t || !p.v1 || Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
const expected = crypto.createHmac('sha256', SECRET).update(`${p.t}.${raw}`).digest('hex');
return p.v1.length === expected.length && crypto.timingSafeEqual(Buffer.from(p.v1), Buffer.from(expected));
}
function upsert(lead) {
const have = leads.get(lead.id);
if (have && have.updated_at >= lead.updated_at) return;
leads.set(lead.id, lead);
// create or update the record in your system here
}
export async function setStatus(id, status) {
const r = await fetch(`${BASE}/${id}`, { method: 'PATCH', headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status }) });
if (r.status === 409) return null; // not allowed from the current status (or lead not accepted)
if (!r.ok) throw new Error(`status ${r.status}`);
return r.json();
}
async function poll() {
let cursor = null, s = since || '2000-01-01T00:00:00Z';
do {
const url = new URL(BASE);
if (cursor) url.searchParams.set('cursor', cursor); else url.searchParams.set('since', s);
const r = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
if (!r.ok) return;
const body = await r.json();
body.leads.forEach(upsert);
cursor = body.has_more ? body.next_cursor : null;
if (body.next_since) s = body.next_since;
} while (cursor);
since = s;
}
const app = express();
app.post('/leads-hook', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body.toString('utf8');
if (!verify(raw, req.get('X-Signature'))) return res.sendStatus(401);
res.sendStatus(200);
const ev = JSON.parse(raw);
if (seenEvents.has(ev.id)) return;
seenEvents.add(ev.id);
if (ev.lead) upsert(ev.lead);
});
app.listen(3000);
poll(); setInterval(poll, 5 * 60 * 1000);Point our Settings webhook at https://your-server/leads-hook. Call setStatus(id, 'hired') when your system books the job.