{
    "schemes": [],
    "swagger": "2.0",
    "info": {
        "description": "REST API for SparkProctoring — proctoring session management, telemetry, and video streaming.",
        "title": "SparkProctoring API",
        "contact": {},
        "version": "1.0"
    },
    "host": "sparkguardian.ru",
    "basePath": "/api/v1",
    "paths": {
        "/sessions": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Paginated list of all sessions with summary stats.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "sessions"
                ],
                "summary": "List proctoring sessions",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Max results (default 50, max 100)",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset (default 0)",
                        "name": "offset",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/handler.SessionListResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Only teachers and admins may create sessions. Returns session_key for agent auth.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "sessions"
                ],
                "summary": "Create a proctoring session",
                "parameters": [
                    {
                        "description": "Session title",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/handler.CreateSessionRequest"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "$ref": "#/definitions/handler.CreateSessionResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "Forbidden",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sessions/{id}": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Returns session info, stream metadata, and event counts.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "sessions"
                ],
                "summary": "Get session details",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/handler.SessionDetailResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sessions/{id}/events": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Downloads encrypted .bin chunks from S3, decrypts, and returns parsed events with optional time range filtering.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "telemetry"
                ],
                "summary": "Get parsed telemetry events",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Start timestamp (Unix ms)",
                        "name": "from",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "End timestamp (Unix ms)",
                        "name": "to",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/handler.ParsedEventsResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sessions/{id}/playlist/{stream_type}.m3u8": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Returns M3U8 playlist for a session's video stream.",
                "produces": [
                    "application/vnd.apple.mpegurl"
                ],
                "tags": [
                    "streaming"
                ],
                "summary": "Get HLS playlist",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "enum": [
                            "screen",
                            "webcam"
                        ],
                        "type": "string",
                        "description": "Stream type",
                        "name": "stream_type",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sessions/{id}/segment/{stream_type}/{chunk_idx}.ts": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Proxies a .ts video segment from S3.",
                "produces": [
                    "video/mp2t"
                ],
                "tags": [
                    "streaming"
                ],
                "summary": "Get video segment",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "enum": [
                            "screen",
                            "webcam"
                        ],
                        "type": "string",
                        "description": "Stream type",
                        "name": "stream_type",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Chunk index",
                        "name": "chunk_idx",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sessions/{id}/telemetry": {
            "get": {
                "security": [
                    {
                        "ForwardAuth": []
                    }
                ],
                "description": "Returns all telemetry events for a session.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "telemetry"
                ],
                "summary": "List telemetry events",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "type": "array",
                            "items": {
                                "$ref": "#/definitions/handler.TelemetryEvent"
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/upload": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "Upload .ts (video) or .bin (event) file for a session. Max 64 MB.",
                "consumes": [
                    "multipart/form-data"
                ],
                "tags": [
                    "agent"
                ],
                "summary": "Upload a video or event chunk",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Session ID",
                        "name": "session_id",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Chunk index",
                        "name": "chunk_idx",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "enum": [
                            "screen",
                            "webcam"
                        ],
                        "type": "string",
                        "description": "Stream type (default: screen)",
                        "name": "stream_type",
                        "in": "formData"
                    },
                    {
                        "type": "file",
                        "description": "Chunk file (.ts or .bin)",
                        "name": "file",
                        "in": "formData",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/handler.ErrorResponse"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "handler.CreateSessionRequest": {
            "type": "object",
            "properties": {
                "title": {
                    "type": "string",
                    "example": "Экзамен по ОС"
                }
            }
        },
        "handler.CreateSessionResponse": {
            "type": "object",
            "properties": {
                "created_at": {
                    "type": "string",
                    "example": "2026-04-05T12:00:00Z"
                },
                "id": {
                    "type": "integer",
                    "example": 1
                },
                "session_key": {
                    "type": "string",
                    "example": "1"
                },
                "status": {
                    "type": "string",
                    "example": "pending"
                },
                "title": {
                    "type": "string",
                    "example": "Экзамен по ОС"
                }
            }
        },
        "handler.ErrorResponse": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "example": "NOT_FOUND"
                },
                "error": {
                    "type": "string",
                    "example": "session not found"
                }
            }
        },
        "handler.ParsedEvent": {
            "type": "object",
            "properties": {
                "data": {
                    "type": "array",
                    "items": {
                        "type": "integer"
                    }
                },
                "event_type": {
                    "type": "string",
                    "example": "keyboard"
                },
                "timestamp": {
                    "type": "integer",
                    "example": 1711360200000
                }
            }
        },
        "handler.ParsedEventsResponse": {
            "type": "object",
            "properties": {
                "count": {
                    "type": "integer",
                    "example": 42
                },
                "events": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/handler.ParsedEvent"
                    }
                },
                "session_id": {
                    "type": "integer",
                    "example": 1
                }
            }
        },
        "handler.SessionDetailResponse": {
            "type": "object",
            "properties": {
                "session": {
                    "$ref": "#/definitions/handler.SessionSummary"
                },
                "streams": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/handler.StreamInfo"
                    }
                }
            }
        },
        "handler.SessionListResponse": {
            "type": "object",
            "properties": {
                "limit": {
                    "type": "integer",
                    "example": 50
                },
                "offset": {
                    "type": "integer",
                    "example": 0
                },
                "sessions": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/handler.SessionSummary"
                    }
                },
                "total": {
                    "type": "integer",
                    "example": 5
                }
            }
        },
        "handler.SessionSummary": {
            "type": "object",
            "properties": {
                "chunks_total": {
                    "type": "integer",
                    "example": 42
                },
                "ended_at": {
                    "type": "string"
                },
                "events_total": {
                    "type": "integer",
                    "example": 128
                },
                "id": {
                    "type": "string",
                    "example": "1"
                },
                "started_at": {
                    "type": "string",
                    "example": "2026-04-05T12:00:00Z"
                },
                "status": {
                    "type": "string",
                    "example": "pending"
                },
                "user_id": {
                    "type": "string",
                    "example": "1"
                }
            }
        },
        "handler.StreamInfo": {
            "type": "object",
            "properties": {
                "chunk_count": {
                    "type": "integer",
                    "example": 10
                },
                "duration_ms": {
                    "type": "integer",
                    "example": 60000
                },
                "playlist_url": {
                    "type": "string",
                    "example": "/api/v1/sessions/1/playlist/screen.m3u8"
                },
                "stream_type": {
                    "type": "string",
                    "example": "screen"
                }
            }
        },
        "handler.TelemetryEvent": {
            "type": "object",
            "properties": {
                "created_at": {
                    "type": "string",
                    "example": "2026-04-05T12:00:00Z"
                },
                "event_type": {
                    "type": "string",
                    "example": "keyboard"
                },
                "id": {
                    "type": "integer",
                    "example": 1
                },
                "payload": {
                    "type": "array",
                    "items": {
                        "type": "integer"
                    }
                },
                "session_id": {
                    "type": "integer",
                    "example": 1
                },
                "user_id": {
                    "type": "integer",
                    "example": 42
                }
            }
        }
    },
    "securityDefinitions": {
        "BearerAuth": {
            "description": "JWT token with \"Bearer \" prefix",
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        },
        "ForwardAuth": {
            "description": "Authelia Forward Auth — set automatically by Traefik",
            "type": "apiKey",
            "name": "Remote-User",
            "in": "header"
        }
    }
}