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

# Audio transcriptions

> Turn a WAV recording into text on one of your dedicated speech-to-text deployments. Shaped like OpenAI's audio transcriptions, so an OpenAI SDK's audio.transcriptions.create works by changing base_url alone. The deployment is billed for the GPU time it holds; the call itself is not billed.

## Which models accept this

Only a [dedicated deployment](https://docs.compute.prentis.ai/speech-to-text.md) of a model that transcribes, named in full as
`accounts/<account>/deployments/<deployment>`. A bare model name returns
`MODEL_CAPABILITY_UNSUPPORTED`.

## WAV only

`file` must be a WAV with PCM samples (16, 24 or 32-bit), up to 25 MB and 10 minutes. Other
formats return `MEDIA_UNSUPPORTED`; a longer or larger file returns `413 MEDIA_TOO_LARGE`.


## OpenAPI

````yaml openapi/prentis.openapi.yaml POST /audio/transcriptions
openapi: 3.1.0
info:
  title: Prentis Inference API
  version: 0.2.0
  summary: One inference API, reachable with an OpenAI client or an Anthropic client.
  description: >
    An OpenAI-compatible inference API. Point any OpenAI SDK at this base URL
    with a

    Prentis key and nothing else in your code changes.


    Anthropic clients are served too: the same host answers `/v1/messages`, and

    `x-api-key` is accepted alongside `Authorization: Bearer`.


    Parameters this API does not implement are ignored rather than rejected,
    except the

    few marked **not supported** below, which return `INVALID_REQUEST` so that a
    silently

    wrong answer is never returned in place of an error.
servers:
  - url: https://compute.prentis.ai/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: chat
  - name: completions
  - name: messages
  - name: responses
  - name: audio
  - name: models
paths:
  /audio/transcriptions:
    post:
      tags:
        - audio
      summary: Transcribe audio
      description: >-
        Turn a WAV recording into text on one of your dedicated speech-to-text
        deployments. Shaped like OpenAI's audio transcriptions, so an OpenAI
        SDK's audio.transcriptions.create works by changing base_url alone. The
        deployment is billed for the GPU time it holds; the call itself is not
        billed.
      operationId: createTranscription
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TranscriptionRequest'
      responses:
        '200':
          headers:
            x-request-id:
              $ref: '#/components/headers/x-request-id'
            x-provider-class:
              $ref: '#/components/headers/x-provider-class'
            x-config-version:
              $ref: '#/components/headers/x-config-version'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptionResponse'
              example:
                text: Can you move my three o'clock meeting to Thursday morning?
                usage:
                  type: duration
                  seconds: 4
            text/plain:
              schema:
                type: string
            text/event-stream:
              schema:
                type: string
              example: >-
                data: {"type":"transcript.text.delta","delta":"Can you move my"}


                data: {"type":"transcript.text.delta","delta":" three o'clock
                meeting to Thursday morning?"}


                data: {"type":"transcript.text.done","text":"Can you move my
                three o'clock meeting to Thursday
                morning?","usage":{"type":"duration","seconds":4}}
          description: >-
            OK. With `stream: true` the same call answers `text/event-stream`
            instead: data-only events, a `transcript.text.delta` for each new
            piece of text, then one `transcript.text.done` with the full text
            and the usage, which ends the stream. There is no `[DONE]` line.
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '402':
          $ref: '#/components/responses/Error402'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '413':
          $ref: '#/components/responses/Error413'
        '429':
          $ref: '#/components/responses/Error429'
        '500':
          $ref: '#/components/responses/Error500'
        '503':
          $ref: '#/components/responses/Error503'
        '504':
          $ref: '#/components/responses/Error504'
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |-
            curl https://compute.prentis.ai/v1/audio/transcriptions \
              -H "Authorization: Bearer $PRENTIS_API_KEY" \
              -F file=@recording.wav \
              -F model=accounts/<your-account>/deployments/<your-asr-deployment> \
              -F language=en
        - lang: python
          label: Python
          source: >-
            import os

            from openai import OpenAI


            client = OpenAI(base_url="https://compute.prentis.ai/v1",
            api_key=os.environ["PRENTIS_API_KEY"])


            with open("recording.wav", "rb") as f:
                resp = client.audio.transcriptions.create(
                    model="accounts/<your-account>/deployments/<your-asr-deployment>",
                    file=f,
                    language="en",
                )
            print(resp.text)
        - lang: typescript
          label: TypeScript
          source: |-
            import fs from "node:fs";
            import OpenAI from "openai";

            const client = new OpenAI({
              baseURL: "https://compute.prentis.ai/v1",
              apiKey: process.env.PRENTIS_API_KEY,
            });

            const resp = await client.audio.transcriptions.create({
              model: "accounts/<your-account>/deployments/<your-asr-deployment>",
              file: fs.createReadStream("recording.wav"),
              language: "en",
            });
            console.log(resp.text);
components:
  schemas:
    TranscriptionRequest:
      type: object
      required:
        - file
        - model
      properties:
        file:
          type: string
          format: binary
          description: >-
            The audio to transcribe: a WAV file (PCM, 16, 24 or 32-bit), up to
            25 MB and 10 minutes. Other formats return MEDIA_UNSUPPORTED.
        model:
          type: string
          examples:
            - accounts/acme/deployments/asr-voice-01
          description: >-
            The speech-to-text deployment that transcribes the audio,
            accounts/{account}/deployments/{deployment}. A model name, or a
            deployment of a model that does not transcribe, returns
            MODEL_CAPABILITY_UNSUPPORTED.
        language:
          type: string
          description: >-
            The language spoken, as an ISO-639-1 code such as en or zh. Leave it
            out and the model detects it.
        prompt:
          type: string
          description: >-
            Text that tells the model what it is about to hear: names, product
            terms, the spelling you expect. UTF-8 text, up to 64 KB.
        temperature:
          type: number
          minimum: 0
          maximum: 1
          description: >-
            Randomness when picking each word. 0 is the most repeatable and the
            usual choice for transcription.
        response_format:
          type: string
          enum:
            - json
            - text
          default: json
          description: >-
            json (the default) returns an object with text and usage; text
            returns the transcript as plain text. Timestamped formats
            (verbose_json, srt, vtt) are not supported.
        stream:
          type: boolean
          default: false
          description: >-
            Return the transcript as server-sent events as it is recognised,
            instead of one response at the end. The final event carries the full
            text and the usage.
    TranscriptionResponse:
      type: object
      required:
        - text
      properties:
        text:
          type: string
        usage:
          $ref: '#/components/schemas/TranscriptionUsage'
    TranscriptionUsage:
      type: object
      required:
        - type
        - seconds
      properties:
        type:
          type: string
          const: duration
        seconds:
          type: integer
          minimum: 0
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
            - type
            - code
          properties:
            message:
              type: string
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - not_found_error
                - rate_limit_error
                - server_error
                - service_unavailable
                - billing_error
            code:
              type: string
              enum:
                - INVALID_API_KEY
                - TENANT_SUSPENDED
                - MODEL_NOT_ALLOWED
                - OPERATION_NOT_ALLOWED
                - AGREEMENT_REQUIRED
                - INVALID_REQUEST
                - MODEL_NOT_FOUND
                - MODEL_CAPABILITY_UNSUPPORTED
                - CONTEXT_LENGTH_EXCEEDED
                - IDEMPOTENCY_CONFLICT
                - MEDIA_TOO_LARGE
                - MEDIA_FETCH_FAILED
                - MEDIA_UNSUPPORTED
                - TENANT_RATE_LIMITED
                - TENANT_BUDGET_EXCEEDED
                - INSUFFICIENT_BALANCE
                - PAYMENT_REQUIRED
                - CONTENT_BLOCKED_INPUT
                - CONTENT_BLOCKED_OUTPUT
                - UPSTREAM_RATE_LIMITED
                - UPSTREAM_UNAVAILABLE
                - UPSTREAM_TIMEOUT
                - PARTIAL_RESPONSE_TIMEOUT
                - UPSTREAM_CONTENT_REJECTED
                - DEPLOYMENT_SCALING_UP
                - REQUEST_CANCELLED
                - REQUEST_DEADLINE_EXCEEDED
                - INTERNAL
                - STORAGE_UNAVAILABLE
            param:
              type:
                - string
                - 'null'
  headers:
    x-request-id:
      schema:
        type: string
      required: true
      description: >-
        On every response, successes and errors alike. It is the handle that
        reaches the whole path your request took -- quote it when you ask us
        anything about a call.
    x-provider-class:
      schema:
        type: string
        enum:
          - primary
          - fallback
      description: >-
        primary or fallback: whether your call was served by the first choice or
        a standby. It never names who served it.
    x-config-version:
      schema:
        type: string
      description: >-
        Which version of the routing configuration was in effect for this call.
        Useful only when comparing two calls that behaved differently.
    Retry-After:
      schema:
        type: integer
        minimum: 0
      description: How many seconds to wait before retrying, on the responses that set it.
    x-ratelimit-limit-requests:
      schema:
        type: integer
        minimum: 0
    x-ratelimit-remaining-requests:
      schema:
        type: integer
        minimum: 0
    x-ratelimit-limit-tokens:
      schema:
        type: integer
        minimum: 0
    x-ratelimit-remaining-tokens:
      schema:
        type: integer
        minimum: 0
  responses:
    Error400:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `CONTENT_BLOCKED_INPUT`,
        `CONTENT_BLOCKED_OUTPUT`, `CONTEXT_LENGTH_EXCEEDED`, `INVALID_REQUEST`,
        `MEDIA_FETCH_FAILED`, `MEDIA_UNSUPPORTED`,
        `MODEL_CAPABILITY_UNSUPPORTED`, `UPSTREAM_CONTENT_REJECTED`. See the
        Errors page for what each one means, whether it is safe to retry, and
        whether it is billed.
    Error401:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `INVALID_API_KEY`. See the Errors page for what
        each one means, whether it is safe to retry, and whether it is billed.
    Error402:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `INSUFFICIENT_BALANCE`, `PAYMENT_REQUIRED`. See
        the Errors page for what each one means, whether it is safe to retry,
        and whether it is billed.
    Error403:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `AGREEMENT_REQUIRED`, `MODEL_NOT_ALLOWED`,
        `OPERATION_NOT_ALLOWED`, `TENANT_SUSPENDED`. See the Errors page for
        what each one means, whether it is safe to retry, and whether it is
        billed.
    Error404:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `MODEL_NOT_FOUND`. See the Errors page for what
        each one means, whether it is safe to retry, and whether it is billed.
    Error413:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `MEDIA_TOO_LARGE`. See the Errors page for what
        each one means, whether it is safe to retry, and whether it is billed.
    Error429:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
        x-ratelimit-limit-requests:
          $ref: '#/components/headers/x-ratelimit-limit-requests'
        x-ratelimit-remaining-requests:
          $ref: '#/components/headers/x-ratelimit-remaining-requests'
        x-ratelimit-limit-tokens:
          $ref: '#/components/headers/x-ratelimit-limit-tokens'
        x-ratelimit-remaining-tokens:
          $ref: '#/components/headers/x-ratelimit-remaining-tokens'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `TENANT_BUDGET_EXCEEDED`, `TENANT_RATE_LIMITED`,
        `UPSTREAM_RATE_LIMITED`. See the Errors page for what each one means,
        whether it is safe to retry, and whether it is billed.
    Error500:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `INTERNAL`. See the Errors page for what each
        one means, whether it is safe to retry, and whether it is billed.
    Error503:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `DEPLOYMENT_SCALING_UP`, `STORAGE_UNAVAILABLE`,
        `UPSTREAM_UNAVAILABLE`. See the Errors page for what each one means,
        whether it is safe to retry, and whether it is billed.
    Error504:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `PARTIAL_RESPONSE_TIMEOUT`,
        `REQUEST_DEADLINE_EXCEEDED`, `UPSTREAM_TIMEOUT`. See the Errors page for
        what each one means, whether it is safe to retry, and whether it is
        billed.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        `Authorization: Bearer <your API key>`. On `/v1/messages`, the
        Anthropic-style `x-api-key: <your API key>` header is accepted instead.

````

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