Skip to content
Development
Skill

/api-messaging-webhooks

Webhook patterns — receiving, sending, signature verification, and retry logic

From plugin
skills
26200 skills

Claude Code

$ npx -y skills add agents-inc/skills --skill api-messaging-webhooks --agent claude-code

SKILL.md

api-messaging-webhooks.SKILL.md
name: api-messaging-webhooks
description: Webhook patterns — receiving, sending, signature verification, and retry logic

Webhook Patterns

> **Quick Guide:** Verify signatures with HMAC-SHA256 using `crypto.createHmac` + `crypto.timingSafeEqual` on the **raw body bytes** -- never parsed JSON. Enforce idempotency by storing processed webhook IDs. Protect against replay attacks with timestamp validation. Return 200 immediately, process asynchronously. When sending, use exponential backoff with jitter and move exhausted retries to a dead letter queue.

---

<critical_requirements>

CRITICAL: Before Using This Skill

**(You MUST verify signatures against the RAW request body -- never parsed/re-serialized JSON)**

**(You MUST use `crypto.timingSafeEqual` for signature comparison -- never `===` which leaks timing information)**

**(You MUST return 2xx immediately and process webhooks asynchronously -- synchronous processing causes timeouts and duplicate deliveries)**

**(You MUST enforce idempotency by checking a stored webhook ID before processing -- retries WILL send the same event multiple times)**

</critical_requirements>

---

**Auto-detection:** webhook, webhooks, HMAC, signature verification, createHmac, timingSafeEqual, webhook-signature, webhook-id, webhook-timestamp, idempotency key, replay attack, exponential backoff, dead letter queue, event routing, webhook handler, webhook endpoint, webhook delivery, webhook retry

**When to use:**

  • Receiving webhooks from external providers (payment processors, version control, messaging platforms)
  • Building a webhook-sending system to notify external consumers of events
  • Implementing signature verification for incoming webhook payloads
  • Adding retry logic with exponential backoff for outbound webhook delivery
  • Routing webhook events to type-safe handlers by event type

**When NOT to use:**

  • Real-time bidirectional communication (use WebSockets or Server-Sent Events)
  • Internal service-to-service communication where both sides are trusted and co-deployed
  • Simple polling scenarios where the consumer controls the fetch timing

**Key patterns covered:**

  • HMAC-SHA256 signature verification with timing-safe comparison
  • Replay attack protection with timestamp validation
  • Idempotency via stored webhook IDs with TTL
  • Type-safe event routing with discriminated unions
  • Outbound webhook delivery with exponential backoff and jitter
  • Dead letter queues for exhausted retries
  • Raw body handling to preserve signature integrity

**Detailed Resources:**

  • [examples/core.md](examples/core.md) - Receiving, signature verification, idempotency, event routing
  • [examples/sending.md](examples/sending.md) - Sending webhooks, retry logic, delivery tracking
  • [reference.md](reference.md) - Decision frameworks, header conventions, status code handling

---

<philosophy>

Philosophy

Webhooks are HTTP callbacks -- a producer POSTs a payload to a consumer's URL when an event occurs. The fundamental challenge is **trust and reliability**: the consumer must verify the payload is authentic (signature verification), not replayed (timestamp validation), and not processed twice (idempotency). The producer must handle delivery failures gracefully (retries with backoff) and not lose events permanently (dead letter queues).

**Core security principle:** The signature is computed over the exact bytes transmitted. Any transformation -- JSON parsing, re-serialization, whitespace normalization -- invalidates the signature. Always verify against the raw body.

**Core reliability principle:** Networks are unreliable. The consumer should acknowledge receipt immediately (return 2xx) and process asynchronously. The producer should retry with exponential backoff and eventually move to a dead letter queue.

**When to implement webhooks:**

  • Notifying external systems of events in near-real-time
  • Replacing polling for event-driven integrations
  • Building platform APIs that external developers consume

**When NOT to implement webhooks:**

  • When polling is simpler and latency requirements are relaxed (minutes, not seconds)
  • For internal pub/sub where a message broker is more appropriate
  • When the consumer cannot expose a public HTTP endpoint

</philosophy>

---

<patterns>

Core Patterns

Pattern 1: HMAC-SHA256 Signature Verification

The foundation of webhook security. The producer signs the payload with a shared secret; the consumer recomputes the signature and compares using timing-safe equality.

import { createHmac, timingSafeEqual } from "node:crypto";

const SIGNATURE_ALGORITHM = "sha256";
const SIGNATURE_ENCODING = "hex";

function verifySignature(
  rawBody: string,
  signature: string,
  secret: string,
): boolean {
  const expected = createHmac(SIGNATURE_ALGORITHM, secret)
    .update(rawBody)
    .digest(SIGNATURE_ENCODING);

  const expectedBuffer = Buffer.from(expected, "utf8");
  const receivedBuffer = Buffer.from(signature, "utf8");

  if (expectedBuffer.length !== receivedBuffer.length) return false;

  return timingSafeEqual(expectedBuffer, receivedBuffer);
}

**Why good:** uses `timingSafeEqual` to prevent timing attacks, operates on raw body bytes, length check before comparison prevents `timingSafeEqual` throwing on mismatched lengths

See [examples/core.md](examples/core.md) for the full handler with raw body extraction and error responses.

---

Pattern 2: Replay Attack Protection

Timestamp validation prevents attackers from re-sending captured webhook payloads. Reject payloads older than a tolerance window.

const MAX_TIMESTAMP_AGE_SECONDS = 300; // 5 minutes
const MS_PER_SECOND = 1000;

function isTimestampValid(timestampHeader: string): boolean {
  const webhookTime = parseInt(timestampHeader, 10);
  if (Number.isNaN(webhookTime)) return false;

  const currentTime = Math.floor(Date.now() / MS_PER_SECOND);
  return Math.abs(currentTime - webhookTime) <= MAX_TIMESTAMP_AGE_SECONDS;
}

*

Read more
@agents-inc
Ships withskills

The official skills marketplace for Agents Inc. 230+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Stars on GitHub

Momentum

stars in total
26
Star history of agents-inc/skills on GitHub, a chart by star-history.com

Other skills on skills.

ai-infrastructure-litellm

ai-infrastructure-lite…

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…

@agents-inc@agents-incInstall Skill
ai-infrastructure-modal

ai-infrastructure-moda…

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…

@agents-inc@agents-incInstall Skill
ai-infrastructure-ollama

ai-infrastructure-olla…

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…

@agents-inc@agents-incInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about api-messaging-webhooks.

Which coding agents can use api-messaging-webhooks?
api-messaging-webhooks installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.