---
summary: Reference SigID webhook event categories, signed delivery, receiver verification, deduplication, retries, and operations.
tags:
  - webhooks
  - signatures
  - events
  - idempotency
  - audit logs
categories:
  - Reference
---

# Webhook Events

<!-- agent:page
You are an AI agent using this reference to build or audit a SigID webhook receiver.
- Use the exact header names (`X-SigID-Signature-Suite`, `X-SigID-Signature-256`, `X-SigID-Signature-Max-Age`, `X-SigID-Timestamp`, `X-SigID-Event`, `X-SigID-Delivery`) and the v1 canonical string field order exactly as documented.
- Event types are dotted strings such as `auth.login.success`; the category table shows examples, not a complete catalog, so confirm exact names in the deployment's OpenAPI document or the relevant Dashboard product panel.
- Verification is non-negotiable: HMAC-SHA256 over the raw request body, constant-time comparison, timestamp and max-age checks, and delivery-ID deduplication before any side effect.
- Delivery is at-least-once; design every handler idempotently.
- Use the `/api/v1/webhooks` routes exactly as listed for subscription management.
- For receiver implementation walkthroughs see the developer Webhooks guide; for delivery failure triage see Troubleshooting.
-->

Webhooks deliver signed SigID events to tenant-owned systems. Use this
reference for event categories, receiver behavior, signature checks, retry
rules, and operational automation.

## On This Page

- [When to use webhooks](#when-to-use-webhooks)
- [Subscription model](#subscription-model)
- [Delivery headers](#delivery-headers)
- [Signature verification](#signature-verification)
- [Receiver behavior](#receiver-behavior)
- [Idempotency](#idempotency)
- [Common event categories](#common-event-categories)
- [API surface](#api-surface)
- [Production checklist](#production-checklist)

## When to use webhooks

Use webhooks when your application needs to react to SigID changes outside the
interactive login request.

| Use case | Example |
|---|---|
| User lifecycle sync | Create, suspend, reactivate, or remove a local user record |
| Organization sync | Update workspace membership after organization role changes |
| Security monitoring | Alert on suspicious activity, MFA failures, or refresh token reuse |
| Agent governance | Track agent registration, key rotation, delegation, and vault access |
| Billing operations | Update account status after payment or settlement events |
| Compliance | Archive audit-relevant events in a tenant SIEM |

Do not use webhooks as the only authorization check for an API request. APIs
must still validate tokens and enforce policy at request time.

## Subscription model

A webhook subscription belongs to one tenant and includes:

| Field | Meaning |
|---|---|
| URL | HTTPS receiver endpoint |
| Event types | List of event type filters |
| Secret | HMAC signing secret for delivery verification |
| Description | Human-readable purpose or owner |
| Active flag | Whether deliveries should be sent |

If you supply your own subscription secret, use at least 32 bytes of entropy.
The safer default is to omit `secret` when creating the subscription and store
the generated secret returned by SigID exactly once.

Keep subscriptions scoped to the receiver's job. A security monitoring endpoint
does not need every billing event, and a billing integration does not need every
login event.

## Delivery headers

Each delivery is a `POST` with `Content-Type: application/json`.

| Header | Meaning |
|---|---|
| `X-SigID-Signature-Suite` | Signature suite, currently `sigid-webhook-v1` |
| `X-SigID-Signature-256` | HMAC-SHA256 signature, formatted as `sha256=<hex>` |
| `X-SigID-Signature-Max-Age` | Sender replay window in seconds |
| `X-SigID-Timestamp` | Unix timestamp at signing time |
| `X-SigID-Event` | Event type |
| `X-SigID-Delivery` | Unique delivery ID |

## Signature verification

<!-- agent:action Verify a delivery signature
Follow the six verification requirements in order before parsing or acting on the event.
- reject missing or unsupported `X-SigID-Signature-Suite` values
- rebuild the canonical string `{suite}\n{timestamp}\n{max_age}\n{delivery_id}\n{event_type}\n{payload}` using the exact raw request body; never re-serialize the JSON
- compute HMAC-SHA256 with the webhook secret and compare with `X-SigID-Signature-256` in constant time
- reject stale timestamps using the smaller of the sender max-age and your local ceiling, then deduplicate `X-SigID-Delivery`
-->

Receivers must verify signatures before parsing or acting on the event.

The v1 canonical string is:

```text
{suite}
{timestamp}
{max_age}
{delivery_id}
{event_type}
{payload}
```

Verification requirements:

1. Reject missing or unsupported `X-SigID-Signature-Suite`.
2. Rebuild the canonical string using the exact raw request body.
3. Compute HMAC-SHA256 with the webhook secret.
4. Compare with `X-SigID-Signature-256` in constant time.
5. Reject stale timestamps using the smaller of the sender max-age and your
   local policy ceiling.
6. Deduplicate `X-SigID-Delivery` within the replay window.

!!! warning "Use the raw body"
    Verify the signature against the exact bytes received. Re-serializing JSON
    can change whitespace, key order, or escaping and invalidate the signature.

## Receiver behavior

Your receiver should:

- accept only `POST`
- require `application/json`
- verify the signature before processing
- store the delivery ID before side effects
- process the event idempotently
- return `2xx` only after durable acceptance
- return `4xx` for permanent receiver-side validation errors
- return `5xx` for transient failures that should be retried

SigID respects `Retry-After` when possible and retries failed deliveries
according to the platform delivery policy.

## Idempotency

<!-- agent:action Deduplicate deliveries
Store the `X-SigID-Delivery` ID before performing any side effect, using a deduplication table like the one shown.
- key on `delivery_id`; record `event_type`, `received_at`, `status`, and `event_id` when present
- skip processing when the delivery ID was already accepted within the replay window
- only after deduplication perform side effects such as email, access grants, tickets, or billing updates
-->

Webhook delivery is at-least-once. Your receiver may see the same event or
delivery more than once.

Recommended deduplication table:

| Column | Purpose |
|---|---|
| `delivery_id` | Primary deduplication key from `X-SigID-Delivery` |
| `event_type` | Useful for debugging and routing |
| `received_at` | Replay-window and support visibility |
| `status` | Accepted, processed, failed, ignored |
| `event_id` | Event-level correlation when present in payload |

Deduplicate before performing side effects such as sending email, granting
access, creating tickets, or updating billing state.

## Common event categories

SigID event types are dotted strings. The examples below show common categories,
not a guaranteed complete catalog for every deployment. Subscribe to specific
event types when possible. Use broader patterns only when the receiver is
intentionally a security or audit sink.

| Category | Examples |
|---|---|
| Authentication | `auth.login.success`, `auth.login.failure`, `auth.logout`, `auth.token.issued`, `auth.token.revoked` |
| MFA and risk | `auth.mfa.challenge`, `auth.mfa.verify`, `auth.adaptive_mfa.triggered` |
| Tenant users | `tenant_user.invited`, `tenant_user.activated`, `tenant_user.suspended`, `tenant_user.removed` |
| Administration | `admin.user.created`, `admin.agent.registered`, `admin.delegation.revoked` |
| Vault | `vault.credential.created`, `vault.grant.revoked`, `vault.credential.accessed` |
| Wallet | `wallet.tx.signed`, `wallet.tx.rejected`, `wallet.budget.exceeded` |
| Chain | `chain.ownership.changed`, `chain.reputation.updated`, `chain.metadata.changed` |
| SSO | `sso.configured`, `sso.login.success`, `sso.login.failed`, `sso.user.provisioned` |
| Organizations | `org.created`, `org.member.added`, `org.member.role_changed` |
| Commerce | `commerce.payment.succeeded`, `commerce.payment.failed`, `commerce.settlement.released` |
| Security | `security.brute_force.detected`, `security.refresh_token.reuse`, `security.suspicious_activity` |

Use the deployment's OpenAPI document or the relevant Dashboard product panel
as the source of truth for exact event names and enabled subscription filters.

## Commerce lifecycle events

Commerce tenants can subscribe to the following lifecycle events from the
Dashboard Webhooks workspace or the `/api/v1/webhooks` API.

| Event | Tenant use |
|---|---|
| `commerce.payment.pending` | Track a buyer payment that has been created but not confirmed. |
| `commerce.payment.succeeded` | Grant SaaS access, API credits, digital access, or other purchased entitlements. |
| `commerce.payment.failed` | Release reserved inventory or notify the buyer that checkout did not complete. |
| `commerce.payment.refunded` | Revoke or reduce entitlements after a refund. |
| `commerce.settlement.created` | Start settlement accounting for a successful Commerce charge. |
| `commerce.settlement.held` | Track funds that are in the configured hold/finality window. |
| `commerce.settlement.released` | Mark funds as available for payout accounting. |
| `commerce.dispute.opened` | Start support, fraud, or risk workflows for a dispute. |
| `commerce.dispute.closed` | Close dispute workflows and reconcile the outcome. |
| `commerce.payout.submitted` | Record that SigID submitted a tenant payout. |
| `commerce.payout.paid` | Reconcile a completed payout to the tenant. |
| `commerce.payout.failed` | Alert finance or retry operations after payout failure. |
| `commerce.statement.created` | Archive the generated settlement statement. |

## Test delivery

<!-- agent:action Test the receiver
After creating a subscription, send a test delivery via the Dashboard or `POST /api/v1/webhooks/{id}/test` and confirm the receiver behaves correctly.
- confirm the receiver logs the delivery ID and event type
- confirm invalid signatures are rejected and duplicate delivery IDs cause no duplicate side effects
- confirm alerting fires on repeated non-2xx responses
-->

After creating a subscription:

1. Send a test delivery from the dashboard or API.
2. Confirm your receiver logs the delivery ID and event type.
3. Confirm invalid signatures are rejected.
4. Confirm duplicate delivery IDs do not duplicate side effects.
5. Confirm your alerting fires if the endpoint returns repeated non-`2xx`
   responses.

## API surface

| Route | Purpose |
|---|---|
| `GET /api/v1/webhooks` | List subscriptions |
| `POST /api/v1/webhooks` | Create a subscription |
| `GET /api/v1/webhooks/{id}` | Read a subscription |
| `PUT /api/v1/webhooks/{id}` | Update URL, event types, description, or active flag |
| `DELETE /api/v1/webhooks/{id}` | Delete a subscription |
| `POST /api/v1/webhooks/{id}/test` | Send a test delivery |
| `GET /api/v1/webhooks/{id}/deliveries` | Inspect delivery history |

Use idempotency keys for subscription creation and test delivery if your client
can retry after network failures.

## Production checklist

- Receiver URL uses HTTPS.
- Receiver is dedicated to SigID events.
- Secret is stored in a secret manager.
- Signature verification uses the raw request body.
- Delivery IDs are deduplicated.
- Receiver returns `2xx` only after safe acceptance.
- Retries and failures are monitored.
- Event subscriptions are limited to the receiver's purpose.
- Logs do not contain secrets, access tokens, refresh tokens, or full payloads
  when they include sensitive data.
