Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.offthehook.dev/llms.txt

Use this file to discover all available pages before exploring further.

This endpoint generates a new webhook signing secret for a subscription. To avoid dropping deliveries during a key rotation, you can specify a grace period during which the service signs each delivery with both the old and the new secret. Your endpoint can then validate against either, giving you time to deploy the new secret without downtime.

Request

POST /v1/subscriptions/:id/secrets/rotate

Headers

HeaderRequiredDescription
AuthorizationYesBearer oth_YOUR_API_KEY
Content-TypeYesapplication/json
Idempotency-KeyNoA unique key to safely retry this request without causing a double rotation.

Path parameters

id
string
required
The subscription ID (e.g. sub_2QkP9aB7xN...).

Body

gracePeriodSeconds
integer
How long, in seconds, the old secret remains valid alongside the new one. Set to 0 for an immediate cutover — the old secret becomes invalid as soon as the request completes. Defaults to 0.
curl -X POST https://api.offthehook.dev/v1/subscriptions/sub_2QkP9aB7xN.../secrets/rotate \
  -H "Authorization: Bearer oth_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: rotate-$(date +%s)" \
  -d '{ "gracePeriodSeconds": 3600 }'

Response

200 OK — the newly generated secret.
{ "secret": "whsec_NEW_SECRET..." }
The new secret is returned only in this response. Store it immediately before making any other API calls. After the grace period ends, the old secret is invalid and cannot be recovered.

During the grace period

While the grace period is active, the webhook-signature delivery header contains space-separated v1, signatures for both secrets:
webhook-signature: v1,<base64-hmac-new-secret> v1,<base64-hmac-old-secret>
The Svix verification library handles multi-signature validation automatically — you do not need to change your verification code during the transition.

Idempotency

Use the Idempotency-Key header to safely retry this request if you receive a network error or timeout. If the server has already processed a request with the same key, it returns the cached response without generating a new secret. Sending a conflicting body with the same key returns idempotency_conflict.

Errors

CodeHTTPDescription
not_found404The subscription ID does not exist or belongs to a different API key.
idempotency_in_flight409A request with this Idempotency-Key is currently being processed. Retry after a short delay.
idempotency_conflict409A request with this Idempotency-Key was already completed with a different request body.
unauthorized401The Authorization header is missing or the key is invalid.