SyncNexaSyncNexa
Docs
v1.0 (Latest)

Webhooks & Events

v1.0

Subscribe to real-time events, configure webhook endpoints, and handle verification and consent notifications securely with HMAC verification.

Last updated: August 2026

Webhooks allow your application to receive asynchronous, real-time push notifications whenever an important event occurs in SyncNexa, such as a student completing verification, granting or revoking consent, or an application status update.

Why Webhooks?

Instead of polling the SyncNexa API repeatedly to check if a student has completed their verification session, webhooks notify your server the instant the cryptographic zero-knowledge proof is confirmed.

Supported Event Types

Event NameDescriptionTrigger Condition
verification.completedVerification successfully confirmedStudent approved verification and zk-proof validated
verification.failedVerification rejected or timed outProof validation failed or session expired without approval
consent.approvedStudent approved data sharingStudent granted application permission to access claims
consent.deniedStudent declined data sharingStudent explicitly rejected application permission request
student.revokedStudent credential revokedIssuing university marked the student as graduated or withdrawn
app.updatedApplication configuration updatedApp metadata, redirect URIs, or credentials changed

Registering a Webhook Endpoint

You can configure webhooks either during Application Creation (Step 2) or via the Webhooks dashboard in the Business Portal:

  • Navigate to Webhooks in the Business Portal sidebar.
  • Click Add Endpoint.
  • Enter your HTTPS server endpoint URL (e.g., https://api.yourdomain.com/webhooks/syncnexa).
  • Select the events you want to subscribe to using the interactive event checkboxes.
  • Save the endpoint. A unique Signing Secret (whsec_...) will be generated for your endpoint.
HTTPS Endpoint Required
All production webhook URLs must use valid HTTPS with a trusted TLS certificate. Self-signed certificates are only permitted in local development proxies.

Payload Structure

Every webhook notification is delivered as a POST request with a JSON payload:

sample-webhook-payload.jsonjson
1{
2 "id": "evt_1a2b3c4d5e6f7g8h",
3 "event": "verification.completed",
4 "createdAt": "2026-08-20T12:00:00.000Z",
5 "appId": "app_8a7b6c5d4e3f",
6 "environment": "live",
7 "data": {
8 "sessionId": "sess_9f8e7d6c5b4a",
9 "status": "completed",
10 "verified": true,
11 "university": {
12 "name": "Imperial College London",
13 "domain": "imperial.ac.uk",
14 "country": "GB"
15 },
16 "proof": {
17 "type": "Groth16",
18 "proofHash": "0x4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b",
19 "expiresAt": "2027-06-30T23:59:59Z"
20 }
21 }
22}

Signature Verification (HMAC-SHA256)

SyncNexa signs every webhook delivery using your endpoint's signing secret (whsec_...). The signature is included in the X-SyncNexa-Signature HTTP header in the format t=timestamp,v1=signature_hex:

typescript
1import crypto from 'crypto';
2import express from 'express';
3 
4const app = express();
5 
6app.post(
7 '/webhooks/syncnexa',
8 express.raw({ type: 'application/json' }),
9 (req, res) => {
10 const signatureHeader = req.headers['x-syncnexa-signature'] as string;
11 const signingSecret = process.env.SYNCNEXA_WEBHOOK_SECRET!; // whsec_...
12 
13 if (!signatureHeader) {
14 return res.status(400).send('Missing signature header');
15 }
16 
17 // 1. Extract timestamp and signature
18 const parts = signatureHeader.split(',');
19 const timestamp = parts.find((p) => p.startsWith('t='))?.split('=')[1];
20 const expectedSig = parts.find((p) => p.startsWith('v1='))?.split('=')[1];
21 
22 // 2. Compute expected HMAC
23 const signedPayload = `${timestamp}.${req.body.toString('utf8')}`;
24 const computedSig = crypto
25 .createHmac('sha256', signingSecret)
26 .update(signedPayload)
27 .digest('hex');
28 
29 // 3. Constant-time comparison
30 const isValid = crypto.timingSafeEqual(
31 Buffer.from(computedSig),
32 Buffer.from(expectedSig || '')
33 );
34 
35 if (!isValid) {
36 return res.status(401).send('Invalid webhook signature');
37 }
38 
39 const payload = JSON.parse(req.body.toString('utf8'));
40 console.log('Verified Webhook Event:', payload.event);
41 
42 // Return 200 OK immediately
43 res.status(200).json({ received: true });
44 }
45);

Delivery & Retry Policy

SyncNexa expects your server to respond with an HTTP 2xx status code within 5 seconds. If your server returns an error code or times out, the webhook dispatcher will automatically retry delivery using exponential backoff:

  • Immediate Attempt: At time 0
  • Retry 1: 30 seconds later
  • Retry 2: 5 minutes later
  • Retry 3: 30 minutes later
  • Retry 4: 2 hours later
  • Final Retry: 24 hours later
Was this page helpful?