> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signa.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Rotate Webhook Secret

> Roll the signing secret with a 24-hour overlap window

## Overview

Rotates the signing secret. The new secret is returned once in the response. The previous
secret remains valid for 24 hours, during which every delivery is signed with both:
`webhook-signature: v1,<new> v1,<old>` (space-separated, per the Standard Webhooks spec). Update
your verifier to the new secret any time within the window; no deliveries are missed. A second
rotation attempt while that window is still open returns `409` unless you pass `force: true`.

Requires the `portfolios:manage` scope.

## Path Parameters

<ParamField path="id" type="string" required>Endpoint ID (`whk_*`).</ParamField>

## Query Parameters

<ParamField query="force" type="boolean" default="false">
  Convenience alias for `force` in the body. `?force=true` is equivalent to `{"force": true}` in
  the JSON body.
</ParamField>

## Body Parameters

<ParamField body="force" type="boolean" default="false">
  Emergency use only. When `true`, skips the 24-hour overlap window and immediately invalidates
  the previous secret. Any receiver still using the previous secret fails signature
  verification on the next delivery. Without `force`, rotating while the previous secret is
  still within its 24-hour window returns `409`.
</ParamField>

<ParamField body="reason" type="string">
  Optional human-readable reason (max 500 chars), recorded on the audit event when `force: true`. Ignored otherwise.
</ParamField>

## Response

A `Webhook` with the new `secret` and bumped `secret_version`.

## Errors

| Status | `type`      | When                                                                                   |
| ------ | ----------- | -------------------------------------------------------------------------------------- |
| 404    | `not_found` | Endpoint doesn't exist or belongs to another org                                       |
| 409    | `conflict`  | The previous secret's 24-hour overlap window is still active and `force` wasn't `true` |

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.signa.so/v1/webhooks/whk_2mR8vNkT/rotate-secret" \
    -H "Authorization: Bearer sig_YOUR_KEY" \
    -H "Idempotency-Key: rotate-whk-2mR8vNkT-2026-06-12"
  ```

  ```bash cURL (force) theme={null}
  curl -X POST "https://api.signa.so/v1/webhooks/whk_2mR8vNkT/rotate-secret" \
    -H "Authorization: Bearer sig_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: force-rotate-whk-2mR8vNkT-2026-06-12" \
    -d '{"force": true, "reason": "Secret leaked in a client-side log"}'
  ```

  ```typescript TypeScript theme={null}
  import { Signa } from "@signa-so/sdk";
  const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });

  const rotated = await signa.webhooks.rotateSecret("whk_2mR8vNkT");
  // Store rotated.secret in your secrets manager: it is not returned again.
  console.log(rotated.secret);
  ```
</CodeGroup>

<ResponseExample>
  ```json theme={null}
  {
    "id": "whk_2mR8vNkT",
    "object": "webhook_endpoint",
    "url": "https://hooks.auroradigital.example.com/signa",
    "description": "Production alerts for Aurora Digital",
    "enabled_events": ["alert.created"],
    "status": "active",
    "secret_version": 2,
    "secret": "whsec_1a2b3c4d5e6f7081920a1b2c3d4e5f60",
    "consecutive_failures": 0,
    "last_success_at": "2026-07-05T09:12:31.000Z",
    "last_failure_at": null,
    "metadata": {},
    "created_at": "2026-07-06T08:00:00.000Z",
    "updated_at": "2026-07-06T09:00:00.000Z",
    "request_id": "req_3vXq7RmT"
  }
  ```
</ResponseExample>

## Related Endpoints

* [Retrieve Webhook Endpoint](/api-reference/monitoring/webhooks/retrieve) - check `secret_version` on an endpoint
* [Webhooks guide](/guides/monitoring/webhooks) - signature verification
