Skip to main content

Webhooks API

This reference covers the REST API for managing webhook subscriptions. For setup, security verification, and retry handling patterns, see the Webhook Integration Guide.

Base URL

https://cronozen.com/api/v1/webhooks
All endpoints require a Bearer API key in the Authorization header.

Event Types

Subscribe to one or more event types when registering a webhook. Events are namespaced by domain.
EventWhen It Fires
dpu.sealedA new Decision Proof Unit is sealed and committed to the chain
dpu.verifiedAn external verification request was processed
agent.decision.completedAn agent finished a decision (autonomous or after approval)
agent.approval.requestedAn agent is waiting on human approval
payment.completedA payment was confirmed and reconciled
payment.failedA payment attempt failed terminally
attendance.verifiedA QR check-in or workshop attendance was confirmed
certificate.issuedA digital certificate (with DPU proof) was issued to a learner
workflow.transitionedA workflow instance moved between states
Wildcard * is supported (e.g., payment.*) but not recommended in production — explicit lists make consumer behavior clearer.

Endpoints

Register Webhook

POST /api/v1/webhooks
Body
{
  "url": "https://your-app.example.com/webhooks/cronozen",
  "events": ["dpu.sealed", "payment.completed"],
  "description": "Production listener",
  "active": true
}
Response 201
{
  "id": "wh_a7f3d8",
  "url": "https://your-app.example.com/webhooks/cronozen",
  "events": ["dpu.sealed", "payment.completed"],
  "active": true,
  "signingSecret": "whsec_e3a9b2c1d4f5...",
  "createdAt": "2026-05-28T03:14:00Z"
}
signingSecret is returned only at registration. Store it securely. If lost, use POST /webhooks/{id}/rotate-secret to generate a new one (and update your consumer).

List Webhooks

GET /api/v1/webhooks
Response 200
{
  "data": [
    {
      "id": "wh_a7f3d8",
      "url": "https://your-app.example.com/webhooks/cronozen",
      "events": ["dpu.sealed", "payment.completed"],
      "active": true,
      "lastDeliveryAt": "2026-05-28T03:13:55Z",
      "lastDeliveryStatus": "success",
      "createdAt": "2026-05-28T03:14:00Z"
    }
  ]
}

Update Webhook

PATCH /api/v1/webhooks/{webhookId}
Body (any subset of fields)
{
  "events": ["dpu.sealed", "agent.approval.requested"],
  "active": false
}

Delete Webhook

DELETE /api/v1/webhooks/{webhookId}

Rotate Signing Secret

POST /api/v1/webhooks/{webhookId}/rotate-secret
Response 200
{
  "id": "wh_a7f3d8",
  "signingSecret": "whsec_newkey..."
}
After rotation, both the old and new secrets are valid for 24 hours to allow zero-downtime rollover. Update your consumer to verify against the new secret, then the old secret is invalidated.

Retry a Failed Event

POST /api/v1/webhooks/events/{eventId}/retry
Re-attempts delivery immediately. Returns the same retry semantics as the original delivery (exponential backoff for subsequent failures).

List Recent Deliveries

GET /api/v1/webhooks/{webhookId}/deliveries?limit=50
Response 200
{
  "data": [
    {
      "eventId": "evt_8x2k",
      "eventType": "dpu.sealed",
      "deliveredAt": "2026-05-28T03:13:55Z",
      "status": "success",
      "responseStatus": 200,
      "attempts": 1
    },
    {
      "eventId": "evt_7y1j",
      "eventType": "payment.completed",
      "deliveredAt": "2026-05-28T02:50:12Z",
      "status": "failed",
      "responseStatus": 502,
      "attempts": 7,
      "nextRetryAt": null
    }
  ]
}

Event Payload Shape

Every webhook POST to your endpoint follows this envelope:
{
  "id": "evt_8x2k",
  "type": "dpu.sealed",
  "createdAt": "2026-05-28T03:13:54Z",
  "data": {
    "dpuId": "dpu_a7f3d8e2",
    "chainHash": "a7f3d8e2c1...b4f9",
    "domain": "grant-review",
    "actorId": "user_x9y2"
  },
  "deliveryAttempt": 1
}

Headers

HeaderDescription
X-Cronozen-SignatureHMAC-SHA256 hex of the raw request body, signed with the webhook’s signingSecret
X-Cronozen-Event-IdSame as data.id — use for idempotency
X-Cronozen-Delivery-Attempt1 for first attempt, increments on retry
X-Cronozen-TimestampServer-side dispatch time (ISO-8601 UTC)
Content-Typeapplication/json
Always verify X-Cronozen-Signature before processing — see the verification example.

Rate Limits

Webhook outbound delivery from Cronozen has no per-endpoint rate limit, but high-frequency endpoints may queue. If your endpoint cannot keep up with a burst, return 429 Retry-After — Cronozen respects this header. Webhook management API calls follow standard API rate limits (see API Overview).

See Also