Event Catalog Export
You can download your whole event catalog as one machine-readable file. Your integrators can load it into the tools they already use: docs portals, mock servers, contract tests and code generators. They don't have to copy schemas out of the dashboard one event type at a time.
| Format | What you get |
|---|---|
| AsyncAPI 3.0 (YAML or JSON) | One channel, send operation and message per event type |
| OpenAPI 3.1 (YAML or JSON) | One entry per event type under the top-level webhooks object |
TypeScript (.d.ts) | One type per event type, plus a WebhookEvent union discriminated by event type name |
Every plan includes the export.
From the dashboard
Go to Outbound → Event Types and click Export. Then pick a format. The export includes every enabled event type. Deprecated event types are included too, flagged as deprecated.
From the API
GET /api/organizations/{orgId}/event-types/export| Query parameter | Values | Default |
|---|---|---|
format | asyncapi, openapi, typescript | asyncapi |
encoding | yaml, json (ignored for typescript) | yaml |
includeDisabled | true to include disabled event types | false |
includeDeprecated | false to leave deprecated event types out | true |
curl "https://api.hookbase.app/api/organizations/{orgId}/event-types/export?format=asyncapi&encoding=yaml" \
-H "Authorization: Bearer whr_your_api_key" \
-o asyncapi.yaml
curl "https://api.hookbase.app/api/organizations/{orgId}/event-types/export?format=typescript" \
-H "Authorization: Bearer whr_your_api_key" \
-o webhooks.d.tsThe response is the file itself, sent with Content-Disposition: attachment. The output is deterministic: event types are sorted by name, so the same catalog always produces a byte-identical file. That makes it safe to commit the file and diff it in CI.
From your public catalog
If you publish event types to your public catalog, the catalog page has download links for the same formats. Anyone can fetch them without authentication:
GET /api/event-catalog/{orgSlug}/_export?format=asyncapi|openapi|typescript&encoding=yaml|jsonThe public export contains exactly what the public catalog page shows: event types that are both published and enabled. Unpublished event types never appear in it.
What the documents describe
Each document describes what Hookbase actually sends to a subscribed endpoint:
- Method and body: an HTTP
POSTwhose body is the event payload you passed to send-event. The payload isn't wrapped in an envelope. If a subscription has a transform, the endpoint receives the transformed body, which the exported schema doesn't describe. - Payload schema: the JSON Schema stored on the event type. Schemas are placed under
components.schemas. Root$defs/definitionsbecome their own components, and local$refs are rewritten to point at them. - Missing schemas: an event type without a schema exports as an unconstrained payload (
{}) with a note saying so (x-hookbase-schema-missing: true). - Examples: the event type's example payload, if it has one.
- Headers: the Standard Webhooks headers
webhook-id,webhook-timestampandwebhook-signature, plusx-hookbase-event-type, which is fixed to the event type's name. - Security: a
standardWebhookssecurity scheme that describes the HMAC-SHA256 signature. See Signature Verification. - Deprecation: OpenAPI operations get
deprecated: true. AsyncAPI messages and operations getx-deprecated: true, the payload schema getsdeprecated: true, and the description starts with your deprecation message.
Versioned event types
If an event type has versions, the export describes every version. The latest keeps the names an unversioned event type gets, so files generated before you versioned it keep working. Each older version is added next to it, with an x-hookbase-event-version header fixed to its label:
| Format | Latest | An older version v1 |
|---|---|---|
| AsyncAPI | message order_created | message order_created__v1 on the same channel and operation |
| OpenAPI | webhook order.created | webhook order.created@v1 |
| TypeScript | OrderCreated | OrderCreatedV1, and WebhookEventVersionMap["order.created"]["v1"] |
Deprecated versions are flagged as deprecated, with their sunset date.
TypeScript types
The .d.ts file contains one interface (or type alias) per event type, named after the event type: order.created becomes OrderCreated. It also contains:
export interface WebhookEventMap {
"order.created": OrderCreated;
"order.refunded": OrderRefunded;
}
export type WebhookEventType = keyof WebhookEventMap;
export type WebhookEvent =
| { type: "order.created"; payload: OrderCreated }
| { type: "order.refunded"; payload: OrderRefunded };
export interface WebhookHeaders { /* webhook-id, webhook-timestamp, webhook-signature, x-hookbase-event-type */ }The event type name isn't part of the body; it arrives in the x-hookbase-event-type header. Build the union value from the header and the parsed body, but only after you verify the signature:
import { Webhook } from 'standardwebhooks';
import type { WebhookEvent, WebhookEventType } from './webhooks';
const wh = new Webhook(process.env.HOOKBASE_SECRET!); // your endpoint's whsec_... secret
export function parseWebhook(rawBody: string, headers: Record<string, string>): WebhookEvent {
const payload = wh.verify(rawBody, headers); // throws if the signature is invalid
return { type: headers['x-hookbase-event-type'] as WebhookEventType, payload } as WebhookEvent;
}
const event = parseWebhook(body, headers);
switch (event.type) {
case 'order.created':
console.log(event.payload.id); // typed as OrderCreated
break;
}The generator handles objects, arrays and tuples, enum, const, oneOf / anyOf (unions), allOf (intersections), required vs. optional properties, nullable, and local $refs, including recursive ones. Any schema construct it can't express becomes unknown, so the file always compiles.
Other languages
Only TypeScript has built-in codegen right now. For other languages, generate types from the AsyncAPI or OpenAPI export with standard tools, for example the AsyncAPI generator, quicktype for the payload schemas, or datamodel-code-generator for Python.