{"openapi":"3.1.0","info":{"title":"Loquino API","version":"1.0.0","description":"Public REST API for audio and video transcription: submit a file, poll status/result (or get notified by webhook), export. Audio and transcripts are processed within the EU."},"servers":[{"url":"https://loquino.de"}],"security":[{"bearerAuth":[]}],"paths":{"/api/v1/transcriptions":{"post":{"summary":"Submit a file for transcription","operationId":"createTranscription","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"Audio or video file."},"diarization":{"type":"boolean","default":true,"description":"Split by speakers (enabled by default)."},"webhook_url":{"type":"string","format":"uri","description":"Public URL to be notified on completion (optional). The notification carries only a signal; fetch the result via GET /api/v1/transcriptions/{id}."}}}}}},"responses":{"202":{"description":"Job accepted into the queue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Accepted"}}}},"401":{"$ref":"#/components/responses/Error"},"402":{"$ref":"#/components/responses/Error"},"413":{"$ref":"#/components/responses/Error"},"415":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}},"get":{"summary":"List account jobs","operationId":"listTranscriptions","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous response."}],"responses":{"200":{"description":"A page of the job list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscriptionList"}}}},"401":{"$ref":"#/components/responses/Error"}}}},"/api/v1/transcriptions/{id}":{"get":{"summary":"Job status and result","operationId":"getTranscription","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status/result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transcription"}}}},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/v1/transcriptions/{id}/export":{"get":{"summary":"Download the result as a file","operationId":"exportTranscription","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":true,"schema":{"type":"string","enum":["srt","txt","docx","xlsx"]}}],"responses":{"200":{"description":"Transcript file.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}}},"webhooks":{"transcriptionFinished":{"post":{"summary":"Job completion notification","operationId":"transcriptionWebhook","description":"Sent to webhook_url if it was provided when the job was created. The body contains only id/status/event; fetch the result separately via GET /api/v1/transcriptions/{id} with Authorization: Bearer sk_live_… . Retried with increasing backoff until the first 2xx response.","security":[],"parameters":[{"name":"X-Svitok-Event","in":"header","required":true,"schema":{"type":"string","enum":["transcription.completed","transcription.failed"]},"description":"Duplicates the body's event field — for routing."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Notification received. Any 2xx stops retries; any other response or a timeout triggers a scheduled retry."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key: Authorization: Bearer sk_live_…"}},"responses":{"Error":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Accepted":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["queued"]},"duration_sec":{"type":"integer"},"cost_kopecks":{"type":"integer"}}},"WebhookEvent":{"type":"object","required":["id","status","event"],"properties":{"id":{"type":"string","description":"Job identifier — use it with GET /api/v1/transcriptions/{id}."},"status":{"type":"string","enum":["done","failed"]},"event":{"type":"string","enum":["transcription.completed","transcription.failed"]}}},"Segment":{"type":"object","properties":{"start":{"type":"number"},"end":{"type":"number"},"text":{"type":"string"}}},"Speaker":{"type":"object","properties":{"start":{"type":"number"},"end":{"type":"number"},"speaker":{"type":"string","description":"A “Speaker N” label with no link to a real person."},"text":{"type":"string"}}},"Transcription":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["queued","running","done","failed"]},"duration_sec":{"type":["integer","null"]},"language":{"type":["string","null"]},"text":{"type":"string"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}},"speakers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/Speaker"}},"error":{"type":"string","description":"Human-readable reason (only when status=failed)."}}},"TranscriptionList":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"duration_sec":{"type":["integer","null"]}}}},"next_cursor":{"type":["string","null"]}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}