---
title: "Register a webhook endpoint"
method: POST
path: "/api/v1/webhooks"
tags: ["Async"]
---

# Register a webhook endpoint

`POST /api/v1/webhooks`

## Request

- Base URL: `https://legal.nexusquantum.legal`
- URL: `https://legal.nexusquantum.legal/api/v1/webhooks`
- Auth: HTTP bearer

Registers a URL that will receive HMAC-SHA256-signed POSTs on events. The returned secret is shown ONLY ONCE — store it to verify the `X-Nexus-Signature` signature.

Available events: `analysis.completed`, `analysis.failed`, `credits.low`, `normativa.updated` (Spain indexed at 100%, operational event; other jurisdictions still on rails), `citation.broken` and `analysis.flagged`.

- `citation.broken` fires when `anyBroken === true`, that is, when the analysis contained ≥1 verifiable broken citation (`mismatch` + `not_found` + `derogated` > 0). The states `pending` (not parseable) and `not_verifiable` (jurisdiction with no active corpus) do NOT count as broken and never fire the event.
- `analysis.flagged` (the «needs human review» umbrella) fires when `anyBroken === true` OR when verification could not run (`verificationError`, fail-safe). It carries `reasons: string[]` (e.g. `["broken_citations"]`, `["verification_error"]`). The `nodoBVerdict` travels as informational data inside `quality` but is NOT by itself a trigger.

Governance events (v1.30.0): `apikey.created`, `apikey.revoked`, `apikey.updated`, `apikey.spend_cap_changed`, `spend_cap.reached` and `byo_provider.rejected` are low-frequency lifecycle events (key management, spend-cap enforcement, BYO fail-closed rejection). Every event delivered here is also durably readable via the pull API `GET /api/v1/events` (replay/backfill), even for accounts with no push endpoint registered.

Operational governance events (v1.31.0): `provider.unreachable` (a BYO provider was unreachable — payload `provider_id`/`error_class`/`jurisdiction`), `verify.engine.degraded` (the citation-verification engine degraded on a metric — payload `degraded_metric`/`sample_size`/`jurisdiction`) and `rate_limit.sustained` (sustained 429s over a window — payload `window`/`count_429`/`rpm_limit`/`key_id`). Zero-Retention: these payloads carry only those diagnostic fields — never url, key material or request body. Also durably readable via `GET /api/v1/events` and the signed SIEM export `GET /api/v1/audit/export`.

Only API-key-authenticated traffic has a webhook destination: `citation.broken`/`analysis.flagged` are emitted for jobs and synchronous API-key calls, not for web-session traffic.

Every delivery carries a stable `event_id` (uuid) in the body — identical across retries and shared by all subscribed endpoints — for idempotent deduplication in SIEM. It is an alias of `id`; the `X-Nexus-Event-Id` header mirrors that value (unlike `X-Nexus-Delivery-Id`, which is per-endpoint/per-retry and is NOT usable as a dedupe key).

Signature: `X-Nexus-Signature: t=<unix-ts>,v1=<hex-hmac>` where `hmac = HMAC-SHA256(secret, t + '.' + rawBody)`. Exponential retries up to 5 times (1m, 5m, 30m, 2h, 12h).

## Request body

- object
  - `url` string, uri, required
  - `events` string[]
  - `description` string

## Response `201`

Webhook created. The `secret` field is only shown here.

- object

---

[API](https://skmtc.dev/nexusquantum/apis/nexus-legal-api.md) · [All operations](https://skmtc.dev/nexusquantum/apis/nexus-legal-api/llms.txt) · [OpenAPI document](https://skmtc.dev/nexusquantum/apis/nexus-legal-api/revisions/4084d8d4eb0b?raw)
