openapi: 3.0.3
info:
  title: ConvertAudioToText Public API
  version: "1.0.0"
  description: >-
    Public transcription API for ConvertAudioToText. Submit an audio or video
    file (by upload or URL), poll for the result, and export the transcript as
    SRT, WebVTT, plain text, or JSON. Billing is pay-per-success: minutes are
    deducted only when a transcription completes successfully — failed jobs
    are never charged. This document describes only the public developer
    surface served at /v1. The dashboard and admin APIs are not part of this
    contract and are not documented here.
  contact:
    name: ConvertAudioToText
    url: https://convertaudiototext.com
  termsOfService: https://convertaudiototext.com/api-disclosure

servers:
  - url: https://convertaudiototext.com/v1
    description: Public API (primary origin)
  - url: https://api.convertaudiototext.com/v1
    description: Public API (direct backend origin)

security:
  - apiKey: []

tags:
  - name: Transcription
    description: Create transcription jobs, read results, and export transcripts.

paths:
  /transcribe:
    post:
      tags: [Transcription]
      summary: Create a transcription job
      description: >-
        Submit a media file for transcription, either by public URL or by file
        upload. Returns immediately with a job id; the transcript is produced
        asynchronously. Requires an API key with the `transcribe` scope.
      operationId: createTranscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [source]
              properties:
                source:
                  type: string
                  enum: [url, upload]
                  default: url
                input_url:
                  type: string
                  format: uri
                  description: URL of the audio/video file (required when source is url).
                language:
                  type: string
                  default: en
                  description: BCP-47 / ISO language hint. Defaults to English.
          multipart/form-data:
            schema:
              type: object
              required: [source, file]
              properties:
                source:
                  type: string
                  enum: [upload]
                file:
                  type: string
                  format: binary
                  description: Audio/video file to transcribe.
                language:
                  type: string
                  default: en
      responses:
        '201':
          description: Job accepted for asynchronous processing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscribeAccepted'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/TooManyRequests'
    get:
      tags: [Transcription]
      summary: List transcription jobs
      description: List the jobs on the account behind the API key.
      operationId: listTranscriptions
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: status
          in: query
          schema:
            type: string
            enum: [queued, processing, completed, failed]
      responses:
        '200':
          description: A page of jobs.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobs:
                    type: array
                    items:
                      $ref: '#/components/schemas/Job'
                  total:
                    type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /transcribe/{job_id}:
    get:
      tags: [Transcription]
      summary: Get a transcription result
      description: >-
        Read one job and its transcript. Poll this endpoint until `status` is
        `completed`.
      operationId: getTranscription
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: The job and, once ready, its transcript.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptResult'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /transcribe/{job_id}/srt:
    get:
      tags: [Transcription]
      summary: Export as SRT subtitles
      operationId: exportSrt
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: SRT subtitle file.
          content:
            application/x-subrip:
              schema:
                type: string
            text/plain:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /transcribe/{job_id}/vtt:
    get:
      tags: [Transcription]
      summary: Export as WebVTT subtitles
      operationId: exportVtt
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: WebVTT subtitle file.
          content:
            text/vtt:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /transcribe/{job_id}/txt:
    get:
      tags: [Transcription]
      summary: Export as plain text
      operationId: exportTxt
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: Plain-text transcript.
          content:
            text/plain:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /transcribe/{job_id}/json:
    get:
      tags: [Transcription]
      summary: Export as JSON
      operationId: exportJson
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: Structured JSON transcript.
          content:
            application/json:
              schema:
                type: object
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        API key with the `ck_live_` (production) or `ck_test_` (test) prefix,
        sent as `Authorization: Bearer ck_live_...`. Create a key on the
        Developer or Business plan at
        https://convertaudiototext.com/dashboard/developers. Session JWTs are
        rejected on this API; only ck_live_/ck_test_ keys are accepted, and each
        must carry the `transcribe` scope.

  parameters:
    JobId:
      name: job_id
      in: path
      required: true
      schema:
        type: string
        format: uuid

  responses:
    BadRequest:
      description: The request was malformed or missing required fields.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key. Session JWTs are rejected on this API.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: The key is valid but lacks the required `transcribe` scope.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: >-
        The account has no transcription minutes remaining, or API access is not
        included on the current plan.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: No job with that id belongs to this account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooManyRequests:
      description: Rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

  schemas:
    Error:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
        request_id:
          type: string

    TranscribeAccepted:
      type: object
      properties:
        job_id:
          type: string
          format: uuid
        status:
          type: string
          example: queued
        message:
          type: string

    Job:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        status:
          type: string
          enum: [uploading, queued, processing, completed, failed]
        source_type:
          type: string
          enum: [upload, url]
        language:
          type: string
        duration:
          type: number
        error_message:
          type: string
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time

    TranscriptResult:
      type: object
      properties:
        job_id:
          type: string
          format: uuid
        status:
          type: string
          enum: [uploading, queued, processing, completed, failed]
        transcript:
          type: string
        edited_text:
          type: string
        summary:
          type: string
        topics:
          type: array
          items:
            type: string
        sentiments:
          type: array
          items:
            type: object
        utterances:
          type: array
          items:
            type: object
            properties:
              speaker:
                type: integer
              speaker_name:
                type: string
              start:
                type: number
              end:
                type: number
              text:
                type: string
              confidence:
                type: number
        current_version:
          type: integer
        review_status:
          type: string
