> ## Documentation Index
> Fetch the complete documentation index at: https://bobprince-78964c2b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Code generation

> Generate TypeScript interfaces and handler code from your webhook payloads

<Note>
  AI features require a Starter plan or above. [Upgrade your plan](/billing/plans) to
  unlock them.
</Note>

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

1. Open the **Events** tab for any endpoint.
2. Click the event you want to type.
3. Click **Generate types** in the event detail panel.

Copy the generated interface directly into your project.

### Via the API

```bash theme={null}
curl https://hookdrop.dev/api/endpoints/<endpointId>/events/<eventId>/ai/schema \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

**Example response**

```json theme={null}
{
  "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:

```typescript theme={null}
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;
  };
}
```

<Tip>
  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.
</Tip>

***

## 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

```bash theme={null}
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**

```json theme={null}
{
  "language": "typescript",
  "framework": "express"
}
```

### Example responses

<Tabs>
  <Tab title="TypeScript / Express">
    ```typescript theme={null}
    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.
    }
    ```
  </Tab>

  <Tab title="JavaScript / Express">
    ```javascript theme={null}
    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.
    }
    ```
  </Tab>

  <Tab title="Python / FastAPI">
    ```python theme={null}
    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.
    ```
  </Tab>

  <Tab title="Go / Gin">
    ```go theme={null}
    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.
    }
    ```
  </Tab>
</Tabs>

<Warning>
  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.
</Warning>
