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.
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(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. Unlikebody,headers,options):Promise<WebhookEvent>
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
Properties
Properties
any
必須
The raw request body, as text or bytes.
string | Uint8Array<ArrayBufferLike>WebhookHeaders
必須
The request headers.
VerifyEventOptions
必須
Verification options, including your public keys.
Returns
WebhookEvent
A promise that resolves to the verified event.
Throws
- The promise rejects with a
WebhookVerificationErrorwhen the delivery can’t be trusted. Answer with a 400. - The promise rejects with a
WebhookConfigurationErrorwhen the public keys are missing or malformed, or the runtime can’t use them. Answer with a 500.
Example
createHandler()
createHandler(Creates a route handler that verifies deliveries and calls your handlers. The returned function takes a standard Fetch APIoptions): (request) =>Promise<Response>
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).
event.id.
Parameters
CreateHandlerOptions
必須
Your public keys, handlers, and callbacks.
Properties
Properties
WebhookPublicKeys
必須
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 aRequest and resolves to the Response to send.
(request):Promise<Response>
Example
Type Definitions
WebhookEvent
WebhookEvent =A verified webhook event. Check{ [K in WebhookEventType]: CloudEvent<K, WebhookEventMap[K]> }[WebhookEventType] |UnknownWebhookEvent
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, buttype is "unknown", the event’s real type is
in name, and data isn’t checked, so check a field before using it.
'1.0'
必須
CloudEvents version. Always
1.0.string
必須
Unique event ID, starting with
evt_. A redelivery keeps the same ID, so use it to skip events you already handled.string
必須
URL of the workspace the event happened in.
string
必須
The resource the event is about, such as
apps/<app ID>.string
必須
When the event happened, as an RFC 3339 timestamp in UTC.
string
必須
Content type of
data. Always application/json.string
必須
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
必須
Kind of actor that caused the event.
string
必須
ID of the actor that caused the event.
TData
必須
The event’s payload. Its shape depends on
type.'unknown'
必須
Always
"unknown". Narrows the event to this shape.string
必須
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. TheverifyEvent() 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
必須
What happened. One of the verification error codes.
Verification error codes
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. TheverifyEvent() 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
必須
What’s wrong with the keys. One of the configuration error codes.
Configuration error codes
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.