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

# Create Realtime Transcription

> Create a realtime transcription session and get the WebSocket URL and stream token to stream audio.

The Realtime Transcription API is available to Enterprise plan customers on request. Tiro must enable it for the workspace first.

- Call this from your server. Pass `wsUrl` and `streamToken` to the client that streams audio, and keep the API key on the server
- Connect to `wsUrl` with the `Authorization: Bearer <streamToken>` header, then send 16 kHz mono PCM s16le audio as binary frames
- `streamToken` appears only in this response. Reuse it to reconnect while the session is `OPEN`
- Requires a workspace API key, or an account API key bound to the workspace whose owner is a workspace member
- Each workspace can have 10 `OPEN` sessions at once
- Tiro does not create notes and does not keep the audio. Results arrive only over the WebSocket

Documentation: [Quickstart](/en/developers/realtime-transcription/quickstart), [WebSocket protocol](/en/developers/realtime-transcription/protocol)




## OpenAPI

````yaml /openapi.yaml post /v1/external/realtime-transcriptions
openapi: 3.1.0
info:
  title: Tiro API
  description: AI-powered note-taking and voice file processing API
  version: 1.0.0
  contact:
    name: Tiro Support
    email: support@tiro.ooo
    url: https://tiro.ooo
servers:
  - url: https://api.tiro.ooo
    description: Production server
security:
  - BearerAuth: []
tags:
  - name: Workspace
    description: >
      List the workspaces an API key can reach. Workspace-scoped endpoints take
      a

      `{workspaceGuid}` path segment; get it from `GET /v1/external/workspaces`.
  - name: Note
    description: Operations for managing notes and their paragraphs
  - name: Note Share Link
    description: Manage share links for notes
  - name: Note Summary
    description: Operations for retrieving note summaries
  - name: Note Document
    description: Template-based document generation from notes
  - name: Note Document Template
    description: Operations for managing note document templates
  - name: Folder
    description: Operations for retrieving folders
  - name: Voice File
    description: Operations for voice file processing
  - name: Realtime Transcription
    description: >
      Create, get, list, and end realtime transcription sessions. Audio and
      results flow over the

      WebSocket at `wsUrl`, documented in [WebSocket
      protocol](/en/developers/realtime-transcription/protocol).

      Available to Enterprise plan customers on request.
  - name: Word Memory
    description: >
      Manage word memories to improve voice transcription accuracy. Register
      important terms like company names, people's names, and product names so
      Tiro recognizes them precisely during recording. Each term has an `entry`
      and an optional `subEntry` (an alternate spelling or notation). Personal
      (User), workspace-shared (Workspace), and organization-shared
      (Organization) word memories are managed separately, and each scope
      supports bulk create/update/delete (up to 1000 items per request).
  - name: Wiki
    description: |
      Access workspace wikis — unified knowledge graphs built from notes.
      Requires a workspace with wiki plan and activation enabled.
  - name: Organization
    description: >
      Endpoints for organization API keys. An organization key is issued by an

      organization admin, carries fixed scopes chosen at issuance, and can reach

      the notes in every workspace that belongs to the organization. Built for

      server-to-server integrations such as CRM sync — receive `note.ended`
      webhook

      events, generate documents for notes, and reconcile with the organization

      notes list.
  - name: Organization Management
    description: Operations for the authenticated user's organization.
paths:
  /v1/external/realtime-transcriptions:
    post:
      tags:
        - Realtime Transcription
      summary: Create Realtime Transcription
      description: >
        Create a realtime transcription session and get the WebSocket URL and
        stream token to stream audio.


        The Realtime Transcription API is available to Enterprise plan customers
        on request. Tiro must enable it for the workspace first.


        - Call this from your server. Pass `wsUrl` and `streamToken` to the
        client that streams audio, and keep the API key on the server

        - Connect to `wsUrl` with the `Authorization: Bearer <streamToken>`
        header, then send 16 kHz mono PCM s16le audio as binary frames

        - `streamToken` appears only in this response. Reuse it to reconnect
        while the session is `OPEN`

        - Requires a workspace API key, or an account API key bound to the
        workspace whose owner is a workspace member

        - Each workspace can have 10 `OPEN` sessions at once

        - Tiro does not create notes and does not keep the audio. Results arrive
        only over the WebSocket


        Documentation:
        [Quickstart](/en/developers/realtime-transcription/quickstart),
        [WebSocket protocol](/en/developers/realtime-transcription/protocol)
      operationId: createRealtimeTranscription
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                workspaceGuid:
                  type: string
                  description: >
                    Optional. Defaults to the key's workspace. If set, it must
                    equal the key's workspace GUID, otherwise the request fails
                    with `403` `workspace_access_denied`.
                  example: Wk8sQ2mLx1aB7
                transcriptionLocale:
                  type: string
                  nullable: true
                  description: >
                    Language to transcribe. Omit it, send `null`, or send `AUTO`
                    to detect the spoken language.

                    Accepts `ko_KR`, `ko-KR`, and `ko`, case-insensitive. A
                    language-only tag resolves to its supported region. Regions
                    outside the [supported
                    locales](/en/developers/fundamentals/supported-locales),
                    such as `en-GB`, return `400` `unsupported_language`.
                  example: ko_KR
                translationLocale:
                  type: string
                  nullable: true
                  description: >
                    One language to translate into. Omit it or send `null` for
                    no translation.

                    Uses the same format as `transcriptionLocale`. `AUTO`, or
                    the same language as `transcriptionLocale`, returns `400`
                    `invalid_request`.
                  example: en_US
            example:
              transcriptionLocale: ko_KR
              translationLocale: en_US
      responses:
        '201':
          description: Session created. The response includes `streamToken`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RealtimeTranscription'
              example:
                id: Rt7Yq2PbX9cDk
                workspaceGuid: Wk8sQ2mLx1aB7
                apiKeyId: tk_8f2a91c0d3e4
                status: OPEN
                endReason: null
                wsUrl: >-
                  wss://api.tiro.ooo/v1/external/realtime-transcriptions/Rt7Yq2PbX9cDk/stream
                streamToken: rtt_5Hq3...
                maxDurationMs: 10800000
                audioDurationMs: 0
                transcriptionLocale: ko_KR
                translationLocale: en_US
                createdAt: '2026-11-05T09:00:00Z'
                endedAt: null
        '400':
          description: >
            `400023 bad_request` with `detail.reason` `invalid_request` when a
            value breaks a rule, such as `translationLocale` set to `AUTO` or to
            the transcription language. Check `detail.fields`.


            `400024 bad_request` with `detail.reason` `unsupported_language`
            when a locale is not supported. Check `detail.field` and
            `detail.value`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            The API key is missing or invalid. Send a valid key in the
            Authorization header.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >
            `403013 forbidden` (`insufficient_scope`) when the key lacks
            `realtime_transcription:write`. OAuth access tokens also get this
            response.


            `403024 forbidden` (`workspace_bound_key_required`) for an account
            API key not bound to a workspace or an organization API key. Use a
            key bound to the workspace.


            `403025 forbidden` (`workspace_access_denied`) when `workspaceGuid`
            differs from the key's workspace, or the account API key owner is
            not a workspace member.


            `403026 forbidden` (`realtime_api_not_enabled`) when the workspace
            does not have the Realtime Transcription API enabled. Contact Tiro
            to enable it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: The key's workspace was deleted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >
            `409043 conflict` (`concurrent_transcription_limit`) when the
            workspace already has 10 `OPEN` sessions. `detail.limit` holds the
            limit. Find unused sessions with List Realtime Transcriptions, end
            them, and try again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: 409043
                  errorType: conflict
                  message: >-
                    Concurrent realtime transcription limit reached for this
                    workspace
                  detail:
                    reason: concurrent_transcription_limit
                    limit: 10
components:
  schemas:
    RealtimeTranscription:
      type: object
      description: >
        A realtime transcription session. Results are delivered only over the
        WebSocket at `wsUrl`, not through this resource.

        See [WebSocket
        protocol](/en/developers/realtime-transcription/protocol).
      required:
        - id
        - workspaceGuid
        - status
        - wsUrl
        - maxDurationMs
        - audioDurationMs
        - createdAt
      properties:
        id:
          type: string
          description: Session ID.
          example: Rt7Yq2PbX9cDk
        workspaceGuid:
          type: string
          description: >-
            Workspace the session belongs to. Concurrent sessions are counted
            per workspace.
          example: Wk8sQ2mLx1aB7
        apiKeyId:
          type: string
          nullable: true
          description: >-
            Public ID of the API key that created the session, matching
            `apiKeyId` from `GET /v1/external/auth/me`. `null` only when Tiro
            can no longer find that key.
          example: tk_8f2a91c0d3e4
        status:
          type: string
          enum:
            - OPEN
            - ENDED
          description: >
            - `OPEN`: Tiro accepts audio. You can connect and reconnect. The
            session holds a concurrent slot

            - `ENDED`: The session is over. You cannot reconnect


            New values can appear. Treat an unknown value as not `ENDED`.
          example: OPEN
        endReason:
          type: string
          nullable: true
          enum:
            - CLIENT_REQUESTED
            - IDLE_TIMEOUT
            - MAX_DURATION
            - INTERNAL_ERROR
          description: >
            Why the session ended. `null` while `OPEN`.

            - `CLIENT_REQUESTED`: WebSocket `session.end` or End Realtime
            Transcription

            - `IDLE_TIMEOUT`: No audio for 15 minutes

            - `MAX_DURATION`: 3 hours since the first connection

            - `INTERNAL_ERROR`: Tiro could not continue the session


            New values can appear. Treat an unknown value as a normal end.
          example: null
        wsUrl:
          type: string
          description: >-
            WebSocket URL to connect to. Use it as returned. Do not build or
            hard-code the host or path.
          example: >-
            wss://api.tiro.ooo/v1/external/realtime-transcriptions/Rt7Yq2PbX9cDk/stream
        streamToken:
          type: string
          description: >
            Token for the WebSocket `Authorization: Bearer` header. Present only
            in the Create Realtime Transcription response.

            Opaque, up to 512 characters. Valid for this session while it is
            `OPEN`.
          example: rtt_5Hq3...
        maxDurationMs:
          type: integer
          format: int64
          description: >-
            Maximum session length, counted from the first connection. Currently
            10,800,000 (3 hours).
          example: 10800000
        audioDurationMs:
          type: integer
          format: int64
          description: >-
            Audio length Tiro has received so far, including connections that
            already closed.
          example: 0
        transcriptionLocale:
          type: string
          nullable: true
          description: >-
            Transcription locale applied to the session. `null` means auto
            detection.
          example: ko_KR
        translationLocale:
          type: string
          nullable: true
          description: Translation locale. `null` means no translation.
          example: en_US
        createdAt:
          type: string
          format: date-time
          description: When the session was created.
          example: '2026-11-05T09:00:00Z'
        endedAt:
          type: string
          format: date-time
          nullable: true
          description: When the session ended. `null` while `OPEN`.
          example: null
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - errorType
            - message
          properties:
            code:
              type: integer
              description: >
                6-digit error code in `AAABBB` form: first 3 digits match the
                HTTP status,

                last 3 digits are a per-status serial (e.g. `404018`). Use only
                when you need

                to distinguish specific error cases within the same HTTP status
                — values may be

                added or renumbered across releases. For general client
                branching, prefer `errorType`.
              example: 404018
            errorType:
              type: string
              description: >
                Stable, coarse-grained error category. Recommended default for
                client-side

                branching: the value-to-status mapping is part of the API
                contract and will not

                change without a breaking-change notice. Typical use:
                  - `unauthorized` → trigger re-authentication
                  - `forbidden` → surface a permission error to the user
                  - `not_found` → treat as missing resource
                  - `too_many_requests` → back off and retry
                  - `internal_error` → retry with exponential backoff
              enum:
                - bad_request
                - unauthorized
                - forbidden
                - not_found
                - not_acceptable
                - conflict
                - payload_too_large
                - unprocessable_entity
                - too_many_requests
                - internal_error
              example: not_found
            message:
              type: string
              description: >-
                Human-readable error message. Not stable; do not use for
                branching.
              example: 'No team found for user #217'
            detail:
              description: >-
                Additional error details. Authorization failures may include a
                reason and required scopes.
              oneOf:
                - type: string
                  nullable: true
                - type: object
                  additionalProperties: true
                  properties:
                    reason:
                      type: string
                      example: insufficient_scope
                    required:
                      type: array
                      items:
                        type: string
                      example:
                        - folder:read
              example: null
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >
        API key in format `{id}.{secret}`.


        The notes an endpoint returns depend on the key type. A **user key**
        reaches the

        notes that user can see in the app, including notes in their own private
        folders.

        A **system key** (workspace or organization, no user identity) reaches
        only notes

        that sit in a folder shared with all workspace members. Notes in a
        private folder,

        in a folder shared with only some members, or in no folder at all fall
        outside a

        system key's read scope, and scopes do not widen that boundary.


        List and search endpoints drop out-of-scope notes from the response
        without an

        error. Single-note reads and their sub-resources return `404`, the same
        response

        as a deleted note. See [What notes a system key
        reads](https://docs.tiro.ooo/en/developers/fundamentals/system-key-note-scope).

````

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