Channex Webhook Signing Keys API
HMAC keys that sign webhook deliveries, so that a receiving endpoint can tell that a callback came from Channex and that its body was not altered on the way. A key is a shared secret: Channex holds it and so do you. It is not an API credential — it authenticates nothing against this API and grants no access. It is used in one direction only, on the callbacks Channex sends to you. A key belongs to a billing account and holds up to two secret versions — the current one plus an optional pending one, which is what makes rotation zero-downtime. To turn signing on, point a webhook at the key with `signing_key_id` and set `is_signed`. ## What is signed Every delivery of a signed webhook — the `POST` Channex makes to the webhook's `callback_url` — carries three headers: - `x-hmac-timestamp` — Unix timestamp (seconds) taken when the delivery was signed. - `x-hmac-signature-256` — comma-separated lowercase-hex HMAC-SHA256 signatures, one per secret version of the key, the current version first. - `x-hmac-keys-256` — comma-separated version labels (`...` followed by each secret's last 6 characters), in the same order as the signatures. Each signature is computed over the string `{timestamp}.{raw request body}`: the value of `x-hmac-timestamp`, a dot, and the exact bytes of that delivery's body. Nothing else enters it — neither the callback URL nor the webhook's `request_params` and `headers`. ## Verifying a delivery Recompute HMAC-SHA256 over `{timestamp}.{raw body}` with your stored secret, then compare it against the signature at the position whose label in `x-hmac-keys-256` ends with your secret's last 6 characters. ## Rotating a key `generate` adds a pending secret version beside the current one, and deliveries are then signed with both — so verification against the current secret keeps working while the new secret is stored on your side. `rotate` promotes the newest version to be the sole current version, after which deliveries carry its signature alone.