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

# Revoke a Secured Account

> End a Secured Account from your server. Send `reason: 'credential_changed'` when a primary sign-in detail changed on your side (password reset, email change, …) — the Secured Accounts spec requires it; the person's app then shows the account as Unlinked with a Re-link action. Your company's agents for that person are revoked with it, `account.unlinked { handle, by: 'platform', unlinked_at, reason, surface_id }` is sent to your webhook endpoints, live widgets for the account update at once, and the person is told. The next passkey ceremony on that account secures it again from scratch. Idempotent: an account that is not secured (or already unlinked) returns `revoked: false`. Select it by `platform_user_ref` or by `handle` — exactly one. The environment is your API key's: a `bs_dev_…` key sees and changes development Secured Accounts only, a `bs_prod_…` key production only. Server API keys only — site keys (`pk_…`) are refused.



## OpenAPI

````yaml /openapi.json post /secured-accounts/revoke
openapi: 3.1.0
info:
  title: BotShield API
  version: 2.0.0
  description: >-
    The BotShield partner API.


    **BotShield Gate** — ask whether a live human is present (Human Gate) or
    over an age threshold (Age Gate). The person confirms with their passkey in
    the BotShield app and you receive a signed result. Partners learn *that* a
    user is human, never *who*.


    **Agents Ask** — your agent proposes an action, a verified human confirms or
    denies it, and BotShield signs a Proof of Resolution you can verify offline.


    Every operation answers HTTP 200 with a `data` envelope; handler errors
    arrive as `data.error`. See the API overview and error reference. In the
    `botshield-sdk` package these operations live under `client.census.*`,
    `client.verification.*` and `client.actions.*`.
  contact:
    name: BotShield Support
    email: support@botshield.ai
    url: https://botshield.ai
servers:
  - url: https://api.botshield.ai/operations
    description: Production
security: []
tags:
  - name: BotShield Gate
    description: >-
      Place a gate and learn whether a present human (Human Gate) or a human
      over an age threshold (Age Gate) confirmed.
  - name: Agents Ask
    description: >-
      Your agent proposes an action; a verified human confirms or denies it in
      the BotShield app; you receive a signed Proof of Resolution.
paths:
  /secured-accounts/revoke:
    post:
      tags:
        - BotShield Gate
      summary: Revoke a Secured Account
      description: >-
        End a Secured Account from your server. Send `reason:
        'credential_changed'` when a primary sign-in detail changed on your side
        (password reset, email change, …) — the Secured Accounts spec requires
        it; the person's app then shows the account as Unlinked with a Re-link
        action. Your company's agents for that person are revoked with it,
        `account.unlinked { handle, by: 'platform', unlinked_at, reason,
        surface_id }` is sent to your webhook endpoints, live widgets for the
        account update at once, and the person is told. The next passkey
        ceremony on that account secures it again from scratch. Idempotent: an
        account that is not secured (or already unlinked) returns `revoked:
        false`. Select it by `platform_user_ref` or by `handle` — exactly one.
        The environment is your API key's: a `bs_dev_…` key sees and changes
        development Secured Accounts only, a `bs_prod_…` key production only.
        Server API keys only — site keys (`pk_…`) are refused.
      operationId: SecuredAccountsRevoke
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                platform_user_ref:
                  type: string
                  maxLength: 512
                  description: >-
                    Your stable user id for the account (the same
                    `platform_user_ref` you passed when it was secured). Hashed
                    server-side; never stored or returned. Send this OR
                    `handle`.
                handle:
                  type: string
                  pattern: ^OP_[A-Za-z0-9]{12}$
                  description: >-
                    The Secured Account handle — your per-platform reference for
                    the person, the same value carried on `account.secured` /
                    `account.unlinked`. Send this OR `platform_user_ref`.
                reason:
                  type: string
                  enum:
                    - platform
                    - credential_changed
                  description: Default `platform`.
      responses:
        '200':
          description: >-
            Result. NOTE: handler errors also arrive here (HTTP 200) as
            data.error — codes: `api_key_required` / `invalid_api_key` (401),
            `partner_not_found` (403), `ref_or_handle_required` /
            `invalid_platform_user_ref` / `invalid_handle` / `invalid_reason`
            (400), `revoke_failed` (500).
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    properties:
                      data:
                        type: object
                        required:
                          - success
                          - revoked
                          - handle
                          - unlinked_at
                          - unlink_reason
                        properties:
                          success:
                            type: boolean
                          revoked:
                            type: boolean
                            description: >-
                              false when no active Secured Account matched
                              (idempotent).
                          handle:
                            type: string
                            pattern: ^OP_[A-Za-z0-9]{12}$
                            description: >-
                              The revoked account's handle; null when nothing
                              was revoked.
                            nullable: true
                          unlinked_at:
                            type: string
                            format: date-time
                            nullable: true
                          unlink_reason:
                            type: string
                            enum:
                              - credential_changed
                              - platform
                            nullable: true
                      error:
                        $ref: '#/components/schemas/ErrorBody'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    ErrorBody:
      type: object
      required:
        - message
        - statusCode
      description: >-
        Handler error. Arrives inside `data.error` with HTTP 200. Check for it
        before reading the result.
      properties:
        message:
          type: string
          description: Human-readable explanation. Log it; do not parse it.
        statusCode:
          type: integer
          description: >-
            The HTTP status the error stands for (400, 401, 403, 404, 409, 422,
            429, 500, 502). Branch on this.
        code:
          type: string
          description: >-
            Machine code when present: `ttl_below_floor`, `ttl_above_ceiling`,
            `trust_layer_rejected`, `trust_layer_unavailable`, `gate_required`,
            `alias_retired`, `RATE_LIMITED`.
        min_ttl_seconds:
          type: integer
          description: With `ttl_below_floor`.
        max_ttl_seconds:
          type: integer
          description: With `ttl_above_ceiling`.
        retryable:
          type: boolean
          description: >-
            With `trust_layer_*`: whether sending the same request again can
            succeed.
        next_step:
          type: string
          description: 'With `trust_layer_*`: what to do next.'
        violations:
          type: array
          description: >-
            With `trust_layer_*` (statusCode 422): the parts of
            `adaptive_card_payload` that were flagged.
          items:
            type: object
            properties:
              source:
                type: string
              type:
                type: string
              path:
                type: string
              severity:
                type: string
              value:
                description: The flagged value from your payload.
              explanation:
                type: string
              fix:
                type: string
        reason:
          type: string
          enum:
            - rate
            - concurrent
          description: >-
            With `RATE_LIMITED` on a development key: a bucket is full (`rate`)
            or another request is still running (`concurrent`).
        bucket:
          type: string
          description: >-
            With `RATE_LIMITED`: the bucket that blocked the call (`per_minute`,
            `hourly`, `daily`, `in_flight`).
        retry_in:
          type: integer
          description: 'With `RATE_LIMITED`: seconds to wait.'
        limits:
          type: object
          description: >-
            With `RATE_LIMITED` on a development key: the development limits
            (`per_minute`, `hourly`, `daily`, `in_flight`).
        upgrade_url:
          type: string
          description: >-
            With `RATE_LIMITED` on a development key: where to create a
            production key in the Console.
    InvalidInputError:
      type: object
      required:
        - message
        - input
        - errors
      properties:
        message:
          type: string
          example: Invalid input provided
        input:
          type: object
          additionalProperties: true
        errors:
          type: array
          items:
            type: object
            required:
              - propertyPath
              - invalidValue
              - message
            properties:
              propertyPath:
                type: string
              invalidValue:
                description: The invalid value
              message:
                type: string
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
            - statusCode
          properties:
            message:
              type: string
            statusCode:
              type: integer
  responses:
    BadRequest:
      description: Invalid input
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InvalidInputError'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: >-
        Your secret API key (`bs_dev_…` for development, `bs_production_…` for
        production), or a site key (`pk_test_…` / `pk_live_…`) when calling from
        an allowed origin. Create keys in the Console under Settings → Developer
        Tools.

````

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