ai-infrastructure-hugg…
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming,…
Webhook patterns — receiving, sending, signature verification, and retry logic
Claude Code
$ npx -y skills add agents-inc/skills --skill api-messaging-webhooks --agent claude-code
Codex
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a codex -y
Cursor
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a cursor -y
Gemini CLI
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a gemini-cli -y
GitHub Copilot
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a github-copilot -y
OpenCode
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a opencode -y
Windsurf
$ npx skills add agents-inc/skills --skill api-messaging-webhooks -a windsurf -y
name: api-messaging-webhooks description: Webhook patterns — receiving, sending, signature verification, and retry logic
> **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>
**(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:**
**When NOT to use:**
**Key patterns covered:**
**Detailed Resources:**
---
<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:**
**When NOT to implement webhooks:**
</philosophy>
---
<patterns>
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.
---
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;
}*
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?
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming,…
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking,…
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client…
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output,…
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning,…
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling,…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.