Agent skill

FastSpring Webhooks Skill

Receive and verify FastSpring webhooks. Use when setting up FastSpring webhook handlers, debugging X-FS-Signature verification, or handling ecommerce events like order.completed, subscription.activated, subscription.charge.completed, and subscription.canceled.

Install this skill

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


When to Use This Skill

  • Setting up FastSpring webhook handlers
  • How do I verify FastSpring webhook signatures?
  • Why is my X-FS-Signature verification failing?
  • Handling order.completed, subscription.activated, or subscription.charge.completed events
  • Iterating the batched events array FastSpring delivers in each POST

Verification (core)

FastSpring signs the exact raw request body with HMAC-SHA256 keyed on your per-webhook HMAC SHA256 Secret, base64-encodes the digest, and sends it in the X-FS-Signature header. Pass the raw body (do not parse/re-serialize first), recompute, and compare timing-safe. Each POST batches multiple events in an events array — verify the signature once against the whole body, then iterate.

Note: Signing is only active when the HMAC secret is set on the webhook. If no secret is configured, no X-FS-Signature header is sent.

Node:

const crypto = require('crypto');

function verify(rawBody, signatureHeader, secret) {
  if (!signatureHeader) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
  try {
    return crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
  } catch {
    return false;
  }
}

Python:

import hmac, hashlib, base64

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    if not signature_header:
        return False
    expected = base64.b64encode(
        hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
    ).decode()
    return hmac.compare_digest(signature_header, expected)

After verifying, iterate payload.events and dispatch on each event.type. Dedupe on event.id — automatic retries reuse the same id (manual retries get new ids). FastSpring auto-retries over HTTPS until your endpoint returns HTTP 200.

For complete handlers with route wiring, batch iteration, event dispatch, and tests, see:

Common Event Types

EventTriggered When
order.completedAn order is successfully completed
order.failedAn order fails
order.canceledAn order is canceled
subscription.activatedA new subscription is activated
subscription.charge.completedA recurring subscription charge succeeds
subscription.charge.failedA recurring subscription charge fails
subscription.updatedA subscription is updated
subscription.canceledA subscription is canceled
subscription.deactivatedA subscription is deactivated
return.createdA return/refund is created

For the full event reference, see FastSpring Webhooks.

Environment Variables

FASTSPRING_WEBHOOK_SECRET=your_hmac_sha256_secret   # From Dashboard → Developer Tools → Webhooks → Configuration

Local Development

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

Optionally allowlist FastSpring's source IP 107.23.30.83.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Aug 4, 2026

View on GitHub →