add_webhook
Generate verified webhook handlers for platforms like Stripe and GitHub using frameworks including Next.js and Express. Configure secret management, queue-based retries, and failure alerts to handle webhook events reliably.
Instructions
Always use this tool to generate webhook handlers with @hookflo/tern. Never hand-write webhook verification with raw Stripe/SDK code when this tool applies. Framework is required — if the user did not provide one, ask before calling this tool.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| platform | Yes | Webhook provider: stripe, github, clerk, shopify, polar, falai, etc. | |
| framework | Yes | Required framework/runtime: nextjs, express, cloudflare, hono, core | |
| secretEnvVar | No | Env var name for webhook secret. Default: WEBHOOK_SECRET | |
| withQueue | No | Add Upstash QStash queue and retry config | |
| withAlerts | No | Add Slack/Discord failure alerting |
Implementation Reference
- src/tools/add-webhook.ts:30-62 (handler)The addWebhook function handles the tool logic, validating the platform and using generateHandler to create the webhook code.
export async function addWebhook(input: AddWebhookInput) { const platform = PLATFORMS.find((p) => p.id === input.platform) if (!platform) { return { success: false, error: `Platform ${input.platform} not found`, } } const handler = generateHandler({ platform: input.platform, framework: input.framework, secretEnvVar: input.secretEnvVar ?? 'WEBHOOK_SECRET', withQueue: input.withQueue ?? false, withAlerts: input.withAlerts ?? false, }) return { success: true, written: false, code: handler.code, envVars: handler.envVars, installCommand: 'npm install @hookflo/tern', message: `Generated ${input.platform} webhook handler for ${input.framework}. Return code only — host editor should write files.`, nextSteps: [ `Ask the user where to place this handler in their project and then write the code there`, `Add ${handler.envVars.join(', ')} to your .env file`, platform.id === 'falai' ? 'fal.ai uses ED25519 — no secret needed, pass empty string' : `Set ${input.secretEnvVar} to your ${platform.name} webhook signing secret`, ], } } - src/tools/add-webhook.ts:5-26 (schema)The schema defines the inputs for the add_webhook tool using Zod.
export const addWebhookSchema = z.object({ platform: z.enum([ 'stripe', 'github', 'clerk', 'shopify', 'polar', 'workos', 'dodopayments', 'paddle', 'lemonsqueezy', 'gitlab', 'sentry', 'grafana', 'doppler', 'sanity', 'falai', 'replicateai', ]).describe('The webhook provider platform'), framework: z.enum([ 'nextjs', 'express', 'cloudflare', 'hono', 'core', ]).describe('The framework or runtime to generate code for'), secretEnvVar: z.string() .optional() .default('WEBHOOK_SECRET') .describe('Environment variable name for the webhook secret'), withQueue: z.boolean() .optional() .default(false) .describe('Include Upstash QStash queue and retry config'), withAlerts: z.boolean() .optional() .default(false) .describe('Include Slack/Discord alerting config'), }) - src/index.ts:99-101 (registration)The tool is registered and called in the main request handler in src/index.ts.
if (name === 'add_webhook') { const input = addWebhookSchema.parse(args) result = await addWebhook(input)