← API Documentation

Webhooks

Receive real-time notifications when events occur. Every delivery is signed with HMAC-SHA256 and retried automatically on failure.

Event Types

Event Trigger
case.createdNew verification case submitted
case.closedAll verification steps completed
case.failedVerification failed (e.g. ID check rejected)
case.expired48-hour verification window elapsed
verification.step_completedIndividual verification step passed
pingManual test from console or API

Event Envelope

{
  "id": "evt_a1b2c3d4-5678-...",
  "type": "case.closed",
  "created_at": "2026-03-23T14:30:00Z",
  "data": {
    "case_id": "550e8400-e29b-...",
    "public_id": "a1b2c3d4",
    "subject_email": "[email protected]",
    "status": "closed",
    "created_at": "2026-03-23T12:00:00Z"
  }
}

Delivery Headers

Content-Type: application/json
X-AuthDuty-Signature: sha256=5d7b553b2...
X-AuthDuty-Event: case.closed
X-AuthDuty-Delivery: d4e5f6a7-8901-...
User-Agent: AuthDuty-Webhook/1.0

Retry Schedule

Failed deliveries are retried with exponential backoff up to 8 attempts:

#1

30s

#2

2m

#3

15m

#4

1h

#5

4h

#6

12h

#7

24h

#8

Dead

Delivery Statuses

Status Description
pendingDelivery queued or awaiting retry
successEndpoint returned 2xx response
failedLatest attempt failed; retries remain
dead_letterAll 8 attempts exhausted
pending success | failed dead_letter

Auto-Disable

After 15 consecutive delivery failures, an endpoint is automatically disabled. The disabled_at field is set and your team is notified by email.

One successful delivery resets the failure counter. Only consecutive failures trigger auto-disable.

Re-enabling a Disabled Endpoint

Send a PATCH request with is_active: true to reset the failure counter and clear disabled_at:

curl -X PATCH https://api.authduty.com/v1/webhooks/endpoints/{id}/ \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"is_active": true}'

Secret Rotation

Use POST /v1/webhooks/endpoints/{id}/rotate-secret/ to generate a new signing secret. The new secret is returned once in the response - store it securely.

curl -X POST https://api.authduty.com/v1/webhooks/endpoints/{id}/rotate-secret/ \
  -H "Authorization: Bearer $API_KEY"
Rollover strategy: After rotating, accept signatures from both old and new secrets during a transition window. Existing in-flight deliveries are signed with the old secret.

Verifying Webhook Signatures

Every webhook delivery includes an X-AuthDuty-Signature header containing an HMAC-SHA256 hex digest of the raw request body, signed with your endpoint's secret. Always verify this signature before processing the event.

import hashlib
import hmac

def verify_signature(payload_body: bytes, secret: str, signature_header: str) -> bool:
    """Verify the X-AuthDuty-Signature header."""
    expected = "sha256=" + hmac.new(
        secret.encode(), payload_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)