/api/v1/alerts/webhookRegister a verified alert route.
Point Lexinode at an HTTPS endpoint and choose the failure-delta threshold and pillar that matter to your team. Registration is authenticated with the same API-key identity as POST /api/v1/audit.
X-API-Key header. The registration is stored against the verified key ID; no owner or key ID is accepted from the request body.01 / Request
One URL, one trigger.
The canonical body nests the trigger configuration under trigger. The server accepts only HTTPS URLs; DNS and destination checks happen during verification.
curl -X POST https://lexinode.polsia.app/api/v1/alerts/webhook \
-H "Content-Type: application/json" \
-H "X-API-Key: $LEX_KEY" \
-d '{
"url": "https://hooks.example.com/lexinode",
"trigger": {
"severity": "high",
"branch": "privacy"
}
}'02 / Verification
Prove the destination before it is saved.
Lexinode generates a nonce and sends a JSON verification ping to the submitted URL. Any 2xx response within the configured timeout completes registration; the response body does not need to echo the challenge.
POST with Content-Type: application/json.{
"type": "lexinode.webhook.verification",
"challenge": "<server-generated nonce>"
}HTTPS only, including DNS/IP-layer SSRF protection.
Redirects are rejected; the verifier never follows a 3xx response.
Default timeout is 5 seconds, bounded to a maximum of 15 seconds.
03 / Delivery
Signed failure events.
After a successful audit is persisted, Lexinode sends one event to every verified destination owned by the same API key whose branch and severity threshold match. The audit branch maps wcag to accessibility; ai-governance maps to ai_gov. Only fail findings are eligible.
{
"type": "lexinode.audit.failure",
"version": 1,
"deliveryId": "clx_attempt_123",
"timestamp": "2026-08-28T12:00:00.000Z",
"audit": {
"id": "clx_audit_123",
"url": "https://example.com",
"branch": "accessibility",
"createdAt": "2026-08-28T11:59:58.000Z",
"totals": { "errors": 1, "warnings": 0 }
},
"failures": [{
"control": "1.4.3",
"status": "fail",
"severity": "error",
"evidence": "Contrast ratio is below the required threshold."
}]
}Warning findings match medium; error findings match high.
Critical registrations currently never match because audits emit no critical findings.
No request is sent when the completed audit has no matching failures.
A 2xx delivery is marked delivered; timeout, unsafe-host, network, redirect, and non-2xx outcomes are marked failed.
04 / Signing
The challenge becomes the secret.
The challenge generated during registration is stored server-side and is never returned in JSON, the dashboard, or failure text. Each delivery uses HMAC-SHA256 over timestamp.deliveryId.body, wherebody is the exact serialized JSON request bytes.
X-Lexinode-Signature is sent as sha256=<hex digest>.
X-Lexinode-Timestamp, X-Lexinode-Delivery-Id, X-Lexinode-Event, and X-Lexinode-Version accompany the request.
Legacy registrations without a stored challenge are recorded as failed and are not sent.
05 / Response
A durable verified configuration.
Successful registration returns 201 only after the handshake succeeds. The API key itself is never returned or persisted in plaintext.
{
"id": "clx_webhook_123",
"url": "https://hooks.example.com/lexinode",
"trigger": {
"severity": "high",
"branch": "privacy"
},
"verifiedAt": "2026-08-27T12:00:00.000Z",
"createdAt": "2026-08-27T12:00:00.000Z",
"latestAttempt": null
}06 / Errors
Predictable failure states.
| Status | Meaning | Body |
|---|---|---|
| 400 | Malformed JSON or a body outside the shared contract. | { "errors": { "<field>": "<message>" } } |
| 401 | X-API-Key is missing, invalid, or revoked. | { "error": "invalid api key" } |
| 422 | The HTTPS destination is unsafe or did not complete verification. | { "error": "webhook verification failed", "reason": "…" } |
| 403 | The dashboard list was requested without an admin session. | { "error": "forbidden" } |
| 500 | An unexpected server or persistence failure occurred. | { "error": "internal server error" } |