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

# Mint a ticket for the serial console

> Mint a short-lived, single-instance credential for opening the serial
console from a browser.

**You probably do not need this.** Any client that can set request
headers — the `basaltic` CLI, or any non-browser tool — authenticates
the WebSocket upgrade normally. This exists because a browser's
WebSocket constructor takes a URL and nothing else, so there is no way
to send an `Authorization` header on it.

Pass the returned `ticket` as a query parameter on the upgrade:

```
wss://compute.<region>.basaltic.sh/v1/instances/<id>/console/serial?ticket=<ticket>
```

**The ticket is deliberately narrow.** It opens ONE instance, expires in
sixty seconds, and authorizes nothing else — because a credential in a
URL is written to proxy access logs, and this is worth far less there
than a session token would be. Mint one per connection; do not store it.

It carries who you are, not what you may do. Whether you may open this
console is still decided when the socket connects, against policy as it
stands then — so a permission revoked in the intervening minute is
honoured rather than frozen into the ticket.




## OpenAPI

````yaml /api-reference/specs/compute.yaml post /v1/instances/{instance_id}/console/ticket
openapi: 3.0.3
info:
  title: Basaltic Compute API
  version: 1.0.0
  description: |
    Virtual machine instances, and the images, flavors, SSH keypairs and
    instance pools they are built from. Covers the whole instance lifecycle:
    start, stop, reboot, resize and reinstall.
  contact:
    name: Basaltic Support
    email: ping@basaltic.sh
  license:
    name: Proprietary
    url: https://basaltic.sh/terms
servers:
  - url: https://compute.{region}.basaltic.sh
    description: Regional API endpoint
    variables:
      region:
        default: sa-saopaulo-1
        description: Region code
security:
  - BearerAuth: []
  - SignatureAuth: []
paths:
  /v1/instances/{instance_id}/console/ticket:
    post:
      tags:
        - Compute
      summary: Mint a ticket for the serial console
      description: >
        Mint a short-lived, single-instance credential for opening the serial

        console from a browser.


        **You probably do not need this.** Any client that can set request

        headers — the `basaltic` CLI, or any non-browser tool — authenticates

        the WebSocket upgrade normally. This exists because a browser's

        WebSocket constructor takes a URL and nothing else, so there is no way

        to send an `Authorization` header on it.


        Pass the returned `ticket` as a query parameter on the upgrade:


        ```

        wss://compute.<region>.basaltic.sh/v1/instances/<id>/console/serial?ticket=<ticket>

        ```


        **The ticket is deliberately narrow.** It opens ONE instance, expires in

        sixty seconds, and authorizes nothing else — because a credential in a

        URL is written to proxy access logs, and this is worth far less there

        than a session token would be. Mint one per connection; do not store it.


        It carries who you are, not what you may do. Whether you may open this

        console is still decided when the socket connects, against policy as it

        stands then — so a permission revoked in the intervening minute is

        honoured rather than frozen into the ticket.
      operationId: createSerialConsoleTicket
      parameters:
        - $ref: '#/components/parameters/InstanceId'
      responses:
        '200':
          description: A ticket for one console session
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SerialConsoleTicket'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
        - SignatureAuth: []
components:
  parameters:
    InstanceId:
      name: instance_id
      in: path
      description: Instance ID
      required: true
      schema:
        type: string
        format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    SerialConsoleTicket:
      type: object
      description: |
        A one-shot credential for opening a serial console from a browser.
        Pass `ticket` as a query parameter on the WebSocket upgrade.
      required:
        - ticket
        - expires_at
        - expires_in
      properties:
        ticket:
          type: string
          description: |
            The credential. Opaque — do not parse it. Good for one instance and
            one minute; mint a new one per connection rather than storing it.
        expires_at:
          type: string
          format: date-time
        expires_in:
          type: integer
          description: Seconds until it expires.
          example: 60
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: Error code identifying the type of error
              example: INVALID_INPUT
            message:
              type: string
              description: Human-readable error message
              example: Invalid request parameters
            request_id:
              type: string
              format: uuid
              description: Request ID for debugging
              example: 550e8400-e29b-41d4-a716-446655440000
  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INVALID_INPUT
              message: Invalid request parameters
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Unauthorized:
      description: Authentication required or token invalid
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: UNAUTHORIZED
              message: Authentication required
              request_id: 550e8400-e29b-41d4-a716-446655440000
    Forbidden:
      description: Insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ACCESS_DENIED
              message: You don't have permission to perform this action
              request_id: 550e8400-e29b-41d4-a716-446655440000
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: Resource not found
              request_id: 550e8400-e29b-41d4-a716-446655440000
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: An internal error occurred
              request_id: 550e8400-e29b-41d4-a716-446655440000
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        An OAuth 2.0 bearer token, sent as `Authorization: Bearer <token>`.
        This is the recommended way to authenticate.

        Get one by exchanging a service account's access key pair at
        `POST /v1/oauth/token` with `grant_type=client_credentials`. It is the
        standard client-credentials grant, so any OAuth-aware library will
        obtain and refresh it for you.

        ```
        curl -s -u "$KEY_ID:$SECRET" -d grant_type=client_credentials \
          https://iam.basaltic.sh/v1/oauth/token
        ```

        Tokens last an hour by default. The same access key pair is separately
        your AWS SigV4 credential for the S3-compatible object endpoint, which
        speaks nothing else.
    SignatureAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >
        Request signing with an access key issued to a service account. An

        HMAC-SHA256 over a canonical form of the request, close to AWS SigV4.

        The `basaltic` CLI signs for you.


        Send `Authorization`, `X-Date` (UTC, `YYYYMMDDTHHMMSSZ`) and `X-Nonce`

        (random per request); add `X-Content-Sha256` to bind a body, and

        `X-Amz-Security-Token` when using temporary credentials.


        ```

        Authorization: BASALTIC-HMAC-SHA256
        Credential=<access_key_id>/<date>/<region>/basaltic/basaltic_request,
        SignedHeaders=host;x-date;x-nonce, Signature=<hex>

        ```


        `<region>` is the region code you are calling, or `global` for the
        global

        services. A signature is valid for 5 minutes from `X-Date`, and mutating

        requests are replay-guarded on the nonce.


        **Full signing procedure, including a working implementation:**

        https://docs.basaltic.sh/authentication


        ## Rate limits

        There is no global request budget. A limit applies only where an

        operation documents a `429`, and that operation says what it counts.

        Those responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining`,

        `X-RateLimit-Reset` and, on a `429`, `Retry-After` — read them rather

        than hard-coding a number. Retrying before `Retry-After` is refused and

        extends the window. Everything else is bounded by quota, not by request

        rate.

````