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

# Call keys.rotate

> Propose, then confirm, replacing the API key making this call with a new one — 'rotate this key', 'swap in a fresh credential'. The current key keeps working for overlap_hours after the new key exists, then stops. The new key comes back once, on the confirm, so store it before anything else. Not for any other key — revoke or rotate those in Settings › API & MCP.



## OpenAPI

````yaml /openapi.json post /api/v1/tools/keys.rotate
openapi: 3.1.0
info:
  title: Goosy Bear API
  version: 1.0.0-beta
  summary: Manage workspace content, projects, Data tables, Pages, library and credits.
  description: >-
    BETA. This API is in beta: paths, request shapes and response envelopes may
    change, and every response carries an `x-goosy-api: beta` header for as long
    as that is true. A change is additive, or it is deprecated first: a response
    to a call that uses a deprecated feature carries `Deprecation` and `Sunset`
    headers, and nothing is removed until at least 90 days after its
    deprecation. Pin the OpenAPI document you generated against and re-generate
    when it changes.
servers:
  - url: https://app.goosybear.ai
    description: Production
security:
  - tenantApiKey: []
paths:
  /api/v1/tools/keys.rotate:
    post:
      tags:
        - keys
      summary: Call keys.rotate
      description: >-
        Propose, then confirm, replacing the API key making this call with a new
        one — 'rotate this key', 'swap in a fresh credential'. The current key
        keeps working for overlap_hours after the new key exists, then stops.
        The new key comes back once, on the confirm, so store it before anything
        else. Not for any other key — revoke or rotate those in Settings › API &
        MCP.
      operationId: call_keys_rotate
      parameters:
        - name: x-request-id
          in: header
          required: false
          description: >-
            Your own id for this request, echoed back and recorded on the audit
            trail. 1–128 characters from `A–Z a–z 0–9 . _ : -`, starting with a
            letter or digit; anything else is replaced by a generated id.
          schema:
            type: string
            maxLength: 128
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                overlap_hours:
                  type: integer
                  minimum: 0
                  maximum: 168
                  description: >-
                    How many hours the current key keeps working after the new
                    one exists, 0 to 168. Default 24.
                confirmation_id:
                  type: string
                  format: uuid
              additionalProperties: false
      responses:
        '200':
          description: >-
            The call was admitted and dispatched. `ok` says whether the tool
            succeeded — a refusal the tool itself produced is still a 200,
            exactly as it is a successful JSON-RPC result over MCP.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
            x-goosy-tool-error:
              description: >-
                `true` whenever the call did not succeed, including when the
                tool itself returned a typed `ok: false` — this tool runs at
                account level, so there is no workspace boundary to distinguish.
                **Branch on `ok` in the body for the outcome; this header is the
                transport-level hint.**
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                oneOf:
                  - type: object
                    description: The tool ran and answered.
                    properties:
                      ok:
                        type: boolean
                        const: true
                      state:
                        type: string
                        enum:
                          - confirmation_required
                          - rotated
                      overlap_hours:
                        type: integer
                      previous_key_prefix:
                        type: string
                      confirmation_id:
                        type: string
                        format: uuid
                      expires_in_seconds:
                        type: integer
                        exclusiveMinimum: 0
                      key:
                        type: string
                      key_prefix:
                        type: string
                      key_expires_at:
                        type:
                          - string
                          - 'null'
                      previous_key_expires_at:
                        type: string
                    required:
                      - ok
                      - overlap_hours
                      - previous_key_prefix
                      - state
                  - $ref: '#/components/schemas/ToolRefusal'
        '400':
          description: >-
            The request could not be used: the body is present but not a JSON
            object (`tenant_api.malformed_body`); it is a top-level array
            carrying more messages than this endpoint accepts
            (`tenant_mcp.batch_too_large`); or the `Idempotency-Key` header is
            malformed (`tenant_api.idempotency_key_invalid`), disagrees with the
            body's `idempotency_key` (`tenant_api.idempotency_key_conflict`), or
            was sent to an action that cannot replay a retry
            (`tenant_api.idempotency_unsupported`). Nothing ran.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            No bearer credential, or one that did not resolve. Deliberately ONE
            undifferentiated answer for absent / unknown / revoked / expired, so
            the endpoint is never an oracle over the key space.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            The credential is good but the surface is not open to it — the
            platform or account API switch is off, or the holder lacks the
            `api.access` capability. The `code` says which.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            No such tool. The body names no tool and is identical for every
            unrecognised name.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: >-
            Over this key's per-minute cap. Carries `Retry-After` and
            `error.retry_after_seconds`.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            x-request-id:
              description: >-
                This request's id: the `x-request-id` you sent when it was well
                formed, otherwise one generated for you. Quote it to support; it
                is recorded on every audit row the call wrote.
              schema:
                type: string
            Deprecation:
              description: >-
                RFC 9745: this refusal's nested `error` object is deprecated,
                since this instant (`@<unix seconds>`).
              schema:
                type: string
            Sunset:
              description: >-
                RFC 8594: the nested `error` object may be removed after this
                date (2026-12-31).
              schema:
                type: string
            Link:
              description: The page that says what to read instead (`rel="deprecation"`).
              schema:
                type: string
            RateLimit-Limit:
              description: Requests this key may make in a rolling minute.
              schema:
                type: integer
                minimum: 1
            RateLimit-Remaining:
              description: Requests left in the current rolling minute.
              schema:
                type: integer
                minimum: 0
            RateLimit-Reset:
              description: Whole seconds until the window frees more requests.
              schema:
                type: integer
                minimum: 1
            Retry-After:
              description: Whole seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ToolRefusal:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        code:
          type: string
          description: >-
            The typed reason — e.g. `workspace_ambiguous`, `invalid_arguments`,
            or the tool's own failure code.
        message:
          type: string
          description: A sentence a person can act on.
        workspaces:
          type: array
          items:
            type: string
          description: 'On a workspace refusal: the slugs this key may pass as `workspace`.'
        issues:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
              message:
                type: string
            required:
              - path
              - message
            additionalProperties: false
          description: 'On `invalid_arguments`: which fields failed, and why.'
      required:
        - ok
        - code
        - message
      additionalProperties: false
      description: A call that was admitted and dispatched, and did not succeed.
    Error:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        code:
          type: string
          description: >-
            The typed refusal code — e.g. `tenant_mcp.surface_disabled`,
            `tenant_mcp.rate_limited`.
        message:
          type: string
          description: A sentence a person can act on.
        retry_after_seconds:
          type: number
          description: 'On a 429: whole seconds to wait. Mirrors `Retry-After`.'
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            retry_after_seconds:
              type: number
          required:
            - code
            - message
          additionalProperties: false
          description: >-
            Deprecated: the same values as the top-level fields, kept until
            2026-12-31. Read `code` and `message` at the top level.
      required:
        - ok
        - code
        - message
        - error
      additionalProperties: false
      description: >-
        A request the boundary refused before dispatching anything. The same
        shape the MCP endpoint answers its own refusals with, and the same
        top-level fields a dispatched call's refusal carries, so one client
        branch covers both.
  securitySchemes:
    tenantApiKey:
      type: http
      scheme: bearer
      description: >-
        An API key minted at Settings › API & MCP. Send it as `Authorization:
        Bearer <key>`. A key carries its holder's own permissions, resolved on
        every call — revoking a membership closes the key's reach immediately.
        Keep it in an environment variable (`GOOSY_API_KEY`), never in a
        committed file.

````