Webhook setup
Get a signed POST to your server every time data changes. End-to-end in roughly fifteen minutes.
1. Pick the triggers you need
Participants — created or modified Registrations — a participant materializes after order completion Speaker submissions — drafts, submissions, transitions Block requests — group room blocks created or allocated Hotel reservations — individual bookings, status changes Sourcing and contracts — briefs, RFPs, approvals, contracts, and milestones Continuing education — credit earned events Exhibitors and leads — company profile changes, lead captures, and prospect invite conversions Booths — booths sold at order fulfillment or released back to the market by cancellation Appointments — peer and booth appointment activity
A single webhook can subscribe to multiple triggers — deliveries share one secret and one endpoint. Pick the minimum set for your integration; you can edit later.
2. Stand up an endpoint that responds 2xx fast
Your endpoint must:
Accept POSTwithContent-Type: application/json.Return a 2xx status within 10 seconds. Anything else (non-2xx, timeout, connection error) counts as a failure and triggers a retry. - Be reachable from the public internet for production webhooks. In dev, localhost or a tunneled local server (ngrok) is fine.
The recommended pattern: acknowledge the delivery (HTTP 200) the instant the signature verifies, then enqueue the payload for async processing on your side. Long-running work inside the request handler will hit the 10s timeout.
3. Create the webhook in Jade
From the event's organizer area:
Open the Developers sidebar entry under Event Config. Switch to the Web Hooks tab. Click New webhook. - Fill in a description (e.g. "Salesforce attendee sync"), the target URL, and check the triggers you need.
Click Create webhook.
4. Copy the signing secret immediately
whsec_ followed by a long random string. Jade stores it AES-encrypted at rest and decrypts at delivery time to sign payloads; it is shown to humans exactly once.
5. Verify the signature on every delivery
X-Jade-Signature header in the form sha256=<hex>. Compute the HMAC-SHA256 of the raw request body (exact bytes, no re-stringification) with your signing secret and constant-time- compare:
import { createHmac, timingSafeEqual } from 'crypto';
function verify(rawBody, header, secret) {
const expected = 'sha256=' + createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
return expected.length === header.length &&
timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}6. Handle the payload
Payloads are small — they carry intent, not state:
{
"trigger": "participant",
"action": "updated",
"clientCode": "acme",
"eventCode": "acme-2026",
"participantId": "65ec1234abcd5678ef901234",
"deliveredAt": "2026-05-20T15:30:00.000Z"
}/v1 using your bearer token. That way a webhook arriving late still reads the latest data, and PII gating from your token's account flag applies the same way it does on normal reads.
7. Make your handler idempotent
{ trigger, eventCode, <resource-id>, action } or by tracking the X-Jade-Webhook-Id + deliveredAt pair.
8. Watch the delivery status
9. Rotate the secret periodically
There's no built-in rotation flow today — to rotate, create a new webhook with the same URL + triggers, deploy your endpoint to accept either secret, then delete the old webhook. Subsequent deliveries use the new secret only.
Reference
- Webhooks reference — full payload contract, headers, signature algorithm, retry schedule.
- REST API setup — the read/write side you'll re-fetch resources through.
- Errors — what failed deliveries look like on your side.