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

# Rotate a private preview port's token generation

> Advances only this published private port's token generation, revoking
every older token for it while leaving sibling ports unchanged. The
revocation is committed even if the current host cannot deliver or
enforce the replacement; in that case the request returns an error and
no credential. Rotation requires sandbox write access. A successful
response contains a fresh non-expiring token for the new generation and
identifies both its header and signed-link query carriers. Rotation
immediately makes older browser cookies unusable because every request
revalidates the cookie's embedded generation.




## OpenAPI

````yaml https://raw.githubusercontent.com/superserve-ai/sandbox/refs/heads/main/api/openapi.yaml post /sandboxes/{sandbox_id}/preview-ports/{port}/token/rotate
openapi: 3.1.0
info:
  title: Superserve API
  version: 0.1.0
  description: >
    Superserve provides sandbox infrastructure to run AI agents in the cloud.
    Powered by Firecracker MicroVMs.


    ## Sandbox lifecycle


    ```

    active <--> paused --> deleted

    ```


    A sandbox is `active` when running and `paused` after being paused. Resuming

    a paused sandbox returns it to `active`. Deleting releases all resources.


    | Endpoint | What it does |

    |----------|-------------|

    | `POST /sandboxes` | Create a new sandbox (optionally `from_template`) |

    | `PATCH /sandboxes/:id` | Partially update a running sandbox (e.g. network
    rules) |

    | `POST /sandboxes/:id/pause` | Snapshot full state, suspend the VM |

    | `POST /sandboxes/:id/resume` | Restore from snapshot, continue where it
    left off |

    | `DELETE /sandboxes/:id` | Delete sandbox and all resources |


    ## Sandbox environment


    By default sandboxes boot from the curated `superserve/base` template
    (Ubuntu 24.04,

    1 vCPU, 1 GB RAM, 4 GB disk, with Python 3.12, Node.js 22, npm, git, curl,

    and build-essential pre-installed). Callers can override with any template

    name (e.g. `superserve/python-3.11`, `superserve/node-22`) or a team-owned
    template UUID

    via the `from_template` field on `POST /sandboxes`.


    ## Files and commands


    `/files`, `/exec`, and `/exec/stream` run against a single sandbox and use

    its `X-Access-Token` (returned by create, resume, and activate), not the

    team API key. Two host forms reach them:


    - `https://sandbox.superserve.ai/...` with `X-Superserve-Sandbox-Id:
    <sandbox_id>`.

    - `https://boxd-{sandbox_id}.sandbox.superserve.ai/...` — no routing header
    needed.
  contact:
    name: Superserve Team
  license:
    name: Proprietary
servers:
  - url: https://api.superserve.ai
    description: Production
security: []
paths:
  /sandboxes/{sandbox_id}/preview-ports/{port}/token/rotate:
    parameters:
      - $ref: '#/components/parameters/SandboxId'
      - $ref: '#/components/parameters/PreviewPort'
    post:
      tags:
        - Sandboxes
      summary: Rotate a private preview port's token generation
      description: |
        Advances only this published private port's token generation, revoking
        every older token for it while leaving sibling ports unchanged. The
        revocation is committed even if the current host cannot deliver or
        enforce the replacement; in that case the request returns an error and
        no credential. Rotation requires sandbox write access. A successful
        response contains a fresh non-expiring token for the new generation and
        identifies both its header and signed-link query carriers. Rotation
        immediately makes older browser cookies unusable because every request
        revalidates the cookie's embedded generation.
      operationId: rotateSandboxPreviewToken
      responses:
        '200':
          description: >-
            Fresh header and signed-link credential for the new generation;
            never cache this response
          headers:
            Cache-Control:
              schema:
                type: string
              description: Always `no-store`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PreviewTokenResponse'
        '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'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - apiKey: []
components:
  parameters:
    SandboxId:
      name: sandbox_id
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/PublicSandboxId'
      description: The unique identifier of the sandbox.
    PreviewPort:
      name: port
      in: path
      required: true
      schema:
        type: integer
        minimum: 1024
        maximum: 65535
        not:
          enum:
            - 49983
      description: >-
        Published sandbox port. Port 49983 is reserved for Superserve's sandbox
        service.
  schemas:
    PreviewTokenResponse:
      type: object
      description: >
        A single port-scoped credential with two explicit carriers. Machine

        clients normally send `token` in the request header named by `header`.

        For browser navigation, append the URL-encoded token under the parameter

        named by `query_param`, for example

        `https://{port}-{sandbox_id}.<sandbox-domain>/?{query_param}={token}`.


        For an ordinary `GET`, the edge validates the signed link, sets the

        host-only `__Host-superserve_preview_token` cookie with `Secure`,

        `HttpOnly`, `SameSite=None`, `Partitioned`, `Path=/`, and no `Domain`,

        then returns a `302` to a same-origin HTTPS URL with every reserved
        token

        parameter removed. Unrelated query data is preserved. The redirect is

        `Cache-Control: no-store` with `Referrer-Policy: no-referrer`.


        Non-`GET` requests and genuine WebSocket upgrade handshakes accept the

        query token directly without a redirect. In every case, the reserved

        header, query parameter, and cookie are removed before the upstream

        application receives the request. The edge revalidates cookie tokens on

        every request, so token expiry, generation rotation, access-mode change,

        or unpublication invalidates an existing browser session immediately;

        the browser may retain the now-unusable cookie value.
      required:
        - token
        - port
        - header
        - query_param
        - access
        - preview_access
        - token_version
      properties:
        token:
          type: string
          description: |
            Secret token scoped to this sandbox, port, and generation. Send it
            using the request header named by `header`, or URL-encode it under
            the signed-link query parameter named by `query_param`.
        port:
          type: integer
          minimum: 1024
          maximum: 65535
          not:
            enum:
              - 49983
        header:
          type: string
          example: X-Superserve-Preview-Token
          description: Request-header name to use when sending `token`.
        query_param:
          type: string
          example: superserve_preview_token
          description: Query-parameter name to use when constructing a signed link.
        access:
          type: string
          enum:
            - private
          description: The published port's access mode.
        preview_access:
          type: string
          enum:
            - legacy_public
            - public
            - private
          description: Sandbox default for newly published ports.
        token_version:
          type: integer
          format: int64
          minimum: 1
          description: Exact generation embedded in `token`.
        expires_at:
          type: string
          format: date-time
          description: |
            Present only when `expires_in_seconds` was supplied. After this
            instant the token is rejected in every carrier, including an
            already-established browser cookie.
    PublicSandboxId:
      type: string
      pattern: >-
        ^(sb-[a-z0-9]+-)?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
      description: >
        Public sandbox ID: a bare UUID, or the region-tagged form
        `sb-<region>-<uuid>` (e.g. `sb-use-1b4e28ba-…`). Treat as an opaque
        string; the tagged form routes the request to the sandbox's home region.
        Endpoints accept both forms interchangeably.
    Error:
      type: object
      description: |
        Error envelope. `error.code` is a stable, machine-readable identifier
        (e.g. `bad_request`, `not_found`, `conflict`, `rate_limited`,
        `too_many_builds`, `too_many_templates`, `too_many_sandboxes`,
        `image_pull_failed`, `step_failed`, `snapshot_failed`,
        `start_cmd_failed`, `ready_cmd_failed`, `build_failed`).
        `error.message` is human-readable and may change between releases;
        clients should branch on `code`, not `message`.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Caller is authenticated but not allowed to perform the action
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: Operation conflicts with the resource's current state
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

````