Hookdrop can generate production-ready code directly from a real webhook payload. Use this to bootstrap your integration without writing boilerplate by hand.
Generate TypeScript interface
Hookdrop inspects the shape of a captured payload and returns a TypeScript interface that matches it exactly — field names, nested objects, optional fields, and all.
From the dashboard
- Open the Events tab for any endpoint.
- Click the event you want to type.
- Click Generate types in the event detail panel.
Copy the generated interface directly into your project.
Via the API
curl https://hookdrop.dev/api/endpoints/<endpointId>/events/<eventId>/ai/schema \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example response
{
"schema": "interface WebhookPayload {\n event: string;\n data: {\n id: string;\n customer: {\n id: string;\n email: string;\n };\n amount: number;\n currency: string;\n reference: string;\n status: 'success' | 'failed' | 'pending';\n paid_at: string;\n channel: string;\n card_last4: string;\n };\n}"
}
Rendered, that interface looks like this:
interface WebhookPayload {
event: string;
data: {
id: string;
customer: {
id: string;
email: string;
};
amount: number;
currency: string;
reference: string;
status: 'success' | 'failed' | 'pending';
paid_at: string;
channel: string;
card_last4: string;
};
}
The generated interface is based on a single event payload. If your webhook
provider sends events with optional fields, capture a few different event
types and merge the interfaces to get full coverage.
Generate handler code
Send a POST request with your preferred language and framework, and Hookdrop returns a complete handler function ready to paste into your project.
Supported options
| Option | Values |
|---|
language | typescript, javascript, python, go |
framework | express, fastify, nextjs, fastapi, gin |
Via the API
curl -X POST https://hookdrop.dev/api/endpoints/<endpointId>/events/<eventId>/ai/handler \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"language": "typescript", "framework": "express"}'
Request body
{
"language": "typescript",
"framework": "express"
}
Example responses
TypeScript / Express
JavaScript / Express
Python / FastAPI
Go / Gin
import { Request, Response } from 'express';
interface WebhookPayload {
event: string;
data: {
id: string;
customer: { id: string; email: string };
amount: number;
currency: string;
reference: string;
status: 'success' | 'failed' | 'pending';
paid_at: string;
channel: string;
card_last4: string;
};
}
export async function handleWebhook(req: Request, res: Response): Promise<void> {
const payload = req.body as WebhookPayload;
switch (payload.event) {
case 'charge.success':
await handleChargeSuccess(payload.data);
break;
default:
console.log(`Unhandled event type: ${payload.event}`);
}
res.status(200).json({ received: true });
}
async function handleChargeSuccess(data: WebhookPayload['data']): Promise<void> {
console.log(`Payment of ${data.amount / 100} ${data.currency} received from ${data.customer.email}`);
// TODO: fulfil the order, update your database, send a confirmation email, etc.
}
export async function handleWebhook(req, res) {
const payload = req.body;
switch (payload.event) {
case 'charge.success':
await handleChargeSuccess(payload.data);
break;
default:
console.log(`Unhandled event type: ${payload.event}`);
}
res.status(200).json({ received: true });
}
async function handleChargeSuccess(data) {
console.log(`Payment of ${data.amount / 100} ${data.currency} received from ${data.customer.email}`);
// TODO: fulfil the order, update your database, send a confirmation email, etc.
}
from fastapi import FastAPI, Request
from pydantic import BaseModel
app = FastAPI()
class Customer(BaseModel):
id: str
email: str
class EventData(BaseModel):
id: str
customer: Customer
amount: int
currency: str
reference: str
status: str
paid_at: str
channel: str
card_last4: str
class WebhookPayload(BaseModel):
event: str
data: EventData
@app.post("/webhook")
async def handle_webhook(payload: WebhookPayload):
if payload.event == "charge.success":
await handle_charge_success(payload.data)
else:
print(f"Unhandled event type: {payload.event}")
return {"received": True}
async def handle_charge_success(data: EventData):
print(f"Payment of {data.amount / 100} {data.currency} received from {data.customer.email}")
# TODO: fulfil the order, update your database, send a confirmation email, etc.
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type Customer struct {
ID string `json:"id"`
Email string `json:"email"`
}
type EventData struct {
ID string `json:"id"`
Customer Customer `json:"customer"`
Amount int `json:"amount"`
Currency string `json:"currency"`
Reference string `json:"reference"`
Status string `json:"status"`
PaidAt string `json:"paid_at"`
Channel string `json:"channel"`
CardLast4 string `json:"card_last4"`
}
type WebhookPayload struct {
Event string `json:"event"`
Data EventData `json:"data"`
}
func handleWebhook(c *gin.Context) {
var payload WebhookPayload
if err := c.ShouldBindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
switch payload.Event {
case "charge.success":
handleChargeSuccess(payload.Data)
default:
fmt.Printf("Unhandled event type: %s\n", payload.Event)
}
c.JSON(http.StatusOK, gin.H{"received": true})
}
func handleChargeSuccess(data EventData) {
fmt.Printf("Payment of %.2f %s received from %s\n",
float64(data.Amount)/100, data.Currency, data.Customer.Email)
// TODO: fulfil the order, update your database, send a confirmation email, etc.
}
Generated handler code is a starting point. Review it before deploying to
production — in particular, add signature verification to confirm the webhook
genuinely came from your provider.