Skip to main content
API Preview
Developers

Webhooks

Receive real-time event notifications the moment a credential attestation is issued or revoked. Webhooks integrate ~alter into your event pipeline, a downstream service, or a custom workflow without polling.

Subscription management

Use the following endpoints to create, update, list, and delete webhook subscriptions. All endpoints require JWT authentication with the org_admin role.

MethodPathAuth
POST/webhooks/

Register a webhook

jwt
GET/webhooks/

List webhook subscriptions

jwt
GET/webhooks/{subscription_id}

Get webhook details

jwt
PATCH/webhooks/{subscription_id}

Update a webhook

jwt
DELETE/webhooks/{subscription_id}

Delete a webhook

jwt
GET/webhooks/{subscription_id}/deliveries

List webhook deliveries

jwt
POST/webhooks/{subscription_id}/test

Send test webhook

jwt
GET/webhooks/events

List supported event types

jwt

Event types

Subscribe to any combination of the following event types when registering a webhook. Events marked Live emit today; those marked Planned can be registered now and will emit as the matching surface ships.

EventDescriptionStatus
attestation.issuedA verifiable credential has been issued against an identityLive
attestation.revokedA previously issued credential has been revokedLive
match.proposedA match has been proposed between an identity and a collectivePlanned
match.acceptedA proposed match has been acceptedPlanned
match.declinedA proposed match has been declinedPlanned
placement.createdA new placement record has been createdPlanned
placement.updatedAn existing placement record has changed statePlanned

Delivery format

Webhook events are delivered as POST requests to your registered HTTPS endpoint. Each delivery includes three custom headers for verification and deduplication:

HeaderDescription
X-Alter-SignatureHMAC-SHA256 signature over the canonical JSON serialisation of the payload (sorted keys, compact separators) using your webhook secret
X-Alter-DeliveryUnique delivery UUID for idempotency and deduplication
X-Alter-EventThe event type (e.g. attestation.issued)

Example payload

A typical attestation.issued webhook delivery:

POST /webhooks/alter HTTP/1.1
Host: ats.example.com
Content-Type: application/json
X-Alter-Event: attestation.issued
X-Alter-Delivery: d4e5f6a7-b8c9-0123-4567-890abcdef012
X-Alter-Signature: sha256=a1b2c3d4e5f6...

Signature verification

Always verify the X-Alter-Signature header to confirm the request originated from ~alter. The signature is an HMAC-SHA256 over the canonical JSON serialisation of the payload (sorted keys, compact separators), signed with the webhook secret you received when creating the subscription. Parse the request body and re-serialise it canonically before computing the HMAC.

import hmac
import hashlib
import json

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    """Verify ~alter webhook signature."""
    # Re-serialise canonically: sorted keys, compact separators
    canonical = json.dumps(
        json.loads(payload),
        separators=(",", ":"),
        sort_keys=True,
    )
    expected = hmac.new(
        secret.encode("utf-8"),
        canonical.encode("utf-8"),
        hashlib.sha256
    ).hexdigest()

    received = signature.removeprefix("sha256=")
    return hmac.compare_digest(expected, received)

# In your webhook handler:
is_valid = verify_webhook(
    payload=request.body,
    signature=request.headers["X-Alter-Signature"],
    secret="whsec_your_webhook_secret"  # pragma: allowlist secret
)
if not is_valid:
    return Response(status_code=401)

Retry policy

If your endpoint returns a non-2xx status code or fails to respond within 30 seconds, ~alter retries the delivery with exponential backoff:

AttemptDelayNotes
1st retry1 minuteAfter initial failure
2nd retry5 minutesExponential backoff
3rd retry15 minutesExponential backoff
4th retry1 hourExponential backoff
5th retry2 hoursFinal attempt

After five failed attempts, the delivery is marked as failed. A subscription that records ten consecutive failures is automatically deactivated; re-enable it once your endpoint is healthy again. Use the GET /webhooks/{subscription_id}/deliveries endpoint to inspect delivery history and diagnose failures.

Best practices

  • Always verify signatures. Never process a webhook without validating the X-Alter-Signature header.
  • Respond quickly. Return a 2xx within 10 seconds (the server allows 30 seconds; 10 is a reliability target). Queue heavy processing for async execution.
  • Handle duplicates. Use the X-Alter-Delivery header for idempotency. Retries may deliver the same event multiple times.
  • Use the test endpoint. Send a synthetic event via POST /webhooks/{id}/test to verify your handler before going live.
Docs | ~alter