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

# Client Tokens

> Mint a short-lived, capped client token for direct browser use. Call this server-side with your API key; the returned token grants the requested scopes (default 'interhumanai.stream') and can be handed to a browser to call the upload, stream, and realtime endpoints — e.g. POST /v1/upload/analyze, or open wss://.../v1/stream/analyze or wss://.../v0/realtime/analyze with the 'Sec-WebSocket-Protocol: access_token, <token>' subprotocol pair (a supported alternative to the 'Authorization' header, for browsers that cannot set it). The embedded caps are enforced by the API across all three (the video budget spans upload, stream, and realtime).

#### Response Headers

<ResponseField name="X-Correlation-ID" type="header">
  Unique identifier for the request. Include this when contacting support.

  Example: `f47ac10b-58cc-4372-a567-0e02b2c3d479`
</ResponseField>


## OpenAPI

````yaml post /v1/client_tokens
openapi: 3.1.0
info:
  title: interhuman-api
  version: 2.8.0
servers:
  - url: https://api.interhuman.ai
    description: Production environment
security: []
paths:
  /v1/client_tokens:
    post:
      summary: Create Client Token Endpoint
      description: >-
        Mint a short-lived, capped client token for direct browser use. Call
        this server-side with your API key; the returned token grants the
        requested scopes (default 'interhumanai.stream') and can be handed to a
        browser to call the upload, stream, and realtime endpoints — e.g. POST
        /v1/upload/analyze, or open wss://.../v1/stream/analyze or
        wss://.../v0/realtime/analyze with the 'Sec-WebSocket-Protocol:
        access_token, <token>' subprotocol pair (a supported alternative to the
        'Authorization' header, for browsers that cannot set it). The embedded
        caps are enforced by the API across all three (the video budget spans
        upload, stream, and realtime).
      operationId: create_client_token_endpoint_v1_client_tokens_post
      parameters:
        - name: X-Client-Request-Id
          in: header
          required: false
          description: >-
            Optional identifier supplied by the client to correlate this request
            with their own logs. When provided, the value is recorded alongside
            the server-assigned correlation ID in Interhuman logs to aid lookup
            and support investigations. This header is not echoed back in the
            response; the server returns its own correlation ID in the
            `X-Correlation-ID` HTTP response header.
          schema:
            type: string
            title: X-Client-Request-Id
        - name: X-Interhuman-SDK
          in: header
          required: false
          description: >-
            Optional client SDK identity as `<sdk-name>/<semver>` (e.g.
            `typescript/0.13.0`), sent automatically by the first-party
            Interhuman SDKs. It is recorded in Interhuman telemetry so SDK
            adoption and version distribution are visible. The value is
            self-declared and not authenticated: it never affects
            authentication, authorization, scopes, quotas, or billing, and a
            missing, malformed, or unrecognized value is ignored rather than
            rejected.
          schema:
            type: string
            title: X-Interhuman-SDK
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientTokenRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientTokenResponse'
              example:
                access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                token_type: Bearer
                expires_in: 300
                scope: interhumanai.stream
                max_duration_seconds: 600
                max_bytes: 52428800
                max_concurrent: 1
                allowed_origins:
                  - https://app.example.com
        '401':
          description: Unauthorized. The provided credentials are invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Forbidden. The key is valid but does not hold one of the requested
            scopes.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Unprocessable request. The request body is invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too many requests. The mint rate limit was exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    ClientTokenRequest:
      properties:
        api_key:
          type: string
          title: Api Key
          description: Your full API key from the Interhuman dashboard.
        scopes:
          items:
            $ref: '#/components/schemas/Scope'
          type: array
          minItems: 1
          title: Scopes
          description: >-
            Scopes to grant the token. Defaults to `interhumanai.stream`. The
            key must itself hold every requested scope. A realtime session
            requires `interhumanai.realtime`. The per-token caps are enforced on
            streaming sessions (stream / realtime); the video budget
            additionally spans upload.
        expires_in:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Expires In
          description: >-
            Requested time-to-live in seconds. Clamped to the supported range
            (60–3600s). Omit to use the default. The response `expires_in` is
            authoritative.
        max_duration_seconds:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Max Duration Seconds
          description: >-
            Maximum wall-clock duration of a streaming session (stream or
            realtime) opened with this token.
        max_bytes:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Max Bytes
          description: >-
            Maximum cumulative video bytes a session opened with this token may
            send.
        max_concurrent:
          type: integer
          minimum: 1
          title: Max Concurrent
          description: >-
            Maximum number of concurrent streaming sessions opened with this
            token. Defaults to 1 (a minted token can drive only one session at a
            time); raise it only if a single token must power several
            simultaneous sessions.
          default: 1
        max_video_seconds:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Max Video Seconds
          description: >-
            Maximum total seconds of video the token may process across upload,
            stream, and realtime combined. Metered server-side; when exhausted,
            further processing is refused and the client must mint a new token.
        allowed_origins:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Allowed Origins
          description: >-
            Allow-list of browser `Origin` values permitted to use this token.
            When set, a connection whose `Origin` is absent or not listed is
            rejected.
      type: object
      required:
        - api_key
      title: ClientTokenRequest
      description: Request schema for minting an ephemeral, capped client token.
    ClientTokenResponse:
      properties:
        access_token:
          type: string
          title: Access Token
          description: The generated client token.
        token_type:
          type: string
          title: Token Type
          description: Token type. Always `Bearer`.
          default: Bearer
        expires_in:
          type: integer
          title: Expires In
          description: Time in seconds until the token expires.
        scope:
          type: string
          title: Scope
          description: Space-separated list of granted scopes.
        max_duration_seconds:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Duration Seconds
          description: Per-token max session duration that will be enforced, if any.
        max_bytes:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Bytes
          description: >-
            Per-token max cumulative session bytes that will be enforced, if
            any.
        max_concurrent:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Concurrent
          description: Per-token max concurrent sessions that will be enforced, if any.
        max_video_seconds:
          anyOf:
            - type: integer
            - type: 'null'
          title: Max Video Seconds
          description: Per-token total video-seconds budget that will be enforced, if any.
        allowed_origins:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Allowed Origins
          description: >-
            Per-token allow-list of browser origins that will be enforced, if
            any.
      type: object
      required:
        - access_token
        - expires_in
        - scope
      title: ClientTokenResponse
      description: Response schema for a minted ephemeral client token.
    ErrorResponse:
      properties:
        error_id:
          type: string
          title: Error Id
          description: Machine-readable error code.
        correlation_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Correlation Id
          description: >-
            Unique identifier assigned to each API request or WebSocket
            connection. It allows both the client and the service to trace a
            specific interaction through logs and internal systems. If you
            contact support about a particular request or connection, providing
            the correlation_id allows the team to locate the relevant records
            quickly. Clients who may later request deletion of data for privacy
            reasons should store the correlation_id, as it can be used to
            identify and remove data associated with that specific interaction.
        link:
          anyOf:
            - type: string
            - type: 'null'
          title: Link
          description: URL to additional information about this error.
        message:
          anyOf:
            - type: string
            - type: 'null'
          title: Message
          description: >-
            Error explanation. Contains any additional details about the
            specific error that was encountered.
      type: object
      required:
        - error_id
      title: ErrorResponse
      description: >-
        Structured error returned by all HTTP error paths.


        Only ``error_id`` is required. The other fields are included when
        available.
    Scope:
      type: string
      enum:
        - interhumanai.upload
        - interhumanai.stream
        - interhumanai.realtime
        - interhumanai.upload.inter-2
        - interhumanai.upload.inter-2-audio
        - interhumanai.upload.inter-2-deep
        - interhumanai.stream.inter-2
        - interhumanai.stream.inter-2-audio
      title: Scope
      description: >-
        Scopes define which endpoints, and which models, the API key can call.


        A scope names one operation, or one (operation, model) cell of the
        Inter-2

        routes. The bare operation scopes are the Inter-1 cells; a model scope
        is

        the operation followed by the exact `model` value the route accepts.


        Options:

        - **interhumanai.upload** for /v1/upload/analyze (Inter-1)

        - **interhumanai.stream** for /v1/stream/analyze (Inter-1)

        - **interhumanai.realtime** for /v0/realtime/analyze

        - **interhumanai.upload.inter-2** for /v2/upload/analyze with
        `model=inter-2`

        - **interhumanai.upload.inter-2-audio** for /v2/upload/analyze with
          `model=inter-2-audio`
        - **interhumanai.upload.inter-2-deep** for /v2/upload/analyze with
          `model=inter-2-deep`
        - **interhumanai.stream.inter-2** for /v2/stream/analyze with
        `model=inter-2`

        - **interhumanai.stream.inter-2-audio** for /v2/stream/analyze with
          `model=inter-2-audio`

        Any `interhumanai.upload.<model>` scope also allows reading the
        account's

        upload jobs at /v2/upload/jobs/{job_id}. There is no stream scope for

        `inter-2-deep`: it is an upload-only model.

````