mirror of
https://github.com/rishikanthc/Scriberr.git
synced 2026-06-30 07:46:16 +00:00
1523 lines
38 KiB
JSON
1523 lines
38 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Scriberr API",
|
|
"version": "v1"
|
|
},
|
|
"paths": {
|
|
"/health": {
|
|
"get": {
|
|
"summary": "Health check",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Service is alive"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/health": {
|
|
"get": {
|
|
"summary": "API health check",
|
|
"responses": {
|
|
"200": {
|
|
"description": "API is alive"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/ready": {
|
|
"get": {
|
|
"summary": "Readiness check",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Service is ready"
|
|
},
|
|
"503": {
|
|
"description": "Service is not ready"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/registration-status": {
|
|
"get": {
|
|
"summary": "Get registration status",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Registration status"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/register": {
|
|
"post": {
|
|
"summary": "Register the local user",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Token response"
|
|
},
|
|
"409": {
|
|
"description": "Registration already completed"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/login": {
|
|
"post": {
|
|
"summary": "Log in",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Token response"
|
|
},
|
|
"401": {
|
|
"description": "Invalid credentials"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/refresh": {
|
|
"post": {
|
|
"summary": "Rotate refresh token",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Token response"
|
|
},
|
|
"401": {
|
|
"description": "Invalid refresh token"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/logout": {
|
|
"post": {
|
|
"summary": "Revoke refresh token",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Logout accepted"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/me": {
|
|
"get": {
|
|
"summary": "Get current user",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Current user"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/change-password": {
|
|
"post": {
|
|
"summary": "Change password",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Password changed"
|
|
},
|
|
"401": {
|
|
"description": "Authentication failed"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/change-username": {
|
|
"post": {
|
|
"summary": "Change username",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Username changed"
|
|
},
|
|
"401": {
|
|
"description": "Authentication failed"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/api-keys": {
|
|
"get": {
|
|
"summary": "List API keys",
|
|
"responses": {
|
|
"200": {
|
|
"description": "API key list"
|
|
},
|
|
"401": {
|
|
"description": "JWT required"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create API key",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key. Exact retries return the original successful response; mismatched reuse returns 409.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "API key created"
|
|
},
|
|
"401": {
|
|
"description": "JWT required"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/api-keys/{id}": {
|
|
"delete": {
|
|
"summary": "Delete API key",
|
|
"responses": {
|
|
"204": {
|
|
"description": "API key deleted"
|
|
},
|
|
"401": {
|
|
"description": "JWT required"
|
|
},
|
|
"404": {
|
|
"description": "API key not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/files": {
|
|
"get": {
|
|
"summary": "List files",
|
|
"parameters": [
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 100
|
|
}
|
|
},
|
|
{
|
|
"name": "cursor",
|
|
"in": "query",
|
|
"description": "Opaque pagination cursor returned as next_cursor."
|
|
},
|
|
{
|
|
"name": "q",
|
|
"in": "query",
|
|
"description": "Case-insensitive title search."
|
|
},
|
|
{
|
|
"name": "kind",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["audio", "video", "youtube"]
|
|
}
|
|
},
|
|
{
|
|
"name": "status",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["uploaded", "processing", "ready", "failed"]
|
|
}
|
|
},
|
|
{
|
|
"name": "updated_after",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
{
|
|
"name": "sort",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["created_at", "-created_at", "updated_at", "-updated_at", "title", "-title"]
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "File list"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"422": {
|
|
"description": "Invalid query parameter"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Upload file",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for upload creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "File uploaded"
|
|
},
|
|
"400": {
|
|
"description": "Invalid upload"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"413": {
|
|
"description": "Upload too large"
|
|
},
|
|
"415": {
|
|
"description": "Unsupported media type"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/files:import-youtube": {
|
|
"post": {
|
|
"summary": "Import YouTube media",
|
|
"description": "Creates a processing YouTube file resource, downloads media asynchronously through the configured importer, then transitions the file to ready or failed. Events are published as file.processing, file.ready, or file.failed.",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for YouTube import creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"202": {
|
|
"description": "YouTube import accepted with status processing"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"409": {
|
|
"description": "Idempotency key conflict"
|
|
},
|
|
"422": {
|
|
"description": "Validation error, including unsupported URL host or scheme"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/files/{id}": {
|
|
"get": {
|
|
"summary": "Get file",
|
|
"responses": {
|
|
"200": {
|
|
"description": "File"
|
|
},
|
|
"404": {
|
|
"description": "File not found"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update file metadata",
|
|
"responses": {
|
|
"200": {
|
|
"description": "File updated"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete file",
|
|
"responses": {
|
|
"204": {
|
|
"description": "File deleted"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/files/{id}/audio": {
|
|
"get": {
|
|
"summary": "Stream file audio",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Audio stream"
|
|
},
|
|
"206": {
|
|
"description": "Partial audio stream"
|
|
},
|
|
"416": {
|
|
"description": "Invalid range"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings": {
|
|
"get": {
|
|
"summary": "List recording sessions",
|
|
"description": "Lists browser recording sessions for the authenticated user. Recording sessions are the durable ingest workflow before a finalized audio file exists.",
|
|
"parameters": [
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 100
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Recording session list"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create recording session",
|
|
"description": "Creates a durable browser recording session before chunk upload begins. Chunks are uploaded separately and finalization is requested with the stop command.",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Recording session created"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"422": {
|
|
"description": "Invalid recording request"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings/{id}": {
|
|
"get": {
|
|
"summary": "Get recording session",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Recording session"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Recording not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings/{id}/chunks/{chunk_index}": {
|
|
"put": {
|
|
"summary": "Upload recording chunk",
|
|
"description": "Stores one browser MediaRecorder chunk. The same chunk index may be retried idempotently when checksum and size match.",
|
|
"parameters": [
|
|
{
|
|
"name": "X-Chunk-SHA256",
|
|
"in": "header",
|
|
"description": "Optional hex SHA-256 digest for idempotency and integrity validation."
|
|
},
|
|
{
|
|
"name": "X-Chunk-Duration-Ms",
|
|
"in": "header",
|
|
"description": "Optional chunk duration in milliseconds."
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Chunk stored"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"409": {
|
|
"description": "Chunk conflicts with existing data or session state"
|
|
},
|
|
"413": {
|
|
"description": "Chunk is too large"
|
|
},
|
|
"422": {
|
|
"description": "Invalid chunk request"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings/{id}:stop": {
|
|
"post": {
|
|
"summary": "Stop recording session",
|
|
"description": "Marks recording ingest complete and queues durable finalization into one audio file.",
|
|
"responses": {
|
|
"202": {
|
|
"description": "Recording queued for finalization"
|
|
},
|
|
"409": {
|
|
"description": "Recording cannot be stopped from its current state"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings/{id}:cancel": {
|
|
"post": {
|
|
"summary": "Cancel recording session",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Recording canceled"
|
|
},
|
|
"409": {
|
|
"description": "Recording cannot be canceled from its current state"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/recordings/{id}:retry-finalize": {
|
|
"post": {
|
|
"summary": "Retry recording finalization",
|
|
"responses": {
|
|
"202": {
|
|
"description": "Recording finalization queued"
|
|
},
|
|
"409": {
|
|
"description": "Recording is not retryable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions": {
|
|
"get": {
|
|
"summary": "List transcriptions",
|
|
"parameters": [
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 100
|
|
}
|
|
},
|
|
{
|
|
"name": "cursor",
|
|
"in": "query",
|
|
"description": "Opaque pagination cursor returned as next_cursor."
|
|
},
|
|
{
|
|
"name": "q",
|
|
"in": "query",
|
|
"description": "Case-insensitive title search."
|
|
},
|
|
{
|
|
"name": "status",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["queued", "processing", "completed", "failed", "canceled"]
|
|
}
|
|
},
|
|
{
|
|
"name": "updated_after",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
{
|
|
"name": "sort",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["created_at", "-created_at", "updated_at", "-updated_at", "title", "-title"]
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Transcription list"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"422": {
|
|
"description": "Invalid query parameter"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create transcription",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for transcription creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"202": {
|
|
"description": "Transcription queued"
|
|
},
|
|
"404": {
|
|
"description": "Source file not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions:submit": {
|
|
"post": {
|
|
"summary": "Upload and create transcription",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for combined upload and transcription creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"202": {
|
|
"description": "File uploaded and transcription queued"
|
|
},
|
|
"400": {
|
|
"description": "Invalid multipart request"
|
|
},
|
|
"415": {
|
|
"description": "Unsupported media type"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}": {
|
|
"get": {
|
|
"summary": "Get transcription",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Transcription"
|
|
},
|
|
"404": {
|
|
"description": "Transcription not found"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update transcription metadata",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Transcription updated"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete transcription",
|
|
"responses": {
|
|
"204": {
|
|
"description": "Transcription deleted"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}:cancel": {
|
|
"post": {
|
|
"summary": "Cancel transcription",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for cancel command.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Transcription canceled"
|
|
},
|
|
"409": {
|
|
"description": "State conflict"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}:retry": {
|
|
"post": {
|
|
"summary": "Retry transcription",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for retry command.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"202": {
|
|
"description": "Retry queued"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/transcript": {
|
|
"get": {
|
|
"summary": "Get transcript",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Transcript"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/annotations": {
|
|
"get": {
|
|
"summary": "List transcript annotations",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^tr_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "kind",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": ["highlight", "note"]
|
|
}
|
|
},
|
|
{
|
|
"name": "updated_after",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
{
|
|
"name": "cursor",
|
|
"in": "query",
|
|
"description": "Opaque pagination cursor returned as next_cursor."
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 100
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Annotation list"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Transcription not found"
|
|
},
|
|
"422": {
|
|
"description": "Invalid query parameter"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create transcript annotation",
|
|
"description": "Creates a note or highlight anchored to transcript timing and optional word or character offsets.",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^tr_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for annotation creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AnnotationCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "Annotation created"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Transcription not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/annotations/{annotation_id}": {
|
|
"get": {
|
|
"summary": "Get transcript annotation",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Annotation"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Annotation not found"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update transcript annotation",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AnnotationUpdateRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Annotation updated"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Annotation not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete transcript annotation",
|
|
"responses": {
|
|
"204": {
|
|
"description": "Annotation deleted"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Annotation not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/annotations/{annotation_id}/entries": {
|
|
"post": {
|
|
"summary": "Create transcript note entry",
|
|
"description": "Adds a note entry to an existing note annotation root. The parent annotation must be kind note.",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^tr_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "annotation_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^ann_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for note entry creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AnnotationEntryRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"description": "Note entry created"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Annotation not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/annotations/{annotation_id}/entries/{entry_id}": {
|
|
"patch": {
|
|
"summary": "Update transcript note entry",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^tr_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "annotation_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^ann_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "entry_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^annent_.+"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AnnotationEntryRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Note entry updated"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Entry not found"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete transcript note entry",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^tr_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "annotation_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^ann_.+"
|
|
}
|
|
},
|
|
{
|
|
"name": "entry_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"pattern": "^annent_.+"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"204": {
|
|
"description": "Note entry deleted"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Entry not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/audio": {
|
|
"get": {
|
|
"summary": "Stream transcription audio",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Audio stream"
|
|
},
|
|
"206": {
|
|
"description": "Partial audio stream"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/events": {
|
|
"get": {
|
|
"summary": "Stream transcription events",
|
|
"description": "Authenticated Server-Sent Events stream filtered to the requested transcription. Replay with Last-Event-ID is not supported yet.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "SSE stream using text/event-stream"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
},
|
|
"404": {
|
|
"description": "Transcription not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/logs": {
|
|
"get": {
|
|
"summary": "Get transcription logs",
|
|
"responses": {
|
|
"501": {
|
|
"description": "Deferred placeholder"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/transcriptions/{id}/executions": {
|
|
"get": {
|
|
"summary": "Get transcription executions",
|
|
"responses": {
|
|
"501": {
|
|
"description": "Deferred placeholder"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/profiles": {
|
|
"get": {
|
|
"summary": "List profiles",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile list"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create profile",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for profile creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Profile created"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/profiles/{id}": {
|
|
"get": {
|
|
"summary": "Get profile",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile"
|
|
},
|
|
"404": {
|
|
"description": "Profile not found"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update profile",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile updated"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete profile",
|
|
"responses": {
|
|
"204": {
|
|
"description": "Profile deleted"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/profiles/{id}:set-default": {
|
|
"post": {
|
|
"summary": "Set default profile",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for set-default command.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Profile set as default"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/settings": {
|
|
"get": {
|
|
"summary": "Get settings",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Settings"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update settings",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Settings updated"
|
|
},
|
|
"422": {
|
|
"description": "Validation error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/models": {
|
|
"get": {
|
|
"summary": "List configured chat models",
|
|
"description": "Returns active LLM provider models with context-window metadata. Returns LLM_PROVIDER_NOT_CONFIGURED when chat cannot run.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Chat model capabilities"
|
|
},
|
|
"409": {
|
|
"description": "LLM provider is not configured"
|
|
},
|
|
"503": {
|
|
"description": "LLM provider is unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions": {
|
|
"get": {
|
|
"summary": "List chat sessions for a parent transcript",
|
|
"parameters": [
|
|
{
|
|
"name": "parent_transcription_id",
|
|
"in": "query",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"example": "tr_123"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Chat session collection envelope"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create chat session",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for session creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Chat session created with parent transcript context"
|
|
},
|
|
"409": {
|
|
"description": "LLM provider is not configured"
|
|
},
|
|
"422": {
|
|
"description": "Requested model is not available"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}": {
|
|
"get": {
|
|
"summary": "Get chat session",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Chat session"
|
|
},
|
|
"404": {
|
|
"description": "Chat session not found"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"summary": "Update chat session",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Chat session updated"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Delete chat session",
|
|
"responses": {
|
|
"204": {
|
|
"description": "Chat session deleted"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}/context": {
|
|
"get": {
|
|
"summary": "List chat context sources",
|
|
"description": "Returns context source metadata and state only; raw transcript text and compacted snapshots are not exposed.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Context source collection envelope"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}/context/transcripts": {
|
|
"post": {
|
|
"summary": "Add transcript context source",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for context-source creation.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Context source added"
|
|
},
|
|
"404": {
|
|
"description": "Transcript not found or not completed"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}/context/transcripts/{context_source_id}": {
|
|
"patch": {
|
|
"summary": "Update context source state",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Context source updated"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Remove context source",
|
|
"responses": {
|
|
"204": {
|
|
"description": "Context source removed"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}/messages:stream": {
|
|
"post": {
|
|
"summary": "Create user message and stream assistant response",
|
|
"description": "Server-Sent Events stream. Reasoning and final Markdown content are emitted separately with chat.delta.reasoning and chat.delta.content. The terminal event includes assistant_message.content and assistant_message.reasoning_content.",
|
|
"parameters": [
|
|
{
|
|
"name": "Idempotency-Key",
|
|
"in": "header",
|
|
"required": false,
|
|
"description": "Optional retry key for stream start.",
|
|
"schema": {
|
|
"type": "string",
|
|
"maxLength": 128
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "SSE stream using text/event-stream"
|
|
},
|
|
"409": {
|
|
"description": "LLM provider is not configured"
|
|
},
|
|
"422": {
|
|
"description": "Validation error or model unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/runs/{run_id}:cancel": {
|
|
"post": {
|
|
"summary": "Cancel chat generation run",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Run canceled or already terminal"
|
|
},
|
|
"404": {
|
|
"description": "Run not found"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/chat/sessions/{session_id}/title:generate": {
|
|
"post": {
|
|
"summary": "Generate chat session title",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Generated title"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/events": {
|
|
"get": {
|
|
"summary": "Stream global events",
|
|
"description": "Authenticated Server-Sent Events stream for API-visible file, transcription, profile, and settings changes. Replay with Last-Event-ID is not supported yet.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "SSE stream using text/event-stream"
|
|
},
|
|
"401": {
|
|
"description": "Authentication required"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/models/transcription": {
|
|
"get": {
|
|
"summary": "List transcription models",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Model capabilities"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/queue": {
|
|
"get": {
|
|
"summary": "Queue stats",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Queue stats"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {
|
|
"AnnotationAnchor": {
|
|
"type": "object",
|
|
"required": ["start_ms", "end_ms"],
|
|
"properties": {
|
|
"start_ms": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"end_ms": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"start_word": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"end_word": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"start_char": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"end_char": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"text_hash": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"AnnotationCreateRequest": {
|
|
"type": "object",
|
|
"required": ["kind", "quote", "anchor"],
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"enum": ["highlight", "note"]
|
|
},
|
|
"content": {
|
|
"type": "string"
|
|
},
|
|
"color": {
|
|
"type": "string"
|
|
},
|
|
"quote": {
|
|
"type": "string"
|
|
},
|
|
"anchor": {
|
|
"$ref": "#/components/schemas/AnnotationAnchor"
|
|
}
|
|
}
|
|
},
|
|
"AnnotationUpdateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"content": {
|
|
"type": "string"
|
|
},
|
|
"color": {
|
|
"type": "string"
|
|
},
|
|
"quote": {
|
|
"type": "string"
|
|
},
|
|
"anchor": {
|
|
"$ref": "#/components/schemas/AnnotationAnchor"
|
|
}
|
|
}
|
|
},
|
|
"AnnotationEntryRequest": {
|
|
"type": "object",
|
|
"required": ["content"],
|
|
"properties": {
|
|
"content": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"bearerAuth": {
|
|
"type": "http",
|
|
"scheme": "bearer"
|
|
},
|
|
"apiKeyAuth": {
|
|
"type": "apiKey",
|
|
"in": "header",
|
|
"name": "X-API-Key"
|
|
}
|
|
}
|
|
}
|
|
}
|