Update a webhook

View as Markdown
Changes only the fields you send; the rest keep their stored values. Send `{"is_active": true}` to re-enable a webhook that was disabled after repeated failures. That also resets `failure_count` to 0 and clears `last_error`. The secret cannot be changed here: use `POST /api/webhooks/{webhookId}/rotate-secret`. Arrays and objects are replaced, not merged. Sending `events` replaces the whole list, and sending `filters` or `headers` replaces the stored object. Send `{}` to clear them. The rule against call filters on `audit.log_recorded` is checked against the result, meaning the stored values merged with the ones you send. A new `url` goes through the same syntax and DNS checks as on create. **Side effects.** Updates the webhook and `updated_at`. `is_active: false` stops deliveries at once, including retries already queued. Written to the audit log as `webhook.update`. **Idempotency.** Safe to retry: sending the same body again leaves the webhook in the same state. **Webhook events.** Emits `audit.log_recorded` to webhooks subscribed to it. See [Webhooks](/webhooks). **Access** - **Required scope:** `full`. Human users need the owner or admin role. - **Rate limit:** General API (120–600 requests/min per workspace, by plan) plus the configuration-mutations limit — 10 requests/min per workspace, shared with other configuration changes. See [Rate limits](/rate-limits). - **Plan:** Requires the `webhook` plan feature. Every plan includes it today, so this gate currently refuses nobody.

Authentication

AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

Path parameters

webhookIdstringRequiredformat: "uuid"

UUID of the outbound webhook. It must belong to the authenticated workspace; an id from another workspace answers 404, exactly like an unknown one. Returned as id by GET /api/webhooks.

Request

This endpoint expects an object.
urlstringOptionalformat: "uri"<=2000 characters
New endpoint. Same syntax and DNS checks as on create.
eventslist of enumsOptional

Replaces the whole subscription list (at least one event).

descriptionstringOptional<=500 characters
New label, up to 500 characters.
is_activebooleanOptional

false pauses deliveries, including queued retries. true re-enables and resets failure_count and last_error.

filtersobjectOptional

Optional delivery filters, combined with AND. The ID, outcome and sentiment filters fail closed: if the event’s data does not carry the field, the event is NOT delivered. They are matched against data.campaignId/data.campaign_id, data.agentId/data.agent_id, data.outcome/data.result and data.sentimentScore/data.sentiment. Filtered-out events leave no delivery log entry.

headersmap from strings to stringsOptional

Replaces all custom headers. {} removes them. Same limits as on create.

payload_templatestringOptional<=10000 characters

Replaces the template. "" goes back to the default body. Same validation as on create.

Response

The updated webhook, secret masked.
dataobject

An outbound webhook exactly as the API serializes it: the stored row with snake_case keys. secret is masked as "[configured]" on list, retrieve and update. The plaintext signing secret is returned only once, in the POST /api/webhooks response, and a new one by rotate-secret. Custom headers are returned as stored, in plaintext.

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
404
Not Found Error
429
Too Many Requests Error
500
Internal Server Error