Skip to content

02Guides

Webhooks and callbacks

Payload, response and handler types for webhooks and callbacks.

Webhooks (OpenAPI 3.1 and later) and callbacks (3.0 and later) describe requests the API sends to you. swaggerz generates types for the receiving side, so the route handler you write is checked against the specification.

import type { AccountClosedWebhookHandler } from './generated/api';
export const onAccountClosed: AccountClosedWebhookHandler = async ({ body, headers }) => {
if (headers['x-signature'] === '') return { received: false };
console.log('closed', body.id);
return { received: true };
};

For every webhook, webhooks/<webhook>.ts exports:

Type What it describes
<Name>WebhookPayload The request body the API sends
<Name>WebhookRequest body, and the declared headers and query parameters
<Name>WebhookResponse The body your handler sends back
<Name>WebhookHandler (request) => response, sync or async

Header names are lowercase, as Node.js and fetch expose them. Callbacks get the same types, named after their operation and callback: CreateAccountAccountEventCallbackHandler in callbacks/create-account-account-event.ts. Everything is exported from the main barrel.

No server code is generated: the types fit any framework. Turn the incoming request into the handler’s input and send back what it returns, for example with the web-standard Request and Response that Node.js, Deno, Bun and edge runtimes share:

import type { AccountClosedWebhookHandler, AccountClosedWebhookRequest } from './generated/api';
export function route(handler: AccountClosedWebhookHandler) {
return async (request: Request): Promise<Response> => {
const input: AccountClosedWebhookRequest = {
body: (await request.json()) as AccountClosedWebhookRequest['body'],
headers: { 'x-signature': request.headers.get('x-signature') ?? '' },
};
return Response.json(await handler(input));
};
}

The cast is the trust boundary: the types say what the API promises, not what arrived. With features.validation, parse the body with its schema (AccountSchema.parse(...)) instead.

The payload comes from the API, so it is typed like a response: readOnly properties are kept and writeOnly ones left out. Your handler’s response goes back to the API, so it is typed like a request body (the …Input variant, see read and write models). output.webhooks: false turns the types off.

  • Types only: no routing, signature verification or server adapters are generated.
  • The generated types describe requests; nothing checks at runtime that a request really came from the API.

What's generated

webhook.yaml
openapi: 3.1.0
info:
title: Accounts
version: '1.0'
paths: {}
webhooks:
accountClosed:
post:
summary: Sent when an account is closed.
parameters:
- name: X-Signature
in: header
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
responses:
'200':
description: Received.
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
components:
schemas:
Account:
type: object
required: [id]
properties:
id:
type: string

webhooks/account-closed.ts

/* eslint-disable */
// @generated by swaggerz. Do not edit: this file is overwritten on the next generation.
import type { Account } from '../models/account.js';
/** Sent when an account is closed. */
export type AccountClosedWebhookPayload = Account;
/** The request the API sends for the `accountClosed` webhook. */
export type AccountClosedWebhookRequest = {
/** Request body. */
body: AccountClosedWebhookPayload;
/** Declared headers (names in lowercase). */
headers: { 'x-signature': string };
};
/** Response body the API expects from the `accountClosed` webhook (`200`). */
export type AccountClosedWebhookResponse = {
received?: boolean;
};
/**
* Handles the `accountClosed` webhook.
*
* Implement it in your server and call it with the received request. Payloads are not validated; use the generated Zod schemas to validate untrusted input.
*/
export type AccountClosedWebhookHandler = (request: AccountClosedWebhookRequest) => AccountClosedWebhookResponse | Promise<AccountClosedWebhookResponse>;
Generated by swaggerz 0.1.2, at build time.