Agent skill

Chili Piper Webhooks Skill

Receive and verify Chili Piper webhooks. Use when setting up Chili Piper custom webhook handlers for booked meetings, verifying the X-Chili-Signature and X-Chili-Timestamp headers (hex HMAC-SHA256 of timestamp.body), debugging signature verification failures, or handling Created, Updated and Deleted meeting events.

Install this skill

npx skills add hookdeck/webhook-skills --skill chili-piper-webhooks


When to Use This Skill

  • How do I receive Chili Piper webhooks?
  • How do I verify the Chili Piper X-Chili-Signature header?
  • Why does my Chili Piper webhook signature verification fail?
  • How do I handle Chili Piper meeting Created, Updated and Deleted events?
  • How do I get my Chili Piper webhook signing secret?

Get the Signing Secret

Chili Piper issues the signing secret on request: email Chili Piper support for your tenant's secret and paste it here.

The secret is not shown in the Command Center. Create and enable the webhook first, then email support@chilipiper.com with your tenant (instance) name and the webhook you created. Store it as CHILI_PIPER_WEBHOOK_SECRET. See references/setup.md.

Verification (core)

Every request carries X-Chili-Signature (lowercase hex HMAC-SHA256, no prefix) and X-Chili-Timestamp (Unix seconds). The signed message is the timestamp header value, a literal ., then the raw request body bytes. The key is the secret's UTF-8 bytes, used as-is (not hex- or base64-decoded).

const crypto = require('crypto');

function verifyChiliPiper(rawBody, signature, timestamp, secret) {
  if (!signature || !timestamp || !secret) return false;
  if (!/^[0-9a-fA-F]{64}$/.test(signature)) return false; // validate before decoding
  const signed = Buffer.concat([Buffer.from(timestamp, 'latin1'), Buffer.from('.'), rawBody]);
  const expected = crypto.createHmac('sha256', secret).update(signed).digest();
  return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), expected);
}

Build the signed message as bytes: never decode the body to a string and re-encode it, and never JSON.parse/JSON.stringify before verifying. Reject a missing, empty or malformed signature or timestamp, and a mismatch, with 401.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Timestamp Tolerance (opt-in)

Do not reject old timestamps by default. Hookdeck retries and replays resend the original headers and timestamp, and Hookdeck applies no tolerance itself, so a fixed window would reject legitimate retries. The examples check X-Chili-Timestamp against the clock only when CHILI_PIPER_WEBHOOK_TOLERANCE_SECONDS is set above 0 (unset or 0 = off). Chili Piper's own example uses 300 seconds.

Event Types

Chili Piper sends one webhook per action type, selected when you create the webhook in the Command Center. The body's type field carries the event name. Dispatch on it.

typeWebhook typeTriggered when
CreatedFor New MeetingA meeting is booked, from any source
UpdatedFor Meeting UpdateA meeting is updated, for example reassigned or rescheduled
DeletedFor Canceled MeetingA user or prospect cancels the meeting

Important Headers and Behavior

ItemValue
X-Chili-SignatureLowercase hex HMAC-SHA256 digest (64 characters), compared as a whole value
X-Chili-TimestampUnix timestamp in seconds when the request was signed
Method / bodyPOST with a JSON body. Read the raw body whatever the content type
RetriesNot documented. De-duplicate on meetingIdChili plus type

Environment Variables

CHILI_PIPER_WEBHOOK_SECRET=your_webhook_signing_secret   # issued by Chili Piper support
CHILI_PIPER_WEBHOOK_TOLERANCE_SECONDS=0                  # optional, 0 or unset disables the replay check

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 chili-piper --path /webhooks/chili-piper

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 10, 2026

View on GitHub →