API reference › Webhooks › Rotate secret
Rotate a webhook secret
/v1/webhooks/:id/secretIssues a new signing secret for an endpoint, with a window in which the old one still verifies so you can redeploy on your own schedule.
The path is /:id/secret rather than /:id/rotate-secret: this call
creates a secret, so the noun in the path is the resource and POST is the
verb. Once a family has one route spelling the verb in the path and another
that doesn't, which one a given action gets stops being predictable.
No CLI command yet — webhooks are managed over the API only.
| Field | Type | Description |
|---|---|---|
| windowHours | number | How long the previous secret keeps being accepted, so you can redeploy on your own schedule. Default 24, max 168 (a week). |
curl -s -X POST https://api.propgate.dev/v1/webhooks/019fcf9a-3c4d-7e5f-a06b-7c8d9e0f1a2b/secret \
-H "authorization: Bearer pg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H 'content-type: application/json' -d '{"windowHours":24}'{
"data": {
"id": "019fcf9a-3c4d-7e5f-a06b-7c8d9e0f1a2b",
"object": "webhook_secret",
"secret": "whsec_..."
},
"error": null,
"meta": {
"previousSecretExpiresAt": "2026-08-04T12:00:00.000Z"
}
}Until previousSecretExpiresAt, every delivery is signed with both
secrets at once — see Webhooks for the header format
and how to verify against either. That overlap is what lets a rotation be a
deploy rather than an outage.
Rotating because a secret leaked? Pass windowHours: 0 and the old one stops
being accepted immediately:
curl -s -X POST https://api.propgate.dev/v1/webhooks/019fcf9a-3c4d-7e5f-a06b-7c8d9e0f1a2b/secret \
-H "authorization: Bearer pg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H 'content-type: application/json' -d '{"windowHours":0}'