📘 Public beta · Endpoints are stable; OpenAPI specs and SDKs ship monthly. See changelog →
Products
Identity Platform
Webhooks

Identity Platform · Webhooks

For the verification semantics (signing, retry, idempotency) see Webhooks (global) →. This page lists the events specific to Identity Platform.

Event catalog

EventWhen it firesPayload data shape
verification.createdAny new verification persisted (KTP, face, Dukcapil, NIK format, step-up){ verificationId, customerId, method, status, score }
customer.kyc_updatedKYC tier changed (up or down){ customerId, kycLevel, kycLastVerifiedAt, kycExpiresAt }
review.overriddenAnalyst overrode a verification verdict from the dashboard{ verificationId, customerId, actorUserId, fromStatus, toStatus, reason }
webhook.testYou clicked "Send test" or hit POST /webhooks/{id}/test{ source: "test" }

Signature

Identity Platform currently signs with the X-Identity-Signature header (product-prefixed, legacy). It will migrate to X-Quantum-Signature in the next minor release; the old header will continue working for at least 12 months.

X-Identity-Signature: sha256=8b2c4d7e...
X-Identity-Delivery:  whd_01HXY...
X-Identity-Event:     verification.created
X-Sibling-Service:    identity

The X-Sibling-Service header is set when the delivery is triggered by another Quantum Elixir product (e.g. Orchestration). Lets your receiver distinguish "real customer event" from "orchestrated event".

Example payloads

verification.created

{
  "id": "evt_01HXY...",
  "event": "verification.created",
  "occurredAt": "2026-05-24T08:15:12.481Z",
  "orgId": "org_01HXY...",
  "data": {
    "verificationId": "ver_01HXY...",
    "customerId": "cus_01HXY...",
    "method": "ktp_capture",
    "status": "verified",
    "score": 87
  }
}

customer.kyc_updated

{
  "id": "evt_01HXZ...",
  "event": "customer.kyc_updated",
  "occurredAt": "2026-05-24T08:17:58.491Z",
  "orgId": "org_01HXY...",
  "data": {
    "customerId": "cus_01HXY...",
    "kycLevel": "premium",
    "kycLastVerifiedAt": "2026-05-24T08:17:58.491Z",
    "kycExpiresAt": "2027-05-24T08:17:58.491Z"
  }
}

review.overridden

{
  "id": "evt_01HXA...",
  "event": "review.overridden",
  "occurredAt": "2026-05-24T11:42:08.122Z",
  "orgId": "org_01HXY...",
  "data": {
    "verificationId": "ver_01HXY...",
    "customerId": "cus_01HXY...",
    "actorUserId": "usr_01HXY...",
    "fromStatus": "requires_review",
    "toStatus": "verified",
    "reason": "Glare on hologram but all OCR fields self-consistent. Approved per supervisor."
  }
}

Register a subscription

POST/api/identity/webhooks
Auth · API keyScope · webhooks:manage
{
  "url": "https://your-app.example.com/webhooks/quantum-identity",
  "events": ["verification.created", "customer.kyc_updated"],
  "installedBy": "kyc-service@v0.1.0"
}

Response includes the signing secret exactly once:

{
  "id": "whk_01HXY...",
  "url": "...",
  "events": [...],
  "secret": "qe_whsec_a8f3c92e...",
  "active": true,
  "createdAt": "..."
}

List + manage

GET    /api/identity/webhooks
PATCH  /api/identity/webhooks/{id}
DELETE /api/identity/webhooks/{id}
POST   /api/identity/webhooks/{id}/test

GET includes per-subscription delivery health:

{
  "rows": [{
    "id": "whk_01HXY...",
    "url": "...",
    "events": ["verification.created"],
    "active": true,
    "deliveryCount": 1287,
    "lastDelivery": {
      "status": "sent",
      "responseCode": 200,
      "at": "2026-05-24T11:42:18.122Z"
    }
  }]
}

Subscribe narrowly

You almost never want all events on one URL. Subscribe each receiver to only the events it actually handles — easier to reason about, easier to scale independently, and a per-receiver outage doesn't cause backpressure on unrelated traffic.