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

# Rotate the signing secret

> Generates a new signing `secret` for a subscription while keeping the previous secret valid for a 72-hour grace window, so in-flight receivers don't break. During that window Verbex signs each delivery with both secrets (two `v1=` values in `X-Webhook-Signature`). The new `secret` is returned once in this response - store it immediately.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/public/webhook/subscription/{id}/rotate/secret
openapi: 3.1.0
info:
  title: Verbex Platform API
  description: API for managing AI agents, calls, phone numbers, and more.
  version: 1.0.0
servers: []
security: []
tags:
  - name: Knowledge Bases
    description: >-
      Create and manage knowledge bases, ingest documents into them, and search
      them semantically.


      **Authentication.** Every request carries a bearer token: `Authorization:
      Bearer <API_TOKEN>`. That is the only credential a client sends. The
      gateway resolves your identity from it and injects the tenant headers the
      service reads internally, so clients never send `x-user-org-id` or
      `x-verbex-id` themselves.


      **Tenancy is enforced on every route.** A knowledge base belongs to one
      organization and one user. Requesting one your token does not own returns
      `404 Knowledge base not found`, never `403`. This is deliberate: a
      nonexistent ID, a malformed ID and someone else's ID are indistinguishable
      in the response, so the API cannot be used to probe for other tenants'
      data. If you get a `404` on an ID you are certain exists, suspect the
      token before you suspect the ID.


      **Ingestion is asynchronous.** File upload and website crawl both answer
      `202` as soon as the material is stored and the job is queued. Parsing,
      chunking, embedding and indexing happen afterwards in a worker. Poll the
      document status endpoint until it reports `completed` before expecting
      search to see the content. That gap is the most common source of "why
      isn't my data showing up".


      **There is no document update endpoint.** Every submission mints a new
      `document_id`, so re-uploading a file or re-crawling the same URLs creates
      a second document while the first remains. To refresh material, delete
      then resubmit — and note that the sequence is not atomic.
paths:
  /v1/public/webhook/subscription/{id}/rotate/secret:
    post:
      tags:
        - Webhook Subscriptions
      summary: Rotate the signing secret
      description: >-
        Generates a new signing `secret` for a subscription while keeping the
        previous secret valid for a 72-hour grace window, so in-flight receivers
        don't break. During that window Verbex signs each delivery with both
        secrets (two `v1=` values in `X-Webhook-Signature`). The new `secret` is
        returned once in this response - store it immediately.
      operationId: rotate_webhook_subscription_secret
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            title: Id
          description: The subscription ID whose secret to rotate.
      responses:
        '200':
          description: OK. Returns only the two rotation fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookRotateSecretResponse'
              example:
                secret: whsec_NEWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                previous_secret_expires_at: '2026-06-12T10:15:00.000Z'
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookAuthErrorResponse'
          description: Unauthorized - missing or invalid Bearer token.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookErrorResponse'
          description: Not Found - no subscription exists for the given id.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookErrorResponse'
          description: >-
            Conflict - the subscription was created without signing enabled (no
            secret to rotate).
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookErrorResponse'
          description: Internal Server Error.
      security:
        - BearerAuth: []
components:
  schemas:
    WebhookRotateSecretResponse:
      type: object
      title: WebhookRotateSecretResponse
      description: Returns only the two rotation fields - not the full subscription object.
      properties:
        secret:
          type: string
          title: Secret
          description: The new signing secret (`whsec_...`), returned once.
          example: whsec_NEWxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        previous_secret_expires_at:
          type: string
          format: date-time
          title: Previous Secret Expires At
          description: When the previous secret stops being accepted (rotation time + 72h).
          example: '2026-06-12T10:15:00.000Z'
    WebhookAuthErrorResponse:
      type: object
      title: WebhookAuthErrorResponse
      description: >-
        Authentication failures rejected at the API gateway (401) return this
        leaner body (note camelCase `traceId`).
      properties:
        error:
          type: string
          title: Error
          example: Authentication
        message:
          type: string
          title: Message
          example: Authentication failed
        traceId:
          type: string
          title: Trace Id
          example: e679120f-1d1c-41d2-947c-34e194d5a4a1
    WebhookErrorResponse:
      type: object
      title: WebhookErrorResponse
      description: Service-level error body (400, 404, 409, 500).
      properties:
        status:
          type: integer
          title: Status
          example: 400
        type:
          type: string
          title: Type
          example: VALIDATION_ERROR
        message:
          type: string
          title: Message
          example: Validation failed
        details:
          type: object
          title: Details
          description: >-
            Optional structured detail (e.g. `fields` -> per-field validation
            messages).
        timestamp:
          type: string
          format: date-time
          title: Timestamp
        path:
          type: string
          title: Path
          example: /v1/public/webhook/subscription
        trace_id:
          type: string
          title: Trace Id
          example: 341b5325-a0be-4533-85dd-6f697476dfc3
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        API key passed as a Bearer token in the `Authorization` header:
        `Authorization: Bearer <YOUR_API_KEY>`.

````