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

# Rotate the signature key

> Rotate the HMAC signing key for a webhook subscription. The new key is returned once – store it immediately in a secure secret manager.

Every webhook subscription has a `signature_key` that Tilta uses to sign outgoing event payloads. Rotating this key invalidates the previous key and replaces it with a newly generated secret. The new `signature_key` is included in the response body exactly once – Tilta never stores or re-exposes it. You must update your webhook handler to use the new key immediately after rotation, otherwise signature verification will fail and you will reject legitimate events from Tilta.

<Warning>
  The `signature_key` is returned **only in this response**. Once you close or discard it, it is gone permanently. Store it
  immediately in a secure secret manager such as AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or HashiCorp Vault.
  Never log this value or commit it to source control.
</Warning>

## Zero-downtime rotation procedure

Follow these steps to rotate your signature key without dropping any valid webhook deliveries:

<Steps>
  <Step title="Initiate the rotation">
    Call this endpoint and capture the new `signature_key` from the response immediately.
  </Step>

  <Step title="Store the new key alongside the old key">
    Temporarily configure your webhook handler to accept signatures verified by **either** the old key or the new key. This
    prevents a gap where in-flight events signed with the old key are rejected.
  </Step>

  <Step title="Deploy the updated handler">
    Roll out the updated handler that accepts both keys. Confirm it is live and processing events correctly.
  </Step>

  <Step title="Remove the old key">
    After a brief observation window (typically 5–15 minutes to allow any in-flight deliveries to drain), remove the old key
    from your handler so that only the new key is accepted.
  </Step>
</Steps>

<Tip>
  Schedule key rotations as part of your regular security hygiene cycle – for example, every 90 days or whenever a team member
  with access to the key departs. Automate the rotation using a secrets-management pipeline to avoid manual errors.
</Tip>


## OpenAPI

````yaml POST /v1/webhooks/{type}/signature_key
openapi: 3.0.0
info:
  version: 0.0.1
  title: Tilta API
  description: Tilta API documentation
servers:
  - url: https://api.tilta.io
    description: Tilta Production API
  - url: https://api.tilta-sandbox.io
    description: Tilta Sandbox API
security: []
paths:
  /v1/webhooks/{type}/signature_key:
    post:
      tags:
        - Webhooks
      summary: Rotate webhook signature key
      description: |-
        Rotate the specified Webhook subscription signature key.
            Store this safely because this is the only moment where we will return this value.
      parameters:
        - schema:
            type: string
            enum:
              - BUYER
              - BUYER.CREATED
              - BUYER.UPDATED
              - FACILITY
              - FACILITY.CREATION
              - FACILITY.CREATION.ACCEPTED
              - FACILITY.CREATION.IN_REVIEW
              - FACILITY.CREATION.REJECTED
              - FACILITY.EXPIRED
              - FACILITY.FROZEN
              - FACILITY.INCREASE
              - FACILITY.INCREASE.ACCEPTED
              - FACILITY.INCREASE.IN_REVIEW
              - FACILITY.INCREASE.REJECTED
              - FACILITY.RENEWAL
              - FACILITY.RENEWAL.ACCEPTED
              - FACILITY.RENEWAL.IN_REVIEW
              - FACILITY.RENEWAL.REJECTED
              - FACILITY.UNFROZEN
              - INVOICE
              - INVOICE.CLOSED
              - INVOICE.CREATED
              - INVOICE.DUE
              - INVOICE.FILE
              - INVOICE.FILE.CREATED
              - INVOICE.FILE.DELETED
              - INVOICE.FILE.REPLACED
              - INVOICE.FINANCING
              - INVOICE.FINANCING.PAID_OUT
              - ORDER
              - ORDER.CANCELLED
              - ORDER.CLOSED
              - ORDER.CONFIRMED
              - ORDER.DISBURSED
              - ORDER.EXPIRED
            description: >-
              The webhook's type. Supports the hierarchical dot-notation
              taxonomy; subscribing to a parent (e.g. `FACILITY`) implicitly
              subscribes to every descendant event (e.g.
              `FACILITY.CREATION.ACCEPTED`). Other valid values include
              `ORDER.CONFIRMED` and `INVOICE.DUE`.
            example: FACILITY.CREATION.ACCEPTED
          required: true
          name: type
          in: path
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                type: object
                properties:
                  destination_url:
                    type: string
                    format: uri
                    description: >-
                      Where the webhook should be sent to. This must be an
                      endpoint that handles POST requests.
                  type:
                    type: string
                    enum:
                      - BUYER
                      - BUYER.CREATED
                      - BUYER.UPDATED
                      - FACILITY
                      - FACILITY.CREATION
                      - FACILITY.CREATION.ACCEPTED
                      - FACILITY.CREATION.IN_REVIEW
                      - FACILITY.CREATION.REJECTED
                      - FACILITY.EXPIRED
                      - FACILITY.FROZEN
                      - FACILITY.INCREASE
                      - FACILITY.INCREASE.ACCEPTED
                      - FACILITY.INCREASE.IN_REVIEW
                      - FACILITY.INCREASE.REJECTED
                      - FACILITY.RENEWAL
                      - FACILITY.RENEWAL.ACCEPTED
                      - FACILITY.RENEWAL.IN_REVIEW
                      - FACILITY.RENEWAL.REJECTED
                      - FACILITY.UNFROZEN
                      - INVOICE
                      - INVOICE.CLOSED
                      - INVOICE.CREATED
                      - INVOICE.DUE
                      - INVOICE.FILE
                      - INVOICE.FILE.CREATED
                      - INVOICE.FILE.DELETED
                      - INVOICE.FILE.REPLACED
                      - INVOICE.FINANCING
                      - INVOICE.FINANCING.PAID_OUT
                      - ORDER
                      - ORDER.CANCELLED
                      - ORDER.CLOSED
                      - ORDER.CONFIRMED
                      - ORDER.DISBURSED
                      - ORDER.EXPIRED
                    description: >-
                      The webhook's type. Supports the hierarchical dot-notation
                      taxonomy; subscribing to a parent (e.g. `FACILITY`)
                      implicitly subscribes to every descendant event (e.g.
                      `FACILITY.CREATION.ACCEPTED`). Other valid values include
                      `ORDER.CONFIRMED` and `INVOICE.DUE`.
                    example: FACILITY.CREATION.ACCEPTED
                  signature_key:
                    type: string
                  created_at:
                    type: number
                    description: >-
                      Timestamp indicating when the webhook was created (unix
                      time in seconds).
                    example: 1582896122
                  updated_at:
                    type: number
                    description: >-
                      Timestamp indicating the last time the webhook was updated
                      (unix time in seconds).
                    example: 1582896122
                required:
                  - destination_url
                  - type
                  - signature_key
                  - created_at
                  - updated_at
                additionalProperties: false
        '400':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequestSchema'
        '401':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/unauthorizedRequestSchema'
      security:
        - bearerAuth: []
components:
  schemas:
    badRequestSchema:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: BAD_REQUEST
        error:
          type: string
          description: Error message for debugging purposes
          example: Request validation failed. 1 issue found.
        issues:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
                description: Issue code
                example: INVALID_TYPE
              path:
                type: string
                description: Issue path starting with body, params, querystring, or headers
                example: body.registered_at
              message:
                type: string
                description: Issue message for debugging purposes
                example: Invalid type
            required:
              - code
              - path
              - message
          description: List of issues
          example:
            - code: INVALID_TYPE
              path: body.registered_at
              message: Invalid type
      required:
        - code
        - error
        - issues
      description: Bad Request, see error message for details.
      example:
        code: BAD_REQUEST
        error: Request validation failed. 1 issue found.
        issues:
          - code: INVALID_TYPE
            path: body.registered_at
            message: Invalid type
    unauthorizedRequestSchema:
      type: object
      properties:
        error:
          type: string
          description: Error details.
          example: Unauthorized
        code:
          type: string
          description: Error code.
          example: UNAUTHORIZED
      required:
        - error
        - code
      description: Unauthorized Request.
      example:
        error: Unauthorized
        code: UNAUTHORIZED
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Your Tilta API key, sent as `Bearer <key>`.

````