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

# Rotate a webhook's signing secret

> Adds a secret, shown only in this response. Deliveries are signed with
it from now on, and with the secrets before it for 24 hours more
(Standard Webhooks sends several signatures), so receivers can switch
without rejecting any. Retire an old one sooner with
`DELETE /v1/webhook-secrets/{secret_id}`.




## OpenAPI

````yaml /openapi.json post /v1/webhooks/{webhook_id}/secrets
openapi: 3.1.1
info:
  title: Nohead API
  version: 1.0.0
  summary: Programmable content and data API.
  contact:
    name: Nohead
    email: hello@nohead.io
    url: https://nohead.io
  description: >
    The Nohead API manages projects, collections (your data models), their

    fields, and records (your content), with full version history.


    ## Authentication


    Send `Authorization: Bearer <token>`. Servers, CI and agents use a

    project API key (`nohead_sk_...`, or `nohead_pk_...` for a published-only

    key; created in the web app under API keys)

    with scopes such as `records:read` or `schema:write`. Organization,

    project, member and API key management need a person signed in to the

    web app and are not available to API keys.


    ## Resources and IDs


    Every object has an `object` type, and every resource with an identity of

    its own an opaque, prefixed `id` (`col_`, `fld_`, `rec_`, ...). Record
    values live under `data`, keyed by each

    field's `key`. Timestamps are ISO 8601 in UTC. Deleting a record,

    collection, field, asset or webhook is soft: it can be restored until its

    `purge_after`.


    ## Lists


    Lists return `{ "data": [...], "meta": { "next_cursor", "has_more" } }`.

    Pass `limit` (1-100) and `cursor` to page, and `sort` (prefix `-` for

    descending). Records also take `filter[<key>]=value`,

    `filter[published_at][exists]=true` and `expand=<relation, asset or

    rich text fields>`.


    ## Errors


    Errors share one envelope: `{ "error": { "type", "message",

    "request_id", "details" } }`. `details` lists field-level problems as

    `{ "field", "code", "message" }`. Include the `request_id` when asking

    for support.


    ## Safe retries and concurrent edits


    Send `Idempotency-Key` on any `POST`, `PUT`, `PATCH` or `DELETE` to make
    retrying

    it safe: the first result is stored for 24 hours and returned again for

    the same request. Record responses carry the record's revision as an

    `ETag`; send it back as `If-Match` to update only if nobody changed the

    record in the meantime (`412` otherwise).


    ## History


    Every change to a record is a revision, attributed to the person or API

    key that made it: record revisions can be listed, diffed and reverted,

    and collections keep a schema history. Send `Nohead-Change-Note` to

    record why a change was made. Changes that rewrite existing values

    (such as a field's type) are explicit, previewable field migrations.


    How long revisions are kept depends on the organization's plan. Older

    ones are removed, but every record keeps its first revision and its

    last 10; `history_pruned_through` says how far history was removed.
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://api.nohead.io
    description: Production
security:
  - apiKey: []
tags:
  - name: records
    x-group: Records
    description: Content entries, one at a time or many at once.
  - name: publishing
    x-group: Publishing
    description: Making records live, now or at a set time, and taking them down.
  - name: revisions
    x-group: Revisions
    description: A record's history, comparing two revisions, and going back to one.
  - name: drafts
    x-group: Drafts
    description: Changes to a record that wait to be merged into it, now or at a set time.
  - name: collections
    x-group: Collections
    description: User-defined data models.
  - name: schema-changes
    x-group: Schema changes
    description: A collection's schema history, and its schema at any version.
  - name: fields
    x-group: Fields
    description: Field definitions of a collection.
  - name: migrations
    x-group: Field migrations
    description: Explicit field changes that rewrite existing record values, with previews.
  - name: assets
    x-group: Assets
    description: Files stored for a project, uploaded directly to storage.
  - name: search
    x-group: Search
    description: Full-text search in collections and across a project.
  - name: webhooks
    x-group: Webhooks
    description: Event notifications sent to your URLs, and the secrets that sign them.
  - name: deliveries
    x-group: Webhook deliveries
    description: Each event sent to a webhook, its attempts, and retrying it.
  - name: audit
    x-group: Activity log
    description: The append-only trail of who changed what, through which client.
  - name: system
    x-group: System
    description: Service status, the caller, and its feature flags.
paths:
  /v1/webhooks/{webhook_id}/secrets:
    parameters:
      - $ref: '#/components/parameters/WebhookId'
    post:
      tags:
        - webhooks
      summary: Rotate a webhook's signing secret
      description: |
        Adds a secret, shown only in this response. Deliveries are signed with
        it from now on, and with the secrets before it for 24 hours more
        (Standard Webhooks sends several signatures), so receivers can switch
        without rejecting any. Retire an old one sooner with
        `DELETE /v1/webhook-secrets/{secret_id}`.
      operationId: webhooks_rotate_secret
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/NoheadClient'
      responses:
        '201':
          description: The new secret, with its value.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookSecretWithValue'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
      x-codeSamples:
        - lang: typescript
          label: TypeScript
          source: |
            import { Nohead } from "@nohead/sdk"

            const nohead = new Nohead()

            const result = await nohead.webhooks.rotateSecret("wh_01J9ZQ3F8X")
        - lang: python
          label: Python
          source: |
            from nohead import Nohead

            nohead = Nohead()

            result = nohead.webhooks.rotate_secret("wh_01J9ZQ3F8X")
        - lang: ruby
          label: Ruby
          source: |
            require "nohead"

            nohead = Nohead::Client.new

            result = nohead.webhooks.rotate_secret("wh_01J9ZQ3F8X")
components:
  parameters:
    WebhookId:
      name: webhook_id
      in: path
      required: true
      schema:
        type: string
      example: wh_01J9ZQ3F8X5W2K7M4N6P0R1S2T
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: |
        A unique value (1-255 printable ASCII characters) that makes retrying
        this request safe. The first response (below 500) is stored for 24
        hours per user or API key; retries with the same key and the same
        request get it again with an `Idempotent-Replayed: true` header. The
        same key with a different request is refused with `400`; a retry while
        the first request is still running gets `409`.
      schema:
        type: string
        minLength: 1
        maxLength: 255
      example: 8f14e45f-ceea-467a-9575-0f1a3f2c1d2e
    NoheadClient:
      name: Nohead-Client
      in: header
      description: >-
        First-party client identifier recorded in history (e.g. `cli/0.3.1`).
        Informational only.
      schema:
        type: string
  schemas:
    WebhookSecretWithValue:
      allOf:
        - $ref: '#/components/schemas/WebhookSecretProperties'
        - type: object
          required:
            - secret
          properties:
            secret:
              type: string
              description: >-
                The signing secret (`whsec_...`), shown only when it is added.
                Keep it private.
      unevaluatedProperties: false
    WebhookSecretProperties:
      type: object
      required:
        - id
        - object
        - webhook_id
        - expires_at
        - created_at
      properties:
        id:
          type: string
          examples:
            - whs_01J9ZQ3F8X5W2K7M4N6P0R1S2T
        object:
          const: webhook_secret
        webhook_id:
          type: string
        expires_at:
          $ref: '#/components/schemas/NullableTimestamp'
          description: When it stops signing deliveries; null for the newest secret.
        created_at:
          $ref: '#/components/schemas/Timestamp'
    Error:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - type
            - message
            - request_id
          properties:
            type:
              $ref: '#/components/schemas/ErrorType'
            message:
              type: string
            request_id:
              $ref: '#/components/schemas/RequestId'
            details:
              type: array
              items:
                $ref: '#/components/schemas/ErrorDetail'
    NullableTimestamp:
      type:
        - string
        - 'null'
      format: date-time
    Timestamp:
      type: string
      format: date-time
      description: ISO 8601 timestamp in UTC.
      examples:
        - '2026-09-27T12:00:00.000Z'
    RequestId:
      type: string
      pattern: ^req_[A-Za-z0-9]+$
      examples:
        - req_01J9ZQ3F8X5W2K7M4N6P0R1S2T
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication_error
        - plan_limit_exceeded
        - authorization_error
        - not_found
        - conflict
        - precondition_failed
        - validation_error
        - rate_limited
        - internal_error
        - service_unavailable
    ErrorDetail:
      type: object
      additionalProperties: false
      required:
        - code
        - message
      properties:
        field:
          type: string
          description: Key of the offending field or parameter, when applicable.
        code:
          type: string
          description: Machine-readable error code, e.g. `required`.
        message:
          type: string
        usage:
          type: integer
          description: Current usage, for `plan_limit` details.
        limit:
          type: integer
          description: The plan's limit, for `plan_limit` details.
        current_revision:
          type: integer
          description: The resource's current revision, for `revision_mismatch` details.
        record_id:
          type: string
          description: The record that already has the value, for `taken` details.
        draft_id:
          type: string
          description: The record's draft, for `draft_exists` and `draft_pending` details.
  responses:
    BadRequest:
      description: >-
        The request was malformed: unparseable JSON, an invalid query parameter,
        or a body key the operation doesn't take (detail code
        `unknown_parameter`, naming the key).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Authentication is missing or invalid.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: The caller is not allowed to perform this action.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: The resource does not exist or is not visible to the caller.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: The request conflicts with current state.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: >
        Too many requests for this API key or user (or, with failing

        credentials, this IP address). A published-only key is counted per

        client IP. Wait `Retry-After` seconds; retries with the same
        `Idempotency-Key`

        are safe. On the Free plan, an organization's API keys are also

        refused once its API requests reach the month's limit, with a

        `plan_limit` detail (`field` `api_requests`, `usage` and `limit`),

        until the next month (UTC) or an upgrade.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    RequestId:
      description: Unique identifier for the request, also echoed in error bodies.
      schema:
        $ref: '#/components/schemas/RequestId'
    RateLimitLimit:
      description: >-
        Requests allowed in the current window. Sent on every authenticated
        response.
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests left in the current window.
      schema:
        type: integer
    RateLimitReset:
      description: Seconds until the window resets.
      schema:
        type: integer
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: |
        Project-scoped API key, e.g. `nohead_sk_k7fz0a9c3m2q_<secret>`, or
        `nohead_pk_…` for a published-only key. Used by servers, CI, the CLI
        and coding agents.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.