create(body: WebhookCreate, options?: RequestScope): Promise<CreatedWebhookResource>Registers an HTTPS receiver and subscribes it to a set of events. The endpoint is created with enabled set to true, so any matching event emitted after this call is queued for it straight away. The delivery worker drains the queue on a 5 second tick, so the first request usually lands a moment after this promise settles.
This response is the only place the API hands you the full secret. Every read gives you secretLastFour instead, so persist the secret before you do anything else. If you lose it you have two ways back: reveal it in the dashboard, which needs the webhooks:secret_read permission plus a step up verification, or call rotateSecret from here. Rotation is immediate and there is no overlap window, because each delivery is signed at send time from the endpoint's current secret, so queued deliveries and retries switch to the new secret too. The secret is formatted ev_whsec_ followed by base64url of 24 random bytes, and the HMAC key is the full string including that prefix: do not strip it, and if a verification library wants a base64 secret pass base64(utf8(secret)).
url is validated hard. It must be https, at most 2048 characters, free of embedded credentials, and pointed at a publicly routable host, which rules out loopback, private and carrier grade NAT ranges, link local and unique local IPv6, localhost, cloud metadata hosts and anything ending .internal, .local, .localdomain or .home.arpa. The host is checked again at delivery time: it is resolved and the attempt fails if any resolved address is private. Redirects are never followed, so a 3xx from your receiver is recorded as a failed attempt: register the final URL. eventTypes must be non empty and drawn from listEventTypes, and a 400 request.body_invalid names each offending value.
Example
const created = await envless.webhooks.create({
name: 'production sync',
url: 'https://hooks.example.com/envless',
eventTypes: ['variable.created', 'variable.updated']
})
console.log(created.secret)
console.log(created.id, created.secretLastFour)Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
body.name | string | Yes | Label shown in the dashboard and matched by list search, at most 64 characters. |
body.url | string | Yes | The https receiver URL, publicly routable and with no credentials in it. |
body.eventTypes | Array<string> | Yes | Non empty list of event names taken from listEventTypes. |
body.description | string | No | Free text note, at most 200 characters. |
options.signal | AbortSignal | No | Cancels the request. |
Returns
CreatedWebhookResource, a WebhookResource plus the plaintext secret. Alongside it you get id, name, url, description, eventTypes, enabled, secretLastFour, lastSuccessAt, lastFailureAt, createdAt and updatedAt.
Worth knowing
- Verify every incoming request with
verifyWebhookSignaturefrom the package root: it checks the HMAC over id, timestamp and body plus the timestamp drift, then returns the parsed event. - Delivery is at least once with up to 5 attempts, retrying 30s, 2m, 10m then 30m after the failed attempt, and a 10 second request timeout, so make the handler idempotent on the
webhook-idheader. - A workspace is capped at 20 endpoints, and creating the 21st is a 409
request.conflict. The separate 500 queued deliveries ceiling is enforced onredeliver, not on normal fan out. - An API key restricted to specific projects cannot call this at all: webhooks are workspace wide, so a project locked key gets 403
auth.key_project_restricted.
Required scopes
webhooks:write
Underlying endpoint
POST /webhooks
Request and response schema, every error code, and a live playground.
In Python
envless.webhooks.create()
The same method in envless-sdk, the Python SDK, with the same request, retries and errors.
In Ruby
Envless.webhooks.create
The same method in envless-sdk, the Ruby gem, with the same request, retries and errors.
In PHP
$envless->webhooks->create()
The same method in envless/sdk, the PHP SDK, with the same request, retries and errors.