Agent skill

Maxio Webhooks Skill

Receive and verify Maxio (formerly Chargify) webhooks. Use when setting up Maxio webhook handlers, debugging X-Chargify-Webhook-Signature-Hmac-Sha-256 signature verification, or handling subscription billing events like signup_success, payment_success, payment_failure, renewal_success, and subscription_state_change.

Install this skill

npx skills add hookdeck/webhook-skills --skill maxio-webhooks


When to Use This Skill

  • How do I receive Maxio (Chargify) webhooks?
  • How do I verify the X-Chargify-Webhook-Signature-Hmac-Sha-256 header?
  • Why does my Maxio webhook signature verification fail?
  • How do I parse Maxio's form-encoded payload[...]=...&event=... body?
  • Handling signup_success, payment_success, payment_failure, renewal_success, subscription_state_change

How Maxio Webhooks Differ

  • The body is application/x-www-form-urlencoded, not JSON: payload[...]=...&event=....
  • The signature is the hex HMAC-SHA256 of the raw form body, keyed with the Site Shared Key used as a raw string (not decoded).
  • Verify the raw body first, then parse the form. Parsing and re-encoding changes the bytes.
  • There is no timestamp in the signature, so use idempotency to handle replays and retries.

Verification (core)

const crypto = require('crypto');

function verifyMaxio(rawBody, signatureHeader, sharedKey) {
  if (!signatureHeader || !sharedKey) return false;
  const expected = crypto.createHmac('sha256', sharedKey).update(rawBody).digest('hex');
  const provided = signatureHeader.trim().toLowerCase();
  if (provided.length !== expected.length) return false;
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(provided));
}
// Header: X-Chargify-Webhook-Signature-Hmac-Sha-256
// Docs test vector: key "123", body "payload[chargify]=testing&event=test"
//   -> 19826d51b9f866b26eda1f154de192593360f8d0bcb63df8a28540a5dcf733f1

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

Common Event Types

EventTriggered When
signup_successA customer signs up for a subscription
payment_successA payment succeeds
payment_failureA payment attempt fails
renewal_successA subscription renews
subscription_state_changeA subscription changes state
testYou send a test webhook from the Maxio UI

The event name arrives in the form field event; the data is in nested payload[...] fields. See references/overview.md.

Environment Variables

# Site Shared Key from your Maxio site webhook settings (see references/setup.md)
MAXIO_SHARED_KEY=your_site_shared_key

Local Development

npx hookdeck-cli listen 3000 maxio --path /webhooks/maxio

No account required: the CLI creates a guest account and gives you a tunnel and web UI.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 2, 2026

View on GitHub →