On this page

API webhooks

Noxtica sends signed HTTPS requests, called deliveries, to the endpoints you register in the Backoffice under Integrations & API, Webhooks. A delivery tells your system that something happened. Treat it as a notification and read the current state from the API before you act on it.

The signing secret of an endpoint is shown once when the endpoint is created or rotated. Store it like an API key.

How this page is organisedBar length shows each section’s share of the text. Select a section to jump to it.

Identity verification API

6 event types

Device intelligence API

5 event types

Webhook events by API

Delivery request

Each delivery is a POST with a JSON body. These headers accompany it:

HeaderRequiredDescription
X-Noxtica-SignatureYessha256= followed by the lowercase hex HMAC-SHA256 of the string <X-Noxtica-Timestamp>.<raw request body>, keyed with the endpoint’s signing secret (the secret string’s UTF-8 bytes). Verify against the raw body bytes before parsing, with a constant-time comparison.
X-Noxtica-TimestampYesUnix time in milliseconds at which this attempt was signed. Every retry is re-signed with a fresh timestamp, so compare it with your own clock (a 300 second tolerance is recommended; Noxtica itself enforces none), not with the body’s created_at.
X-Noxtica-EventYesThe event type; equals type in the body.
X-Noxtica-DeliveryYesThe delivery id; equals id in the body and data.deliveryId. It is identical on every retry of the same delivery: use it as the deduplication key.

Every delivery body is a JSON object with the top-level fields id, type, created_at, tenant_id, data. The content of data depends on the event and is described with each event below.

Verify the signature

The signature header holds sha256= followed by the lowercase hexadecimal HMAC-SHA256 of the string <timestamp header>.<raw request body>, keyed with the signing secret of the endpoint. Compute it over the raw body bytes before you parse the JSON, compare it in constant time, and reject a delivery whose timestamp is outside a tolerance you choose. The samples use five minutes. The timestamp is in milliseconds since the Unix epoch.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

const TOLERANCE_MS = 5 * 60 * 1000;

export function verifyWebhook({ secret, rawBody, signature, timestamp }) {
  const age = Math.abs(Date.now() - Number(timestamp));
  if (!Number.isFinite(age) || age > TOLERANCE_MS) return false;
  const expected = createHmac('sha256', secret).update(`${timestamp}.`).update(rawBody).digest('hex');
  const received = String(signature).replace(/^sha256=/, '').toLowerCase();
  const a = Buffer.from(expected);
  const b = Buffer.from(received);
  return a.length === b.length && timingSafeEqual(a, b);
}

Python

import hashlib
import hmac
import time

TOLERANCE_MS = 5 * 60 * 1000


def verify_webhook(secret: str, raw_body: bytes, signature: str, timestamp: str) -> bool:
    try:
        sent = int(timestamp)
    except ValueError:
        return False
    if abs(time.time() * 1000 - sent) > TOLERANCE_MS:
        return False
    signed = timestamp.encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    received = signature.removeprefix("sha256=").lower()
    return hmac.compare_digest(expected, received)

Shell (openssl)

printf '%s.%s' "$TIMESTAMP" "$RAW_BODY" \
  | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"

Compare the printed hexadecimal digest with the part of the signature header after sha256=.

Delivery, retries and deduplication

Answer every delivery with a 2xx status as soon as you have stored it, and process it afterwards. The delivery header is the same on every retry of one delivery, so use it as the deduplication key.

Noxtica sends events to the HTTPS endpoints your organisation registers in the Backoffice (Integrations & API, Webhooks); an endpoint receives only the event types ticked on it. An endpoint URL must be HTTPS without embedded credentials and must not point at a private, loopback or internal address, and an organisation can register at most 25 endpoints. The signing secret is shown once when the endpoint is created or rotated; a rotation invalidates the old secret at once.

Request. Each delivery is POST with Content-Type: application/json and the headers X-Noxtica-Signature, X-Noxtica-Timestamp (Unix milliseconds), X-Noxtica-Event and X-Noxtica-Delivery. The body is the envelope {"id","type","created_at","tenant_id","data"}: id equals X-Noxtica-Delivery, created_at is Unix milliseconds and tenant_id is your organisation. Verdict payloads carry no raw IP address and no personal data.

Signature. X-Noxtica-Signature is sha256= plus the lowercase hex HMAC-SHA256, keyed with the endpoint’s secret (its UTF-8 bytes), of the string <X-Noxtica-Timestamp>.<raw body>. Recompute it over the raw body bytes before parsing the JSON, compare in constant time, and reject a stale timestamp (Noxtica enforces no tolerance of its own; 300 seconds is recommended). Every retry is re-signed with a fresh timestamp.

import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(secret, timestamp, rawBody, signatureHeader) {
  const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
  const given = signatureHeader.replace(/^sha256=/, '').toLowerCase();
  return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}

Delivery and retries. Delivery is at-least-once, never exactly-once: deduplicate on X-Noxtica-Delivery, which is identical on every retry of the same delivery. Answer within 5 seconds; redirects are never followed. Any 2xx marks the delivery delivered. Any 4xx (including 408 and 429) is final: it is never retried. A 3xx, a 5xx, a timeout or a network error is retried, up to 5 retries after the first attempt, after which the delivery is recorded as dead and is not retried again. The spacing between retries is not published. Respond 2xx first and process asynchronously. Events can arrive out of order. A webhook is a notification, not authority: read the resource it refers to before taking an irreversible action. The Backoffice “Send test” button sends only a sample submission.scored event.

Event catalog

EventSent whenAPI
kyc.session.completedA hosted verification session reached a business outcomeIdentity verification API
kyc.session.cancelledThe end customer cancelled a hosted verification sessionIdentity verification API
kyc.verification.completedA KYC verification request reached a terminal stateIdentity verification API
kyc.erasure.completedA KYC erasure request finished successfullyIdentity verification API
kyc.document.expiry_warningA verified identity document is approaching or past its expiryIdentity verification API
kyc.reverification.dueA previously verified identity is due for re-verificationIdentity verification API
submission.scoredA submission was scoredDevice intelligence API
risk.highA submission was scored high or criticalDevice intelligence API
risk.flaggedA risk flag firedDevice intelligence API
risk.cluster_flaggedA device cluster was flagged as badDevice intelligence API
account.agent_linkedA verified agent was linked to an account for the first timeDevice intelligence API

kyc.session.completed

A hosted verification session reached a business outcome

Sent by Noxtica to every endpoint you registered for kyc.session.completed (Backoffice, Integrations & API, Webhooks). See “Webhooks (KYC)” in the API description for the headers, the signature, retries and deduplication; they are common to all six KYC events.

When it fires. A hosted session reached completed, unverified or error. It does not fire when a session lands in review_pending. With the identity provider configured today, a successful hosted capture ends in review_pending (the provider routes every success to manual review, reason code provider_manual_review); the event is sent later, when a Backoffice reviewer approves or overrides the case and the session moves review_pending to completed. Allow up to about 5 minutes between the reviewer’s decision and the delivery (the relay runs on the platform’s 5-minute tick). A review_pending session never expires, so your system must keep waiting for the decision (or poll GET /v1/kyc/sessions/{sessionId}). It never fires for expired or cancelled_by_user sessions.

This is a notification, not authority: before you act on it, read GET /v1/kyc/sessions/{sessionId}. The payload carries no subject reference; correlate by data.sessionId, the id you stored when you minted the session.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id, <sessionId>:<webhookId>. Identical on every retry; equals X-Noxtica-Delivery and data.deliveryId.
typestringYesAllowed values: kyc.session.completed.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycSessionCompletedWebhookData)YesThe data member of kyc.session.completed (schemaVersion "1"). Delivery is at-least-once: deduplicate by deliveryId. A webhook is a notification, not authority; read GET /v1/kyc/sessions/{sessionId} for the outcome. There is no subject reference, digest, evidence id or scorecard. The event does not fire when a session lands in review_pending; it fires when a reviewer’s decision moves it to completed. email and emailVerified (added 2026-10-01, additive) are present only when hosted email verification is enabled for the platform AND the session has a stored address; otherwise both keys are absent.
data.schemaVersionstringYesAllowed values: 1.
data.sessionIdstring (uuid)YesThe id the mint call returned.
data.statusstringYesThe terminal session status. expired and cancelled_by_user sessions never emit this event. Allowed values: completed, unverified, error.
data.verificationIdstring, nullableYes
data.reasonCodesarray of stringYes
data.occurredAtinteger (int64)YesUnix ms the session reached this status (its completedAt).
data.deliveryIdstringYes
data.nvidstringNoThe session’s Noxtica Verification ID (NVID-XXXX-XXXX-XXXX-XXXX). Present only when the session has one (the feature is enabled for your organisation and the outcome was positive); otherwise absent. Never accompanied by the address the person may have given to receive it.
data.emailstringNoPresent only when the session has a stored address (and hosted email verification is enabled for the platform). The normalised address the end customer entered in the hosted flow. Unverified unless emailVerified is true.
data.emailVerifiedbooleanNoPresent together with email. true only if the customer clicked the confirmation link for email.

Example payload

{
  "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c",
  "type": "kyc.session.completed",
  "created_at": 1790762445000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
    "status": "completed",
    "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reasonCodes": [],
    "occurredAt": 1790762445000,
    "deliveryId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c"
  }
}

kyc.session.cancelled

The end customer cancelled a hosted verification session

Sent when the customer confirms on the hosted page that they do not want to continue and the session actually moves to cancelled_by_user. Available only when session cancellation is enabled for your organisation. Subscriptions are opt-in per event: an endpoint registered before this event existed does not receive it until you add it to the endpoint’s event list.

data.cancelReason and data.cancelledAt are delivered only in this event. GET /v1/kyc/sessions/{sessionId} reports the terminal status cancelled_by_user but does not return the cancel reason or the cancel time. An expiry emits no event; observe it by reading the session status.

See “Webhooks (KYC)” in the API description for headers, signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id, <sessionId>:<webhookId>.
typestringYesAllowed values: kyc.session.cancelled.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycSessionCancelledWebhookData)YesThe data member of kyc.session.cancelled (schemaVersion "1"). Same delivery semantics as KycSessionCompletedWebhookData. email and emailVerified (added 2026-10-01, additive) are present only when hosted email verification is enabled for the platform AND the session has a stored address; otherwise both keys are absent.
data.schemaVersionstringYesAllowed values: 1.
data.sessionIdstring (uuid)Yes
data.statusstringYesAllowed values: cancelled_by_user.
data.cancelReasonone of KycSessionCancelReason or any, nullableYes
data.cancelledAtinteger (int64)YesUnix ms.
data.occurredAtinteger (int64)YesUnix ms; equal to cancelledAt.
data.deliveryIdstringYes
data.emailstringNoPresent only when the session has a stored address (and hosted email verification is enabled for the platform). The normalised address the end customer entered before cancelling. Unverified unless emailVerified is true.
data.emailVerifiedbooleanNoPresent together with email. true only if the customer clicked the confirmation link for email.

Example payload

{
  "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c",
  "type": "kyc.session.cancelled",
  "created_at": 1790762300000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
    "status": "cancelled_by_user",
    "cancelReason": "not_now",
    "cancelledAt": 1790762300000,
    "occurredAt": 1790762300000,
    "deliveryId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c"
  }
}

kyc.verification.completed

A KYC verification request reached a terminal state

Sent when a verification request (POST /v1/kyc/verify, or the verification a hosted session runs when the customer submits) reaches a terminal state: completed, terminal_error, expired or cancelled. The non-terminal states retryable_error and provider_unknown emit nothing. data.verdict is the stored canonical verdict (verified, unverified or error; error for an infrastructure-faulted terminal request that has no verdict).

A hosted session’s submit runs the same pipeline, so an endpoint subscribed to both events can receive kyc.verification.completed for the same attempt as kyc.session.*; with the identity provider configured today the verdict of a successful hosted capture is unverified with the reason code provider_manual_review. Delivery order between the two events is not guaranteed. data.verificationId equals session.verificationId on the session status read.

See “Webhooks (KYC)” in the API description for headers, signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id, <verificationId>:<webhookId>.
typestringYesAllowed values: kyc.verification.completed.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycVerificationCompletedWebhookData)YesThe data member of kyc.verification.completed (schemaVersion "1"). A closed, non-personal field set: no subject id, digest or document value. Deduplicate by deliveryId; read the verification through the API before acting.
data.schemaVersionstringYesAllowed values: 1.
data.verificationIdstringYes
data.verdictstringYesAllowed values: verified, unverified, error.
data.reasonCodesarray of stringYesClosed reason-code catalog; may be empty.
data.idTypestringYesThe document type asserted on the request, e.g. passport.
data.occurredAtinteger (int64)YesUnix ms the verification reached its terminal state.
data.deliveryIdstringYes

Example payload

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6:wh_7f3a2c",
  "type": "kyc.verification.completed",
  "created_at": 1790762440000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "verdict": "unverified",
    "reasonCodes": [
      "provider_manual_review"
    ],
    "idType": "passport",
    "occurredAt": 1790762440000,
    "deliveryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6:wh_7f3a2c"
  }
}

kyc.erasure.completed

A KYC erasure request finished successfully

Sent when an erasure request reaches completed. A partial erasure never emits this event. The payload deliberately carries no subject identifier or subject digest: an erasure notification must not re-establish a link to the person whose linkage was just erased. data.requestId is the erasure request’s own id.

See “Webhooks (KYC)” in the API description for headers, signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals data.deliveryId.
typestringYesAllowed values: kyc.erasure.completed.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycErasureCompletedWebhookData)YesThe data member of kyc.erasure.completed (schemaVersion "1"). Emitted only when the erasure request reaches completed; a partial erasure emits nothing. No subject identifier is carried.
data.schemaVersionstringYesAllowed values: 1.
data.requestIdstringYesThe erasure request’s own id; not a subject id.
data.outcomestringYesAllowed values: completed.
data.occurredAtinteger (int64)YesUnix ms the erasure request reached its terminal state.
data.deliveryIdstringYes

Example payload

{
  "id": "er_4b81d2:wh_7f3a2c",
  "type": "kyc.erasure.completed",
  "created_at": 1790900000000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "requestId": "er_4b81d2",
    "outcome": "completed",
    "occurredAt": 1790900000000,
    "deliveryId": "er_4b81d2:wh_7f3a2c"
  }
}

kyc.document.expiry_warning

A verified identity document is approaching or past its expiry

Sent by the scheduled document-expiry monitoring pass when a monitored verification’s document crosses the 90, 60 or 30 day threshold or has expired (data.alertType). Only available when document-expiry monitoring is enabled for your organisation. Each threshold fires once per monitored verification.

Unlike the other KYC events, this event is not read from the delivery ledger: the scheduled pass makes a single signed delivery attempt to each subscribed endpoint and does not retry a failed attempt. Deduplicate on the delivery id anyway, and use data.verificationId to correlate with the original kyc.verification.completed. See “Webhooks (KYC)” for headers and signature.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals data.deliveryId.
typestringYesAllowed values: kyc.document.expiry_warning.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycDocumentExpiryWarningWebhookData)YesThe data member of kyc.document.expiry_warning (schemaVersion "1"). No subject id and no document number: correlate by verificationId.
data.schemaVersionstringYesAllowed values: 1.
data.verificationIdstringYes
data.alertTypestringYesAllowed values: expiry_90d, expiry_60d, expiry_30d, expiry_expired.
data.documentExpiresAtinteger (int64)YesUnix ms the monitored document expires (or expired).
data.occurredAtinteger (int64)YesUnix ms the threshold crossing was detected.
data.deliveryIdstringYes

Example payload

{
  "id": "sched_91c0:wh_7f3a2c",
  "type": "kyc.document.expiry_warning",
  "created_at": 1798538000000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "alertType": "expiry_30d",
    "documentExpiresAt": 1801130000000,
    "occurredAt": 1798538000000,
    "deliveryId": "sched_91c0:wh_7f3a2c"
  }
}

kyc.reverification.due

A previously verified identity is due for re-verification

Sent by the same scheduled monitoring pass as kyc.document.expiry_warning when a re-verification schedule entry reaches its due time. Only available when document-expiry monitoring is enabled for your organisation, and only for a verification that has a re-verification schedule entry. Single signed delivery attempt, no retry, as for kyc.document.expiry_warning.

See “Webhooks (KYC)” in the API description for headers and signature.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals data.deliveryId.
typestringYesAllowed values: kyc.reverification.due.
created_atinteger (int64)YesUnix ms the event occurred.
tenant_idstringYes
dataobject (KycReverificationDueWebhookData)YesThe data member of kyc.reverification.due (schemaVersion "1"). No subject id.
data.schemaVersionstringYesAllowed values: 1.
data.verificationIdstringYes
data.dueAtinteger (int64)YesUnix ms the re-verification became due.
data.occurredAtinteger (int64)Yes
data.deliveryIdstringYes

Example payload

{
  "id": "sched_92d1:wh_7f3a2c",
  "type": "kyc.reverification.due",
  "created_at": 1801130000000,
  "tenant_id": "tenant_42",
  "data": {
    "schemaVersion": "1",
    "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "dueAt": 1801130000000,
    "occurredAt": 1801130000000,
    "deliveryId": "sched_92d1:wh_7f3a2c"
  }
}

submission.scored

A submission was scored

Sent for every scored browser or app submission of your organisation (the broadest subscription: use risk.high or risk.flagged if you only need the notable ones). The Backoffice “Send test” button sends a sample of this event type, with placeholder verdict data and a valid signature.

data.event_id is the request id of the submission: correlate it with the X-Request-Id your browser integration received. data.device_id is the opaque device id (fingerprintId). This is a notification, not authority; read the device (GET /v1/device/{deviceId}) before taking an irreversible action.

See “Webhook delivery and retries” in the API description for the headers, the signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals X-Noxtica-Delivery.
typestringYesAllowed values: submission.scored, risk.high, risk.flagged, risk.cluster_flagged.
created_atinteger (int64)YesUnix ms the event was produced.
tenant_idstringYes
dataobject (VerdictWebhookData)YesThe verdict of one scored submission. Never carries a raw IP address or personal data.
data.scorenumberNoThe numeric risk score.
data.risk_levelstringNoThe verdict band, for example low, medium, high or critical.
data.confidencenumberNoModel confidence from 0 to 1.
data.flagsarray of stringNoThe risk flags that fired.
data.reason_codesarray of stringNoThe published reason-code projection of flags; empty unless reason-code output is enabled for your organisation.
data.device_idstringYesThe opaque device id. An empty string means that no stable per-device identity is available for this event.
data.domain_idstringYesYour domain id.
data.event_idstringYesThe request id of the submission or attestation; always present.

Example payload

{
  "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
  "type": "submission.scored",
  "created_at": 1790762445000,
  "tenant_id": "YOUR_TENANT_ID",
  "data": {
    "score": 12,
    "risk_level": "low",
    "confidence": 0.91,
    "flags": [],
    "reason_codes": [],
    "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "domain_id": "dom_42",
    "event_id": "8f1c2a52-6a6e-4b0e-9d52-2a7c1d9e4b10"
  }
}

risk.high

A submission was scored high or critical

Sent when a scored submission lands in the high or critical risk band. The payload is the same verdict shape as submission.scored. A submission in that band also produces submission.scored (and risk.flagged when a flag fired) for endpoints subscribed to those types.

See “Webhook delivery and retries” in the API description for the headers, the signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals X-Noxtica-Delivery.
typestringYesAllowed values: submission.scored, risk.high, risk.flagged, risk.cluster_flagged.
created_atinteger (int64)YesUnix ms the event was produced.
tenant_idstringYes
dataobject (VerdictWebhookData)YesThe verdict of one scored submission. Never carries a raw IP address or personal data.
data.scorenumberNoThe numeric risk score.
data.risk_levelstringNoThe verdict band, for example low, medium, high or critical.
data.confidencenumberNoModel confidence from 0 to 1.
data.flagsarray of stringNoThe risk flags that fired.
data.reason_codesarray of stringNoThe published reason-code projection of flags; empty unless reason-code output is enabled for your organisation.
data.device_idstringYesThe opaque device id. An empty string means that no stable per-device identity is available for this event.
data.domain_idstringYesYour domain id.
data.event_idstringYesThe request id of the submission or attestation; always present.

Example payload

{
  "id": "0b9d7b1c-2f0e-4c8b-9a52-7c1b3a1f9e11",
  "type": "risk.high",
  "created_at": 1790762446000,
  "tenant_id": "YOUR_TENANT_ID",
  "data": {
    "score": 87,
    "risk_level": "high",
    "confidence": 0.88,
    "flags": [
      "example_flag"
    ],
    "reason_codes": [],
    "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "domain_id": "dom_42",
    "event_id": "3a7d1e52-6a6e-4b0e-9d52-2a7c1d9e4b11"
  }
}

risk.flagged

A risk flag fired

Sent when at least one risk flag fired on a scored submission, whatever its risk band.

The same event type is also sent after each mobile attestation verify (see POST /v1/attest/android and POST /v1/attest/ios), with flags of the form mobile_attest:<platform>, mobile_attest_level:<level> and mobile_attest_verdict:<verdict>. There data.device_id can be an empty string, which means that no stable per-device identity is available for the event: do not group events on an empty device_id, and use data.event_id, which is always present, as the per-event key.

See “Webhook delivery and retries” in the API description for the headers, the signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals X-Noxtica-Delivery.
typestringYesAllowed values: submission.scored, risk.high, risk.flagged, risk.cluster_flagged.
created_atinteger (int64)YesUnix ms the event was produced.
tenant_idstringYes
dataobject (VerdictWebhookData)YesThe verdict of one scored submission. Never carries a raw IP address or personal data.
data.scorenumberNoThe numeric risk score.
data.risk_levelstringNoThe verdict band, for example low, medium, high or critical.
data.confidencenumberNoModel confidence from 0 to 1.
data.flagsarray of stringNoThe risk flags that fired.
data.reason_codesarray of stringNoThe published reason-code projection of flags; empty unless reason-code output is enabled for your organisation.
data.device_idstringYesThe opaque device id. An empty string means that no stable per-device identity is available for this event.
data.domain_idstringYesYour domain id.
data.event_idstringYesThe request id of the submission or attestation; always present.

Example payload

{
  "id": "9c1e5d2a-3b4f-4a6c-8d7e-1f2a3b4c5d6e",
  "type": "risk.flagged",
  "created_at": 1790762447000,
  "tenant_id": "YOUR_TENANT_ID",
  "data": {
    "score": 40,
    "risk_level": "medium",
    "confidence": 0.7,
    "flags": [
      "example_flag"
    ],
    "reason_codes": [],
    "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "domain_id": "dom_42",
    "event_id": "5e8f2a52-6a6e-4b0e-9d52-2a7c1d9e4b12"
  }
}

risk.cluster_flagged

A device cluster was flagged as bad

Sent once, on the first escalation, when a cluster of devices (devices sharing an observational sub-fingerprint) is flagged bad in real time because a high or critical submission came with strong cluster evidence. It lets you react to an emerging cluster before slower offline feeds catch up. A cluster that is already flagged does not produce a new delivery for every further submission.

The payload has the same verdict shape as submission.scored; data.risk_level is the cluster’s band. It carries no raw IP address and no personal data. Available only when real-time cluster propagation is enabled for the deployment.

See “Webhook delivery and retries” in the API description for the headers, the signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals X-Noxtica-Delivery.
typestringYesAllowed values: submission.scored, risk.high, risk.flagged, risk.cluster_flagged.
created_atinteger (int64)YesUnix ms the event was produced.
tenant_idstringYes
dataobject (VerdictWebhookData)YesThe verdict of one scored submission. Never carries a raw IP address or personal data.
data.scorenumberNoThe numeric risk score.
data.risk_levelstringNoThe verdict band, for example low, medium, high or critical.
data.confidencenumberNoModel confidence from 0 to 1.
data.flagsarray of stringNoThe risk flags that fired.
data.reason_codesarray of stringNoThe published reason-code projection of flags; empty unless reason-code output is enabled for your organisation.
data.device_idstringYesThe opaque device id. An empty string means that no stable per-device identity is available for this event.
data.domain_idstringYesYour domain id.
data.event_idstringYesThe request id of the submission or attestation; always present.

Example payload

{
  "id": "2a4c6e8f-1b3d-4f5a-9c7e-0d2b4f6a8c1e",
  "type": "risk.cluster_flagged",
  "created_at": 1790762448000,
  "tenant_id": "YOUR_TENANT_ID",
  "data": {
    "score": 91,
    "risk_level": "critical",
    "confidence": 0.93,
    "flags": [
      "example_flag"
    ],
    "reason_codes": [],
    "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "domain_id": "dom_42",
    "event_id": "7a9b1c52-6a6e-4b0e-9d52-2a7c1d9e4b13"
  }
}

account.agent_linked

A verified agent was linked to an account for the first time

Sent once, when a cryptographically verified signed agent (Web Bot Auth, RFC 9421) is linked to one of your end-user accounts for the first time, that is when the (agent, account) pair had no earlier link. It lets you react when a new agent starts acting on an account.

The payload carries the keyed account_hash (a 16-character lowercase-hex pseudonym; the raw account id is never stored or sent), the verified agent’s agent_keyid and agent_host, and the usual device_id, domain_id and event_id. It carries no raw IP address and no personal data. Use GET /v1/accounts/{accountHash}/devices to list the devices and agents linked to the account.

See “Webhook delivery and retries” in the API description for the headers, the signature, retries and deduplication.

Payload

FieldTypeRequiredDescription
idstringYesThe delivery id; equals X-Noxtica-Delivery.
typestringYesAllowed values: account.agent_linked.
created_atinteger (int64)YesUnix ms the event was produced.
tenant_idstringYes
dataobject (AgentLinkedWebhookData)YesThe first link between a verified agent and one of your accounts. Never carries a raw account id, IP address or personal data.
data.account_hashstringYesThe keyed 16-character lowercase-hex account pseudonym.
data.agent_keyidstringYesThe verified agent’s Signature-Input key id.
data.agent_hoststring, nullableYesThe verified agent’s directory host
data.device_idstringYes
data.domain_idstringYes
data.event_idstringYes

Example payload

{
  "id": "4d6f8a1c-5e7b-4d9f-8a2c-3b5d7f9a1c2e",
  "type": "account.agent_linked",
  "created_at": 1790762449000,
  "tenant_id": "YOUR_TENANT_ID",
  "data": {
    "account_hash": "0a1b2c3d4e5f6071",
    "agent_keyid": "agent-key-1",
    "agent_host": "agent.example.com",
    "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "domain_id": "dom_42",
    "event_id": "9b1d3f52-6a6e-4b0e-9d52-2a7c1d9e4b14"
  }
}

This page is generated from the Noxtica OpenAPI specification release v0.4.0: kyc.yaml version 1.2.0-2026-10-27 (SHA-256 c91a695cfde0), mcp.yaml version 0.1.0-2026-10-27 (SHA-256 1a4875efa736), pulse.yaml version 0.9.0-2026-10-27 (SHA-256 95196a58bb5b), v1.yaml version 1.3.0-2026-10-27 (SHA-256 3fd15257a022). Do not edit it by hand.