Skip to main content
Payloads are signed using asymmetric (public-key) cryptography to guarantee the authenticity of delivered callbacks. Each callback delivery request includes an X-Signature header field. This field contains a base64-encoded RSA PKCS#1 v1.5 signature of the SHA-256 digest of the request body buffer. You can obtain the public key for Webhook authentication from Webhook.public_key of the corresponding Webhook. You can obtain the public key for success callback authentication from GET /public_key/.
GET /public_key/ returns the PEM as a JSON-encoded string — the response body is "-----BEGIN PUBLIC KEY-----..." (with surrounding quotes), not a bare PEM body and not a {"key": ...} object. You must json_decode the response body before passing it to your crypto library. Passing the raw body (quotes included) to openssl_verify / crypto.createVerify fails with “Supplied key param cannot be coerced into a public key”.
Please note that CHIP is not responsible for any financial losses incurred as a result of failing to implement payload signature verification.

How to verify

The verification process is:
  1. Read the raw request body (before JSON parsing). The signature is computed over the bytes as received.
  2. Decode the X-Signature header from base64.
  3. Verify it against the request body using the public key with RSA PKCS#1 v1.5 padding and a SHA-256 digest.
  4. Reject the request if verification fails.
Always verify the raw request body. Re-serializing the parsed JSON will change byte ordering or whitespace and break the signature.

Fetching the public key

GET /public_key/ returns a JSON-encoded PEM string. Decode it before use:

Example (Node.js)

Example (PHP)

Example (Python)