Synchronizing
Architectural Primitives

Webhooks and callbacks

Webhooks deliver verification status changes to your endpoint in near real time. Register a callback URL once, and Sentinel POSTs a small JSON payload whenever a customer's status changes. This is the recommended way to receive outcomes.

Register a callback URL

From your backend, register where webhooks should be delivered and a secret used to verify them.

http
POST https://api.sentinel.example.com/clients/setWebhook/clientAuth
FieldTypeDescription
clientUuidrequiredstringYour client identifier.
clientSecretrequiredstringYour client secret. Server-side only.
callbackUrlrequiredstringWhere Sentinel POSTs webhooks. Must use HTTPS.
callbackPassphraserequiredstringA shared secret, minimum 6 characters, used to verify incoming webhooks.
request
{
  "clientUuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "clientSecret": "xxxxxxxxxxxxxxxx",
  "callbackUrl": "https://your-domain.example/webhooks/sentinel",
  "callbackPassphrase": "your-shared-secret"
}
response
{
  "message": "Success"
}

The payload

Sentinel sends a POST with a JSON body to your callback URL.

FieldTypeDescription
idnumberInternal customer id.
uuidstringCustomer UUID. Safe to use as your external key.
emailstringEmail captured during the journey.
phonestringPhone number captured during the journey.
newStatusnumberThe customer status code. See the table below.
updatedAtstring (ISO)Timestamp of the status change.
eventstringThe event type. See events below.
expiryWarningForstring[]Documents nearing expiry. Populated only on expiry_warning. Values are snake_case here (passport, emirates_id, egypt_national_id), unlike the camelCase document values used elsewhere.
passphrasestringThe callbackPassphrase you registered. Use it to verify the request, as described below.
payload
{
  "id": 1024,
  "uuid": "3f9c1e8a-1d77-4a2b-9f2e-7c6b5a4d3e21",
  "email": "jane.doe@example.com",
  "phone": "+971501234567",
  "newStatus": 6,
  "updatedAt": "2026-05-20T10:15:30.000Z",
  "event": "customer_status_changed",
  "expiryWarningFor": [],
  "passphrase": "your-shared-secret"
}

Events

EventFires when
customer_status_changedThe default event. Sent whenever a customer status changes.
customer_createdThe customer finishes the flow and a customer record is created. Opt in to receive it.
expiry_warningA document is approaching expiry. Carries expiryWarningFor.

The default subscription fires on status change. If you also want a signal at the moment a customer record is created, when the customer finishes the flow, ask to enable the customer_created event.

Verify every webhook

Before trusting a payload, confirm it came from Sentinel by comparing the passphrase in the body to the callbackPassphrase you registered. Reject the request if they do not match.

javascript
app.post('/webhooks/sentinel', (req, res) => {
  if (req.body.passphrase !== process.env.SENTINEL_CALLBACK_PASSPHRASE) {
    return res.sendStatus(401)
  }

  // Trusted. Act on req.body.newStatus and req.body.uuid.
  res.sendStatus(200)
})
Handle the secret with care
Serve your callback over HTTPS so the payload is never sent in the clear. Do not log the passphrase, keep it in server-side configuration, and rotate it periodically. Use the uuid as your key, and treat id as internal.

Status codes

newStatus is a numeric code. The full set is below. Codes marked reserved exist but are not currently emitted, so handle any unrecognized value defensively.

CodeStatusMeaning
1InactivereservedNot currently emitted.
2DraftRe-verification required. Triggered by document expiry or set from the dashboard, with a reason shown to the customer.
3More datareservedNot currently emitted.
4ExpiredreservedNot currently emitted.
5PendingSubmitted; verifying and screening.
6AcceptedPassed all checks.
7RejectedDid not pass.
8EnhancedreservedNot currently emitted.
9ConflictHeld for review; submitted details do not reconcile.
10DuplicateHeld for review; matches an existing record.

Accepted and Rejected are outcomes, but not necessarily permanent: an operator can change a status from the dashboard. Conflict and Duplicate are held for review and resolve to Accepted or Rejected. See Core concepts for the lifecycle.

Delivery and retries

Delivery is retried up to 3 times with exponential backoff. If every attempt fails, the webhook is dropped, so pair webhooks with result retrieval for critical workflows. Respond with a 2xx status quickly, and do any heavy processing asynchronously.

Next
Read outcomes on demand with Retrieving results, or review them in the dashboard.