Skip to main content

Overview

Webhooks module for receiving and verifying Base44’s webhooks. Base44 sends a signed event to your endpoint:
  • When an app is created, published, unpublished, moved to trash, or restored.
  • When you add the endpoint, to test it.
The module verifies each delivery’s signature with your workspace’s public keys and returns the event with a typed payload. It runs on Node.js 20 and later and on edge runtimes, and makes no network requests. Use createHandler() for a ready-made route handler, or verifyEvent() to handle the request yourself. Base44 delivers each event at least once and in no guaranteed order, so skip events whose id you already handled.

Methods

verifyEvent()

verifyEvent(body, headers, options): Promise<WebhookEvent>
Verifies a delivery and returns its event. Pass the request body exactly as received, before any JSON parsing, because the signature covers its exact bytes. Nothing is parsed until the signature checks out. Unlike createHandler(), verifyEvent() doesn’t answer the request for you. When you add an endpoint, Base44 sends it a webhook.test.v1 event and activates the endpoint only if you answer with { "challenge": event.data.challenge } within 5 seconds. Answer every other event with a 2xx, or Base44 retries it.

Parameters

any
requerido
The raw request body, as text or bytes.string | Uint8Array<ArrayBufferLike>
WebhookHeaders
requerido
The request headers.
VerifyEventOptions
requerido
Verification options, including your public keys.
WebhookPublicKeys
requerido
Your workspace’s public keys.Pass both the old and the new key while a key rotation is in progress. Missing or malformed keys reject with WebhookConfigurationError.
number
How far, in seconds, a delivery’s timestamp can be from your server’s clock. Defaults to 300.

Returns

WebhookEvent A promise that resolves to the verified event.

Throws

  • The promise rejects with a WebhookVerificationError when the delivery can’t be trusted. Answer with a 400.
  • The promise rejects with a WebhookConfigurationError when the public keys are missing or malformed, or the runtime can’t use them. Answer with a 500.

Example


createHandler()

createHandler(options): (request) => Promise<Response>
Creates a route handler that verifies deliveries and calls your handlers. The returned function takes a standard Fetch API Request and returns a Response, so you can use it with any framework built on the Fetch API, such as Next.js route handlers, Hono, Cloudflare Workers, Deno, and Bun. For each request, it reads the raw body and verifies it. It answers the test event itself, and for every other event it calls onEvent(), then the event’s handler in on, then onSuccess(). It answers with:
  • 204: Event was handled, including events with no handler and unknown events.
  • 400: Delivery doesn’t verify. Body carries the error code.
  • 500: Public keys are misconfigured (receiver_misconfigured), body can’t be read (request_failed), or a callback throws (handler_failed).
Base44 retries every answer that isn’t 2xx, so it retries both 400 and 500. The two codes only differ in Base44’s delivery log, where a 400 points to the delivery and a 500 points to your server. Base44 might deliver the same event more than once, so make your handlers safe to run twice for the same event.id.

Parameters

CreateHandlerOptions
requerido
Your public keys, handlers, and callbacks.
WebhookPublicKeys
requerido
Your workspace’s public keys.Pass both the old and the new key while a key rotation is in progress. Missing or malformed keys reject with WebhookConfigurationError.
number
How far, in seconds, a delivery’s timestamp can be from your server’s clock. Defaults to 300.
WebhookEventHandlers
Handlers keyed by event type. Events without a handler, including unknown ones, are still answered 2xx, so Base44 doesn’t retry them.
(event: DeliveredWebhookEvent) => unknown
Called for every verified event, before its handler in on.
(event: DeliveredWebhookEvent) => void | Response | Promise<void | Response>
Called after onEvent() and the event’s handler finish without throwing.Return a Response to replace the default empty 204.
(error: unknown, event: DeliveredWebhookEvent) => void | Response | Promise<void | Response>
Called when a delivery fails.The handler answers a WebhookVerificationError with a 400, and a WebhookConfigurationError, a failed body read, or anything a callback throws with a 500. Base44 retries both, because it retries every answer that isn’t 2xx. The two codes only differ in Base44’s delivery log, where a 400 points to the delivery and a 500 points to your server. The event argument is set when the delivery verified and a callback failed. Return a Response to replace the default answer.

Returns

A function that takes a Request and resolves to the Response to send.
(request): Promise<Response>
any
requerido
Request
requerido
Promise
requerido

Example

Type Definitions

WebhookEvent

WebhookEvent = { [K in WebhookEventType]: CloudEvent<K, WebhookEventMap[K]> }[WebhookEventType] | UnknownWebhookEvent
A verified webhook event. Check type to narrow data to that event’s payload. An event added to Base44 after this version of the SDK arrives with type: "unknown", its type in name, and an unchecked data, so check a field before using it. After you upgrade, the event arrives under its own type. Answer it with a 2xx too, because Base44 retries any answer that isn’t 2xx.

Example

UnknownWebhookEvent

A webhook event whose type this version of the SDK doesn’t know, such as one Base44 added later. The envelope is the same as for every event, but type is "unknown", the event’s real type is in name, and data isn’t checked, so check a field before using it.
'1.0'
requerido
CloudEvents version. Always 1.0.
string
requerido
Unique event ID, starting with evt_. A redelivery keeps the same ID, so use it to skip events you already handled.
string
requerido
URL of the workspace the event happened in.
string
requerido
The resource the event is about, such as apps/<app ID>.
string
requerido
When the event happened, as an RFC 3339 timestamp in UTC.
string
requerido
Content type of data. Always application/json.
string
requerido
URL of the JSON Schema that describes data.
string
W3C trace context, when the event was produced inside a trace.
string
W3C trace state, when the event was produced inside a trace.
string
requerido
Kind of actor that caused the event.
string
requerido
ID of the actor that caused the event.
TData
requerido
The event’s payload. Its shape depends on type.
'unknown'
requerido
Always "unknown". Narrows the event to this shape.
string
requerido
The event’s type as Base44 sent it, such as app.renamed.v1.

Errors

WebhookVerificationError

The error the SDK reports when a webhook delivery can’t be trusted. You don’t create these errors. The verifyEvent() method rejects with them, and createHandler() answers them with a 400 and passes them to your onError(). Check code to see what happened, then look the code up below. These errors never carry the request body or its signature.

Example

WebhookVerificationErrorCode
requerido
What happened. One of the verification error codes.
Codes of errors for a delivery that can’t be trusted. Answer these with a 400. Base44 retries any answer that isn’t 2xx, so a genuine delivery that failed because of a passing problem verifies on the retry.
The request is missing one of the webhook-id, webhook-timestamp, or webhook-signature headers.Check that a proxy in front of your endpoint forwards all request headers.
The webhook-timestamp header isn’t a number, or is further from your server’s clock than toleranceSeconds, which defaults to 300.Check your server’s clock. A replayed old delivery fails this way too.
The webhook-signature header has no signature in the v1a scheme Base44 uses.The request didn’t come from Base44, or a proxy rewrote the header.
No signature matches any of your public keys.Check that you pass the request body exactly as received. Parsing the JSON and serializing it again changes the bytes. Also check that your public keys belong to the workspace that sends the webhook.
The signature is valid, but the body isn’t a JSON event.This shouldn’t happen with deliveries from Base44.

WebhookConfigurationError

The error the SDK reports when the public keys you passed can’t be used, so no delivery can be verified. You don’t create these errors. The verifyEvent() method rejects with them, and createHandler() answers them with a 500 and passes them to your onError(). Base44 retries the delivery, and the retries succeed once you fix the problem.

Example

WebhookConfigurationErrorCode
requerido
What’s wrong with the keys. One of the configuration error codes.
Codes of errors that stop verification before it starts, because the public keys you passed can’t be used. They’re about your deployment, not the request, so answer them with a 500. Base44 retries the delivery, as it does for any answer that isn’t 2xx, and the retry succeeds once you fix the problem.
No public keys were passed, for example because an environment variable is unset.Pass your workspace’s public keys to verifyEvent() or createHandler().
A public key isn’t a base64-encoded 32-byte Ed25519 key, with or without the whpk_ prefix.Copy the key again. A truncated key fails this way.
The runtime can’t import Ed25519 keys with WebCrypto.Run your server on Node.js 20 or later, or on an edge runtime that supports Ed25519 in WebCrypto.