Skip to main content

Webhook Headers & Verification

Every webhook delivery is an HTTP POST with a JSON body and three relevant headers.

HTTP headers

Example:

Get the public key

Use GET /v1/webhooks-keys to list public keys. Use the key with is_active: true. Cache the key for up to 24 hours and refresh periodically.

Verification process

Step 1: Validate timestamp

Reject deliveries with timestamps outside a 5-minute window from current time (replay protection).

Step 2: Reconstruct the signed message

PoP format (same pattern as API authentication, with a different uri component):

Step 3: Verify the signature

  1. Compute SHA-256 of the UTF-8 message bytes
  2. Decode x-kiwify-digital-signature from base64url (no padding)
  3. Verify with EdDSA-Ed25519 using the active public key
Webhook signatures use Ed25519 prehashed mode (SHA-256 of the message before verification). This differs from generic Ed25519 examples that sign the message directly.

Example (Python)

Common mistakes

  • Using the full URL instead of only the path in the signed message
  • Re-serializing JSON (whitespace/key order changes the signature)
  • Verifying Ed25519 directly on the message without SHA-256 prehash