# AffixIO webhooks Canonical page: https://www.affix-io.com/webhooks/ Management UI: https://hub.affix-io.com/webhooks/ API base: https://api.affix-io.com Connection surfaces index: https://www.affix-io.com/connections/ Site brief: https://www.affix-io.com/llms.txt AffixIO posts a signed JSON document to an HTTPS endpoint you control when a proof is created, verified or spent, when a leaf is appended to the Merkle audit tree, or when an API key is revoked. ## Events - `proof.created` - proof generated and anchored. Data: `digest`, `circuit_id`, `proof_id`, `merkle_root`, `merkle_leaf_hash`. - `proof.verified` - verification completed and the outcome signed. Same data fields. - `proof.spent` - digest consumed, single use enforced. Same data fields. - `merkle.leaf_appended` - leaf appended to the audit tree. Data: `digest`, `circuit_id`, `proof_id`, `audit_event`, `leaf_hash`, `merkle_index`, `merkle_root`. - `key.revoked` - API key revoked. Data: `key_id`, `label`. An endpoint must subscribe to at least one event. Unknown event names are rejected at registration. ## Envelope ``` {"delivery_id": "dlv_<24 hex>", "event": "", "created_at": "", "data": { ... }} ``` Headers: `X-Affix-Event`, `X-Affix-Timestamp` (unix seconds), `X-Affix-Delivery-Id`, `X-Affix-Signature`, `Content-Type: application/json`, `User-Agent: AffixIO-Webhooks/1.0`. ## Signature `X-Affix-Signature: hmac-sha256=` where the digest is `HMAC-SHA256(key = endpoint secret, message = "{timestamp}.{raw_body}")`. Verification order: check `X-Affix-Timestamp` is within 300 seconds of local time, recompute the MAC over the raw request bytes, compare in constant time, deduplicate on `X-Affix-Delivery-Id`, return 2xx. Secrets are issued once at registration in the form `whsec_` plus 48 hex characters. Rotation invalidates the previous secret immediately and keeps the endpoint id. ## Delivery behaviour - Three attempts per event, short growing pause between them, eight second timeout per attempt. - Any 2xx counts as success. The response body is ignored. - The same `X-Affix-Delivery-Id` is used for all attempts of one event. - After three failures the event is dropped. There is no dead letter queue. - Ordering is not guaranteed. One verification emits both `proof.verified` and `merkle.leaf_appended`. - Endpoints are never disabled automatically. Failure counts are recorded and the endpoint stays active until paused. - Receiver URLs must be HTTPS. ## Management API Authenticate with a Hub session or `Authorization: Bearer ` / `X-API-Key: `. - `GET /api/webhooks` - list endpoints, masked secrets, last delivery status, failure count. - `POST /api/webhooks` - body `{label, url, events[]}`. Returns the signing secret once. - `PATCH /api/webhooks/{id}` - update `label`, `url`, `events` or `active`. - `DELETE /api/webhooks/{id}` - remove the endpoint. - `POST /api/webhooks/{id}/rotate-secret` - new secret, previous one invalidated. Scope: an endpoint created from a Hub session receives events triggered by any key on that account. An endpoint created with an API key alone receives events triggered by that key. ## Limits - No dead letter queue and no delivery history API. Use https://www.affix-io.com/siem/ for a complete record. - Payloads are signed, not encrypted beyond TLS. - Filtering is per event type. Filtering by `circuit_id` happens in receiver code. - Payloads contain digests, identifiers and hashes only. No personal data. Last updated: 2026-08-14