{
  "openapi": "3.1.0",
  "info": {
    "title": "KolWrite Speech-to-Text API",
    "version": "2026-10-08",
    "summary": "Asynchronous transcription of audio and video in 100 languages.",
    "description": "Start a job with POST /transcribe, read it with GET /transcribe/{jobId} or receive a webhook. Models are priced in usage credits per audio hour (1 credit = US$1.20); see https://console.kolwrite.com/llms/pricing.md. Human reference: https://console.kolwrite.com/public_api_docs.",
    "termsOfService": "https://www.kolwrite.com/tos_pp.html#terms",
    "contact": {
      "name": "KolWrite",
      "email": "info@kolwrite.com",
      "url": "https://console.kolwrite.com/"
    }
  },
  "externalDocs": {
    "description": "KolWrite API documentation",
    "url": "https://console.kolwrite.com/public_api_docs"
  },
  "servers": [
    {
      "url": "https://app.kolwrite.com"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/upload": {
      "post": {
        "operationId": "createUpload",
        "summary": "Upload a local file and get an audio_url",
        "description": "With `content` (Base64, up to 4194304 decoded bytes) the file is stored directly and `fileUrl` is returned. Without `content` the response is a signed storage form for files up to 104857600 bytes: POST the file to `uploadUrl` with `uploadFields` (no API key), then use `fileUrl`. The form is valid for 60 minutes; `fileUrl` for 24 hours.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadRequest"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Upload created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          },
          "default": {
            "description": "Error."
          }
        }
      }
    },
    "/transcribe": {
      "post": {
        "operationId": "createTranscription",
        "summary": "Start a transcription job",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Job accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobCreated"
                }
              }
            }
          },
          "default": {
            "description": "Error."
          }
        }
      }
    },
    "/transcribe/{jobId}": {
      "get": {
        "operationId": "getTranscription",
        "summary": "Get the status and result of a job",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "The jobId returned by POST /transcribe.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "2XX": {
            "description": "The job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "description": "Error."
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Current service state",
        "security": [],
        "responses": {
          "200": {
            "description": "Operational or degraded; JSON status details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "503": {
            "description": "State unknown or unavailable; JSON status details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/health/history": {
      "get": {
        "operationId": "getHealthHistory",
        "summary": "Compact availability history",
        "security": [],
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability history.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "transcriptionEvent": {
      "post": {
        "summary": "transcription.completed or transcription.failed",
        "description": "Sent to webhook_url. Return any 2xx. At-least-once delivery; deduplicate on X-KolWrite-Delivery-Id. With webhook_secret, X-KolWrite-Signature is sha256=<hex> of HMAC-SHA256(timestamp + \".\" + raw body).",
        "parameters": [
          {
            "name": "X-KolWrite-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KolWrite-Job-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KolWrite-Delivery-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KolWrite-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KolWrite-Signature",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "UploadRequest": {
        "type": "object",
        "required": [
          "filename"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "examples": [
              "meeting.mp3"
            ]
          },
          "contentType": {
            "type": "string",
            "description": "Optional; inferred from the filename.",
            "examples": [
              "audio/mpeg"
            ]
          },
          "content": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "Raw Base64 media bytes without a data: prefix, up to 4194304 decoded bytes. Omit for a signed upload form."
          }
        }
      },
      "UploadResponse": {
        "type": "object",
        "properties": {
          "fileUrl": {
            "type": "string",
            "format": "uri",
            "description": "Use as audio_url."
          },
          "uploadUrl": {
            "type": "string",
            "format": "uri",
            "description": "Signed form only."
          },
          "uploadFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Signed form only; send exactly as returned."
          },
          "uploadExpiresIn": {
            "type": "integer",
            "description": "Signed form only; seconds the form stays valid."
          }
        },
        "required": [
          "fileUrl"
        ]
      },
      "TranscriptionRequest": {
        "type": "object",
        "required": [
          "audio_url"
        ],
        "properties": {
          "audio_url": {
            "type": "string",
            "format": "uri",
            "description": "Publicly accessible URL of the audio or video file."
          },
          "language": {
            "type": "string",
            "default": "auto",
            "description": "Language code hint, e.g. \"he\", \"en\", \"es\". See /llms/languages.md.",
            "enum": [
              "auto",
              "af",
              "sq",
              "am",
              "ar",
              "hy",
              "as",
              "az",
              "ba",
              "eu",
              "be",
              "bn",
              "bs",
              "br",
              "bg",
              "my",
              "ca",
              "zh",
              "hr",
              "cs",
              "da",
              "nl",
              "en",
              "et",
              "fo",
              "fi",
              "fr",
              "gl",
              "ka",
              "de",
              "el",
              "gu",
              "ht",
              "ha",
              "haw",
              "he",
              "hi",
              "hu",
              "is",
              "id",
              "it",
              "ja",
              "jw",
              "kn",
              "kk",
              "km",
              "ko",
              "lo",
              "la",
              "lv",
              "ln",
              "lt",
              "lb",
              "mk",
              "mg",
              "ms",
              "ml",
              "mt",
              "mi",
              "mr",
              "mn",
              "ne",
              "no",
              "nn",
              "oc",
              "ps",
              "fa",
              "pl",
              "pt",
              "pa",
              "ro",
              "ru",
              "sa",
              "sr",
              "sn",
              "sd",
              "si",
              "sk",
              "sl",
              "so",
              "es",
              "su",
              "sw",
              "sv",
              "tl",
              "tg",
              "ta",
              "tt",
              "te",
              "th",
              "bo",
              "tr",
              "tk",
              "uk",
              "ur",
              "uz",
              "vi",
              "cy",
              "yi",
              "yo",
              "zu"
            ]
          },
          "translate_to": {
            "type": "string",
            "description": "Target language code. Oracle family only.",
            "enum": [
              "af",
              "sq",
              "am",
              "ar",
              "hy",
              "as",
              "az",
              "ba",
              "eu",
              "be",
              "bn",
              "bs",
              "br",
              "bg",
              "my",
              "ca",
              "zh",
              "hr",
              "cs",
              "da",
              "nl",
              "en",
              "et",
              "fo",
              "fi",
              "fr",
              "gl",
              "ka",
              "de",
              "el",
              "gu",
              "ht",
              "ha",
              "haw",
              "he",
              "hi",
              "hu",
              "is",
              "id",
              "it",
              "ja",
              "jw",
              "kn",
              "kk",
              "km",
              "ko",
              "lo",
              "la",
              "lv",
              "ln",
              "lt",
              "lb",
              "mk",
              "mg",
              "ms",
              "ml",
              "mt",
              "mi",
              "mr",
              "mn",
              "ne",
              "no",
              "nn",
              "oc",
              "ps",
              "fa",
              "pl",
              "pt",
              "pa",
              "ro",
              "ru",
              "sa",
              "sr",
              "sn",
              "sd",
              "si",
              "sk",
              "sl",
              "so",
              "es",
              "su",
              "sw",
              "sv",
              "tl",
              "tg",
              "ta",
              "tt",
              "te",
              "th",
              "bo",
              "tr",
              "tk",
              "uk",
              "ur",
              "uz",
              "vi",
              "cy",
              "yi",
              "yo",
              "zu"
            ]
          },
          "word_timestamps": {
            "type": "boolean",
            "default": true
          },
          "model": {
            "type": "string",
            "default": "core",
            "enum": [
              "base",
              "oracle_mini",
              "oracle",
              "oracle_pro",
              "oracle_max",
              "core",
              "edge"
            ],
            "description": "base: 0.40 credits/hour; oracle_mini: 0.80 credits/hour; oracle: 1.20 credits/hour; oracle_pro: 1.40 credits/hour; oracle_max: 3.00 credits/hour; core: 1.00 credits/hour (legacy); edge: 1.20 credits/hour (legacy)"
          },
          "output_format": {
            "type": "string",
            "default": "json",
            "enum": [
              "json",
              "txt",
              "srt"
            ]
          },
          "include_diarization": {
            "type": "boolean",
            "default": false
          },
          "pro_diarization": {
            "type": "boolean",
            "default": false,
            "description": "Adds 0.20 credits per audio hour."
          },
          "num_speakers": {
            "type": "integer",
            "minimum": 1,
            "description": "Used only with include_diarization; omit to auto-detect."
          },
          "channel_speaker_separation": {
            "type": "string",
            "default": "off",
            "enum": [
              "off",
              "standard",
              "overlap"
            ],
            "description": "2–8 channel audio; cannot be combined with diarization."
          },
          "channel_labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Zero-based channel index map, e.g. {\"0\":\"Agent\",\"1\":\"Customer\"}."
          },
          "webhook_url": {
            "type": "string",
            "format": "uri"
          },
          "webhook_secret": {
            "type": "string"
          }
        }
      },
      "JobCreated": {
        "type": "object",
        "required": [
          "jobId"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          }
        }
      },
      "Job": {
        "type": "object",
        "required": [
          "jobId",
          "status"
        ],
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "IN_PROGRESS",
              "COMPLETED",
              "FAILED"
            ]
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TranscriptResult"
              },
              {
                "type": "string",
                "description": "TXT or SRT output."
              }
            ]
          },
          "error": {
            "type": "string"
          }
        }
      },
      "TranscriptResult": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string"
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Segment"
            }
          }
        }
      },
      "Segment": {
        "type": "object",
        "properties": {
          "start": {
            "type": "number",
            "description": "Start time in seconds."
          },
          "end": {
            "type": "number",
            "description": "End time in seconds."
          },
          "text": {
            "type": "string"
          },
          "speaker": {
            "type": "string",
            "description": "Speaker label when diarization is enabled, e.g. \"Speaker 1\"."
          },
          "words": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Word"
            }
          }
        },
        "required": [
          "start",
          "end",
          "text"
        ]
      },
      "Word": {
        "type": "object",
        "properties": {
          "start": {
            "type": "number"
          },
          "end": {
            "type": "number"
          },
          "word": {
            "type": "string"
          }
        },
        "required": [
          "start",
          "end",
          "word"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "transcription.completed",
              "transcription.failed"
            ]
          },
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "model": {
            "type": "string"
          },
          "output_format": {
            "type": "string"
          },
          "result_available": {
            "type": "boolean"
          },
          "result_omitted": {
            "type": "boolean"
          },
          "result_size_bytes": {
            "type": "integer"
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TranscriptResult"
              },
              {
                "type": "string"
              }
            ]
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
