Skip to content

Webhooks

Webhooks push near-real-time events to an HTTPS endpoint you control. Each delivery is a JSON document signed with a shared secret so you can verify it came from Aware.

Every delivery shares the same envelope: id, type, timestamp, and payload. Branch on type to handle the event; payload holds the domain object(s) for that event. Check-in deliveries are documented as WebhookDelivery; subscribe using the event types in WebhookEventType.

Public API webhooks are managed in the Aware dashboard under Settings → APIs & Integrations → Webhooks.

  1. Open your company in the Aware app and go to Settings → APIs & Integrations → Webhooks.
  2. Click Add webhook.
  3. Enter your endpoint URL.
  1. Select one or more events (see below).
  2. Leave Enabled checked and click Create.
  3. Copy the signing secret from the confirmation screen. It is shown once — store it in your secret manager. You cannot retrieve it later.

You can register one webhook per company. Use Update in the list to change the URL, events, or enabled flag.

That webhook receives events from all sites under the company — there is no per-site filter. If you only care about certain sites, filter on payload.siteId in your handler.

When creating or updating a webhook, choose which events to receive. The same type value appears on each delivery:

Event typeMeaning
CHECKIN_ENTEREDPerson is on site.
CHECKIN_EXITEDPerson has checked out.
CHECKIN_PENDINGCheck-in is recorded but not yet admitted (clearance pending).
CHECKIN_STOPPEDCheck-in was hard-stopped — compliance or clearance failed.

For check-in events, payload is a CheckinResponse — the same object returned by the check-in REST endpoints. Status meanings match the Check-ins guide.

Aware POSTs to your URL with:

HeaderPurpose
Content-Typeapplication/json
X-Aware-Delivery-IdUUID for this delivery (same as the id field in the body).
X-Aware-Signaturet=<unix-seconds>,v1=<hex> — HMAC-SHA256 of the raw body.

Example body (trimmed). Full schema: WebhookDelivery.

{
"id": "a502c3e3-4c33-4f38-9297-6a05bb3b07b4",
"type": "CHECKIN_ENTERED",
"timestamp": "2026-06-26T02:49:22.656685Z",
"payload": {
"id": "4faa23fa-3f0c-4507-b60a-e53eaff1696d",
"siteId": 34009,
"timestamp": "2026-06-26T02:49:22.391Z",
"entry": {
"source": "MANUAL",
"timestamp": "2026-06-26T02:49:00.000Z"
},
"exit": {},
"status": "IN",
"personId": 12345
}
}
  • id — delivery id (also sent as X-Aware-Delivery-Id).
  • type — event name (CHECKIN_ENTERED, CHECKIN_EXITED, …); see WebhookEventType.
  • timestamp — when Aware emitted the event (UTC).
  • payload — event body; shape depends on type. Check-in events use CheckinResponse.

Return any 2xx response quickly. Your endpoint must answer the POST directly — redirects are not followed. Non-2xx responses are logged; duplicate deliveries for the same underlying event may be suppressed for 24 hours.

Read the raw request body (before JSON parsing). Parse X-Aware-Signature:

t=<unix-seconds>,v1=<hex-digest>

Compute:

HMAC_SHA256(secret, "<t>." + rawBody)

Compare the digest to v1 with a constant-time comparison.

import { createHmac, timingSafeEqual } from 'node:crypto'
function verifyAwareWebhook(secret, rawBody, signatureHeader) {
const parts = Object.fromEntries(
signatureHeader.split(',').map((part) => {
const [key, ...rest] = part.trim().split('=')
return [key, rest.join('=')]
}),
)
const timestamp = parts.t
const expected = parts.v1
if (!timestamp || !expected) return false
const signed = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
const a = Buffer.from(signed, 'hex')
const b = Buffer.from(expected, 'hex')
return a.length === b.length && timingSafeEqual(a, b)
}

Reject requests that fail verification before acting on the payload.