Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
joelhooks avatar

Webhooks

  • 31 installs
  • 61 repo stars
  • Updated August 4, 2026
  • joelhooks/joelclaw

Add and debug webhook providers in the joelclaw gateway, handling signature verification, payload normalization, and Inngest event routing.

About

Adds, debugs, and manages webhook providers in the joelclaw webhook gateway. A developer uses it to integrate a new webhook, debug signature failures, or verify delivery from external services.

  • WebhookProvider interface with signature verification and payload normalization per provider
  • Existing todoist/front/vercel/github providers plus an 8-step new-provider checklist

Webhooks by the numbers

  • 31 all-time installs (skills.sh)
  • Ranked #3,366 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/joelhooks/joelclaw --skill webhooks

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs31
repo stars61
Last updatedAugust 4, 2026
Repositoryjoelhooks/joelclaw

What it does

Add and debug webhook providers in the joelclaw gateway, handling signature verification, payload normalization, and Inngest event routing.

Files

SKILL.mdMarkdownGitHub ↗

Webhook Gateway Operations

Manage the joelclaw webhook gateway — add providers, debug delivery, register with external services.

Architecture

External Service → Tailscale Funnel :443 → Worker :3111 → /webhooks/:provider
  → verifySignature() → normalizePayload() → (queue pilot or direct Inngest event) → notify function → gateway
  • ADR-0048: Webhook Gateway for External Service Integration
  • Gateway skill: Use gateway push/gateway test patterns for delivery checks

Current Providers

ProviderEventsSignatureFunnel URL
todoistcomment.added, task.completed, task.createdHMAC-SHA256 (x-todoist-hmac-sha256)https://panda.tail7af24.ts.net/webhooks/todoist
frontmessage.received, message.sent, assignee.changedHMAC-SHA1 (x-front-signature)https://panda.tail7af24.ts.net/webhooks/front
verceldeploy.succeeded, deploy.error, deploy.created, deploy.canceledHMAC-SHA1 (x-vercel-signature)https://panda.tail7af24.ts.net/webhooks/vercel
githubworkflow_run.completed, package.publishedHMAC-SHA256 (x-hub-signature-256)https://panda.tail7af24.ts.net/webhooks/github

Current ADR-0217 pilot note: when QUEUE_PILOTS=github, the webhook gateway enqueues normalized github/workflow_run.completed events into the shared Redis queue instead of posting them directly to Inngest. The Restate drainer then forwards the concrete event name github/workflow_run.completed. github/package.published still goes direct.

Adding a New Provider

See references/new-provider-checklist.md for the full 8-step checklist.

Quick summary: 1. Create providers/{name}.ts implementing WebhookProvider interface 2. Register in server.ts provider map 3. Create Inngest notify function(s) in functions/{name}-notify.ts 4. Export from functions/index.ts and add to functions/index.host.ts (or index.cluster.ts when cluster-owned) 5. Store webhook secret in agent-secrets → add lease to start.sh 6. Deploy: joelclaw inngest restart-worker --register 7. Register webhook URL with external service 8. Verify E2E with curl + real webhook

Key Files

FilePurpose
packages/system-bus/src/webhooks/types.tsWebhookProvider interface, NormalizedEvent type
packages/system-bus/src/webhooks/server.tsHono router — dispatches to providers, rate limiting
packages/system-bus/src/webhooks/providers/Provider implementations (one file per service)
packages/system-bus/src/inngest/functions/*-notify.tsGateway notification functions per provider
packages/system-bus/src/inngest/functions/index.tsFunction exports barrel
packages/system-bus/src/inngest/functions/index.host.tsHost worker function registration (current active role)
packages/system-bus/src/inngest/functions/index.cluster.tsCluster worker function registration (future/role split)
packages/system-bus/src/serve.tsWorker role selection + health endpoint + webhook provider list
~/Code/joelhooks/joelclaw/packages/system-bus/start.shSecret leasing on host worker startup

Debugging Webhooks

Check if webhook is arriving

# Watch worker logs
joelclaw logs worker --follow --grep webhook

# Or directly
curl -s http://localhost:3111/ | jq .webhooks
# → { endpoint: "/webhooks/:provider", providers: ["todoist", "front", "vercel"] }

Signature verification failures

# Test with manual HMAC (SHA1 example for Vercel)
SECRET="your-webhook-secret"
BODY='{"type":"test-webhook","payload":{}}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha1 -hmac "$SECRET" -binary | xxd -p)
curl -X POST http://localhost:3111/webhooks/vercel \
  -H "Content-Type: application/json" \
  -H "x-vercel-signature: $HMAC" \
  -d "$BODY"

Common failures:

  • Wrong secret — Todoist uses client_secret (not "Verification token"), Vercel uses the secret from webhook creation, Front uses the rules-based secret
  • Encoding mismatch — Todoist = base64, Vercel = hex, Front = base64 over compact JSON
  • Body mutation — Caddy/proxy rewrites body. Use Tailscale Funnel → worker directly
  • Rate limited — 20 auth failures per IP per minute. Wait or restart worker

Check Inngest received events

joelclaw runs --count 5
# Look for vercel-deploy-*, todoist-*, front-* function runs

Gateway not receiving notifications

joelclaw gateway status
joelclaw gateway events   # Peek pending events

Registering Webhooks with Services

Vercel (Pro/Enterprise required)

# Via Vercel dashboard: Settings → Webhooks → Create
# Or via API:
VERCEL_TOKEN="your-api-token"
curl -X POST "https://api.vercel.com/v1/webhooks" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://panda.tail7af24.ts.net/webhooks/vercel",
    "events": ["deployment.created", "deployment.succeeded", "deployment.error", "deployment.canceled"]
  }'

The response includes a secret — store it: secrets add vercel_webhook_secret --value "..."

GitHub

Set up via repo Settings → Webhooks:

  • URL: https://panda.tail7af24.ts.net/webhooks/github
  • Content type: application/json
  • Secret: generate one, store as github_webhook_secret
  • Events: push, pull_request, deployment_status, or "Send me everything"

Todoist

Already configured via Todoist App Console → Webhooks tab. Uses client_secret as HMAC key (not the "Verification token").

Front

Already configured via Front Rules → "Trigger a webhook" action. Rules webhooks scope to specific inboxes at the rule layer.

Signature Algorithms by Provider

ProviderAlgorithmEncodingHeaderSecret Source
TodoistHMAC-SHA256base64x-todoist-hmac-sha256App Console → client_secret
FrontHMAC-SHA1base64 (over compact JSON)x-front-signatureRules webhook secret
VercelHMAC-SHA1hexx-vercel-signatureWebhook creation response
GitHubHMAC-SHA256hex (prefixed sha256=)x-hub-signature-256Webhook config secret
StripeHMAC-SHA256hexstripe-signature (structured)Endpoint signing secret

Gotchas

  • Caddy drops Funnel POST bodies — Point Tailscale Funnel directly at worker :3111, not through Caddy
  • `joelclaw inngest restart-worker --register` after deploy — ensures restart + registration in one step
  • Vercel webhooks are Pro/Enterprise only — free plans cannot create account-level webhooks
  • Front has TWO webhook types — App-level (SHA256, challenges) vs Rules-based (SHA1, no challenges). We use Rules-based
  • agent-secrets v0.5.0+ — raw output is default, don't pass --raw flag
  • Idempotency keys on all events — safe to receive duplicates from retry-happy providers

Related skills

Backend & APIsintegrationsbackend

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.