Update a webhook
Change a webhook’s subscriptions, URL or enabled state.
Update the subscribed event types, the destination URL, or pause delivery with enabled: false. Paused endpoints keep their configuration and delivery history.
PUT /v3/webhooks/{id}
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Optional | New destination. Re-validated like on create — public https targets only (http:// is rejected). |
events | array of strings | Optional | Replaces the full event list — include every type you still want. |
enabled | boolean | Optional | Pause (false) or resume (true) deliveries. Pausing stamps disabled_reason: "manual" + disabled_at; resuming clears both and resets the consecutive-failure counter — this is also how you re-enable an endpoint that was auto-disabled for consecutive failures (disabled_reason: "auto_failures", see the Webhooks page). |
domain_id | uuid or null | Optional | Scope to one of your domains, or pass null to widen back to all domains. Omit to leave unchanged. |
auth | object | Optional | Receiver-side authentication — same fields as on create (type: none / hmac / bearer / basic / custom_headers / oauth2 / mtls plus the type's fields). Omit to leave unchanged; pass { "type": "none" } to clear it. |
auth.rotate | boolean | Optional | hmac only. Pass { "type": "hmac", "rotate": true } to rotate the signing secret: the response returns the new plaintext whsec_ secret once, and the old secret stays valid for 24 h (previous_secret_valid_until on reads) so you can roll over without dropped events. |
Updating auth
Keeping the same auth.type and omitting a secret (token, password, client_secret, client_cert/client_key, or the headers map) keeps the stored value — so you can change auth.username, auth.token_url or the hmac header_name without re-supplying the secret. Switching to a different type requires that type's full credentials (switching to hmac generates a fresh secret, returned once). Reads echo auth redacted: non-secret fields plus token_set / password_set / client_secret_set / secret_set / cert_set / key_set presence booleans (hmac adds secret_hint, rotated_at, previous_secret_valid_until; mtls adds cert_fingerprint_sha256, cert_subject, cert_expires_at); secrets are never returned.
Responses
| Status | Description |
|---|---|
200 | OK. The updated webhook. The signing secret is never returned — unless you rotate to a new HMAC secret, which is revealed once, here. |
400 | Validation error — e.g. a non-HTTPS url, a failed SSRF check, or a domain you don't own. |
401 | Missing or invalid API key. |
404 | No webhook with this id on your account. |
Code examples
curl -X PUT https://api.wemail.io/v3/webhooks/{id} \
-H "Authorization: Bearer afn_live_…" \
-H "Content-Type: application/json" \
-d '{ "events": [ "delivered", "bounced", "complained" ], "enabled": true }'const res = await fetch("https://api.wemail.io/v3/webhooks/{id}", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.WEMAIL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ "events": [ "delivered", "bounced", "complained" ], "enabled": true }),
});
const data = await res.json();import os, requests
r = requests.put(
"https://api.wemail.io/v3/webhooks/{id}",
headers={"Authorization": f"Bearer {os.environ['WEMAIL_API_KEY']}"},
json={ "events": [ "delivered", "bounced", "complained" ], "enabled": true },
)
data = r.json()