{"openapi":"3.1.0","info":{"title":"LivePin API","description":"**Hooks docs:** [Swagger](/docs/hooks/swagger-ui) · [RapiDoc](/docs/hooks/rapidoc-ui) · [Scalar](/docs/hooks/scalar-ui)\n\n**SFTPGo docs:** [Swagger](/docs/sftpgo/swagger-ui) · [RapiDoc](/docs/sftpgo/rapidoc-ui) · [Scalar](/docs/sftpgo/scalar-ui)","version":"v1"},"servers":[{"url":"/api/v1"}],"paths":{"/health":{"get":{"tags":["Utilities"],"summary":"Check the server's health","description":"Reports whether the server and each service it depends on is working.","operationId":"web_server.routes.health.health_check","responses":{"200":{"description":"Every component is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckResponse"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"At least one component is unhealthy; `components` says which","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckResponse"}}}}}}},"/health/camera":{"get":{"tags":["Utilities"],"summary":"Check a camera's stream","description":"Reports whether the camera on this channel is connected to stream video, which it is only while a stream is running.","operationId":"web_server.routes.health.health_check_camera","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1}],"responses":{"200":{"description":"The camera is connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckEntityResponse"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The camera is not connected, or its state could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckEntityResponse"},"example":{"healthy":false}}}}}}},"/health/device":{"get":{"tags":["Utilities"],"summary":"Check a device's connection","description":"Reports whether the device is connected to the server and can take commands.","operationId":"web_server.routes.health.health_check_device","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"}],"responses":{"200":{"description":"The device is connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckEntityResponse"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The device is not connected, or its state could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.health.HealthCheckEntityResponse"},"example":{"healthy":false}}}}}}},"/history/control-stream":{"get":{"tags":["History Playback"],"summary":"Control a recording's playback","description":"Plays, pauses, stops, fast-forwards, rewinds or seeks the recording streaming on a channel.","operationId":"web_server.routes.history.control_history_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"playback_control","in":"query","description":"What to do:\n- `0`: play\n- `1`: pause\n- `2`: stop\n- `3`: fast forward\n- `4`: keyframe rewind\n- `5`: seek to `drag_playback_time`\n- `6`: keyframe play","required":true,"schema":{"$ref":"#/components/schemas/jt808.types.history_stream.PlaybackControl"}},{"name":"fast_forward_rewind_times","in":"query","description":"Speed for `playback_control` `3` or `4`:\n- `0`: none (normal speed)\n- `1`: 1×\n- `2`: 2×\n- `3`: 4×\n- `4`: 8×\n- `5`: 16×","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.FastForwardRewindTimes"}],"default":0}},{"name":"drag_playback_time","in":"query","description":"Where to seek to with `playback_control=5`, RFC 3339 in any offset;\nsend `+` as `%2B` in the query string","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:02:30+05:30"}],"responses":{"200":{"description":"The device acknowledged the command","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"A parameter is missing or invalid, or `drag_playback_time` falls outside 2000-2099 on the camera's clock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/history/list-videos":{"get":{"tags":["History Playback"],"summary":"List a camera's recordings","description":"Asks the camera which recordings it holds between `start_time` and `end_time`; their times come back in the camera's own UTC offset.","operationId":"web_server.routes.history.get_history_videos","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"start_time","in":"query","description":"Start of the range, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:00:00+05:30"},{"name":"end_time","in":"query","description":"End of the range, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:05:00+05:30"},{"name":"resource_type","in":"query","description":"Only recordings containing:\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only\n- `3`: video, with or without audio","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.ResourceType"}],"default":3}},{"name":"stream_type","in":"query","description":"Only recordings from:\n- `0`: any stream\n- `1`: main stream\n- `2`: sub stream","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.StreamType"}],"default":0}},{"name":"memory_type","in":"query","description":"Only recordings stored on:\n- `0`: any storage\n- `1`: main storage\n- `2`: backup (disaster-recovery) storage","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.MemoryType"}],"default":0}},{"name":"alarm","in":"query","description":"Only recordings with these alarm flags set (a bitmask); `0` for all","required":false,"schema":{"type":"integer","format":"uint64","default":0,"minimum":0}}],"responses":{"200":{"description":"The recordings the camera holds in the range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalResourceListResponse"}}}},"400":{"description":"A parameter is missing or invalid, `start_time` is not before `end_time`, or a time falls outside 2000-2099 on the camera's clock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/history/start-stream":{"get":{"tags":["History Playback"],"summary":"Start playing a recording","description":"Asks the camera to stream its recording between `start_time` and `end_time`; watch it at `GET /history/stream.flv`.","operationId":"web_server.routes.history.start_history_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"start_time","in":"query","description":"Start of the range, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:00:00+05:30"},{"name":"end_time","in":"query","description":"End of the range, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:05:00+05:30"},{"name":"resource_type","in":"query","description":"What to play:\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only\n- `3`: video, with or without audio","required":true,"schema":{"$ref":"#/components/schemas/jt808.types.history_stream.ResourceType"},"example":3},{"name":"stream_type","in":"query","description":"Which stream to play:\n- `1`: main stream\n- `2`: sub stream","required":true,"schema":{"$ref":"#/components/schemas/web_server.routes.history.StreamTypeInput"},"example":1},{"name":"memory_type","in":"query","description":"Where the recording is stored:\n- `1`: main storage\n- `2`: backup (disaster-recovery) storage","required":true,"schema":{"$ref":"#/components/schemas/web_server.routes.history.MemoryTypeInput"},"example":1},{"name":"host","in":"query","description":"Media server the camera streams to; leave out to use this server's own","required":false,"schema":{"type":"string"}},{"name":"tcp_port","in":"query","description":"TCP port on `host`; leave out to use this server's own","required":false,"schema":{"type":"integer","format":"uint16","minimum":0}},{"name":"udp_port","in":"query","description":"UDP port on `host`; leave out to use this server's own","required":false,"schema":{"type":"integer","format":"uint16","minimum":0}},{"name":"playback_mode","in":"query","description":"How to play:\n- `0`: normal\n- `1`: fast forward\n- `2`: keyframe rewind\n- `3`: keyframes only\n- `4`: single frame","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.PlaybackMode"}],"default":0}},{"name":"fast_forward_rewind_times","in":"query","description":"Speed for `playback_mode` `1` or `2`:\n- `0`: none (normal speed)\n- `1`: 1×\n- `2`: 2×\n- `3`: 4×\n- `4`: 8×\n- `5`: 16×","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.FastForwardRewindTimes"}],"default":0}}],"responses":{"200":{"description":"The camera acknowledged, or the channel was already streaming","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"A parameter is missing or invalid, `start_time` is not before `end_time`, or a time falls outside 2000-2099 on the camera's clock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/history/stream.flv":{"get":{"tags":["History Playback"],"summary":"Watch a recording","description":"Plays the recording started with `GET /history/start-stream` as HTTP-FLV until it ends.","operationId":"web_server.routes.history.stream_history_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1}],"responses":{"200":{"description":"The recording, as HTTP-FLV (`video/x-flv`)"},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The channel is not streaming: the recording ended, or was never started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The media server returned an error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/realtime/control-stream":{"get":{"tags":["Realtime Playback"],"summary":"Control a live stream","description":"Stops, pauses, resumes or switches the camera's live stream on a channel.","operationId":"web_server.routes.realtime.control_realtime_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"ctrl_instruction","in":"query","description":"What to do:\n- `0`: stop (what stops is set by `close_stream_type`)\n- `1`: switch between the main and sub stream\n- `2`: pause\n- `3`: resume\n- `4`: end the two-way intercom","required":true,"schema":{"$ref":"#/components/schemas/jt808.types.realtime_stream.RealtimeStreamCtrlInstruction"}},{"name":"close_stream_type","in":"query","description":"With `ctrl_instruction=0`, what to stop:\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.realtime_stream.CloseRealtimeStreamType"}],"default":0}},{"name":"stream_type","in":"query","description":"With `ctrl_instruction=1`, the stream to switch to:\n- `0`: main stream\n- `1`: sub stream","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.realtime_stream.RealtimeStreamType"}],"default":0}}],"responses":{"200":{"description":"The device acknowledged the command","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/realtime/start-stream":{"get":{"tags":["Realtime Playback"],"summary":"Start a live stream","description":"Asks the camera to start streaming a channel; watch it at `GET /realtime/stream.flv`, which the server stops about a minute after its last viewer leaves.","operationId":"web_server.routes.realtime.start_realtime_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"host","in":"query","description":"Media server the camera streams to; leave out to use this server's own","required":false,"schema":{"type":"string"}},{"name":"tcp_port","in":"query","description":"TCP port on `host`; leave out to use this server's own","required":false,"schema":{"type":"integer","format":"uint16","minimum":0}},{"name":"udp_port","in":"query","description":"UDP port on `host`; leave out to use this server's own","required":false,"schema":{"type":"integer","format":"uint16","minimum":0}},{"name":"data_type","in":"query","description":"What to stream:\n- `0`: audio and video\n- `1`: video only\n- `2`: two-way intercom\n- `3`: listen-in (monitoring)\n- `4`: central broadcast\n- `5`: transparent transmission","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.realtime_stream.RealtimeStreamDataType"}],"default":0}},{"name":"stream_type","in":"query","description":"Which stream to send:\n- `0`: main stream (full quality)\n- `1`: sub stream (lower quality, less bandwidth)","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.realtime_stream.RealtimeStreamType"}],"default":0}}],"responses":{"200":{"description":"The camera acknowledged, or the channel was already streaming","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/realtime/stream.flv":{"get":{"tags":["Realtime Playback"],"summary":"Watch a live stream","description":"Plays the channel's live stream as HTTP-FLV for as long as the connection stays open.","operationId":"web_server.routes.realtime.stream_realtime_playback","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1}],"responses":{"200":{"description":"The live stream, as HTTP-FLV (`video/x-flv`)"},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The channel is not streaming; start it with `GET /realtime/start-stream`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The media server returned an error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/send-control-command":{"post":{"tags":["Utilities"],"summary":"Send a control command","description":"Sends the device a terminal control command, such as restart or power off, and returns its answer.","operationId":"web_server.routes.command.send_ctrl_cmd","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"}],"requestBody":{"description":"Extract json format data from request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.command.SendCtrlCmd"}}}},"responses":{"200":{"description":"The device acknowledged the command","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"The body or a parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"413":{"description":"The request body is larger than 16 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/send-text":{"post":{"tags":["Utilities"],"summary":"Send a text message","description":"Sends the device a text message to show or read aloud, and returns its answer.","operationId":"web_server.routes.text.send_text_message","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"}],"requestBody":{"description":"Extract json format data from request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.text.SendText"}}}},"responses":{"200":{"description":"The device acknowledged the command","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"}}}},"400":{"description":"The body or a parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"413":{"description":"The request body is larger than 16 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/videos":{"get":{"tags":["Video Upload"],"summary":"Get an upload","description":"Returns one upload's status and the bytes received so far.","operationId":"web_server.routes.upload.uploaded_video","parameters":[{"name":"video_id","in":"query","description":"Upload id, as returned by `GET /videos/upload`","required":true,"schema":{"type":"string"},"example":"66fe5c2a9b1e8a3f4c2d1e0b"}],"responses":{"200":{"description":"The upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.UploadedVideo"}}}},"400":{"description":"`video_id` is missing or is not a 24-character hex id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"No upload has this `video_id`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}},"delete":{"tags":["Video Upload"],"summary":"Delete an upload","description":"Deletes a completed, failed or cancelled upload, its video file included; this cannot be undone.","operationId":"web_server.routes.upload.delete_uploaded_video","parameters":[{"name":"video_id","in":"query","description":"Upload id, as returned by `GET /videos/upload`","required":true,"schema":{"type":"string"},"example":"66fe5c2a9b1e8a3f4c2d1e0b"}],"responses":{"200":{"description":"Deleted; the body is the upload as it was","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.UploadedVideo"}}}},"400":{"description":"`video_id` is missing or is not a 24-character hex id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"403":{"description":"The upload is still uploading or paused; cancel it first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"No upload has this `video_id`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The video file could not be deleted; nothing was removed, so try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/videos/control":{"get":{"tags":["Video Upload"],"summary":"Pause, resume or cancel an upload","description":"Asks the camera to pause, resume or cancel an upload; cancelling also deletes what was uploaded.","operationId":"web_server.routes.upload.control_upload_video","parameters":[{"name":"video_id","in":"query","description":"Upload id, as returned by `GET /videos/upload`","required":true,"schema":{"type":"string"},"example":"66fe5c2a9b1e8a3f4c2d1e0b"},{"name":"action","in":"query","description":"What to do:\n- `0`: pause (while uploading)\n- `1`: resume (while paused)\n- `2`: cancel (either)","required":true,"schema":{"$ref":"#/components/schemas/jt808.types.upload.VideoUploadAction"}}],"responses":{"200":{"description":"The camera answered; if it refused, the upload is unchanged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.types.UploadedVideo"}}}},"400":{"description":"`video_id` is missing or is not a 24-character hex id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"No upload has this `video_id`, or the device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"409":{"description":"The action does not fit the upload's status, it changed meanwhile, or (on resume) the camera is busy with another upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 15 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/videos/list":{"get":{"tags":["Video Upload"],"summary":"List a device's uploads","description":"Returns every upload requested for the device, in any status, with the bytes received so far.","operationId":"web_server.routes.upload.uploaded_video_list","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Only this camera channel; leave out for every channel","required":false,"schema":{"type":"integer","format":"uint8","minimum":0}}],"responses":{"200":{"description":"The device's uploads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.upload.UploadedVideoListResp"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/videos/upload":{"get":{"tags":["Video Upload"],"summary":"Upload a recorded clip","description":"Asks the camera to upload its recording between `start_time` and `end_time`; follow it with `GET /videos/list` or `GET /videos`.","operationId":"web_server.routes.upload.upload_video","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"},{"name":"channel","in":"query","description":"Camera channel, starting at 1","required":true,"schema":{"type":"integer","format":"uint8","minimum":0},"example":1},{"name":"start_time","in":"query","description":"Start of the clip, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:00:00+05:30"},{"name":"end_time","in":"query","description":"End of the clip, RFC 3339 in any offset; send `+` as `%2B` in the\nquery string. Fractions of a second are dropped.","required":true,"schema":{"type":"string","format":"date-time"},"example":"2026-10-03T10:05:00+05:30"},{"name":"host","in":"query","description":"FTP server the camera uploads to; leave out to use this server's own","required":false,"schema":{"type":"string"}},{"name":"port","in":"query","description":"FTP port on `host`; leave out to use this server's own","required":false,"schema":{"type":"integer","format":"uint16","minimum":0}},{"name":"resource_type","in":"query","description":"What to upload:\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only\n- `3`: video, with or without audio","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.ResourceType"}],"default":3}},{"name":"stream_type","in":"query","description":"Which stream's recording:\n- `0`: any stream\n- `1`: main stream\n- `2`: sub stream","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.StreamType"}],"default":0}},{"name":"memory_type","in":"query","description":"Where the recording is stored:\n- `0`: any storage\n- `1`: main storage\n- `2`: backup (disaster-recovery) storage","required":false,"schema":{"oneOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.MemoryType"}],"default":0}},{"name":"alarm","in":"query","description":"Only a recording with these alarm flags set (a bitmask); `0` for any","required":false,"schema":{"type":"integer","format":"uint64","default":0,"minimum":0}},{"name":"wifi","in":"query","description":"Let the camera upload over Wi-Fi","required":false,"schema":{"type":"boolean","default":true}},{"name":"lan","in":"query","description":"Let the camera upload over a wired network","required":false,"schema":{"type":"boolean","default":true}},{"name":"mobile_network","in":"query","description":"Let the camera upload over its mobile connection","required":false,"schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"The camera accepted the upload; or the clip already had one, whose status is then in `result`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.upload.UploadGeneralResponse"}}}},"400":{"description":"A parameter is missing or invalid, `start_time` is not before `end_time`, or a time falls outside 2000-2099 on the camera's clock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"409":{"description":"The camera is already uploading another clip","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The camera refused the upload, or its reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}},"/wakeup":{"get":{"tags":["Utilities"],"summary":"Wake a device","description":"Wakes a sleeping device, which ignores every other command until it is awake.","operationId":"web_server.routes.wakeup.device_wakeup","parameters":[{"name":"imei","in":"query","description":"Device identifier: its 12- or 20-digit terminal number","required":true,"schema":{"type":"string"},"example":"018200000001"}],"responses":{"200":{"description":"The device woke and answered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.routes.wakeup.WakeupResponse"}}}},"400":{"description":"A parameter is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"404":{"description":"The device is not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"429":{"description":"Too many requests; retry after the number of seconds in `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"502":{"description":"The device's reply could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"503":{"description":"The request ran past the server's 95-second limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}},"504":{"description":"The device did not reply within 90 seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/web_server.middlewares.ApiError"}}}}}}}},"components":{"schemas":{"jt808.types.history_stream.FastForwardRewindTimes":{"type":"integer","description":"Fast-forward or rewind speed\n\n- `0`: none (normal speed)\n- `1`: 1×\n- `2`: 2×\n- `3`: 4×\n- `4`: 8×\n- `5`: 16×","enum":[0,1,2,3,4,5]},"jt808.types.history_stream.MemoryType":{"type":"integer","description":"Where the camera stored a recording\n\n- `0`: any storage\n- `1`: main storage\n- `2`: backup (disaster-recovery) storage","enum":[0,1,2]},"jt808.types.history_stream.PlaybackControl":{"type":"integer","description":"What to do with a recording's playback\n\n- `0`: play\n- `1`: pause\n- `2`: stop\n- `3`: fast forward\n- `4`: keyframe rewind\n- `5`: seek to `drag_playback_time`\n- `6`: keyframe play","enum":[0,1,2,3,4,5,6]},"jt808.types.history_stream.PlaybackMode":{"type":"integer","description":"How a recording plays back\n\n- `0`: normal\n- `1`: fast forward\n- `2`: keyframe rewind\n- `3`: keyframes only\n- `4`: single frame","enum":[0,1,2,3,4]},"jt808.types.history_stream.ResourceType":{"type":"integer","description":"What a recording contains\n\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only\n- `3`: video, with or without audio","enum":[0,1,2,3]},"jt808.types.history_stream.StreamType":{"type":"integer","description":"Which of the camera's streams a recording comes from\n\n- `0`: any\n- `1`: main stream\n- `2`: sub stream","enum":[0,1,2]},"jt808.types.realtime_stream.CloseRealtimeStreamType":{"type":"integer","description":"What a stop command stops\n\n- `0`: audio and video\n- `1`: audio only\n- `2`: video only","enum":[0,1,2]},"jt808.types.realtime_stream.RealtimeStreamCtrlInstruction":{"type":"integer","description":"What to do with a live stream\n\n- `0`: stop (what stops is set by `close_stream_type`)\n- `1`: switch between the main and sub stream\n- `2`: pause\n- `3`: resume\n- `4`: end the two-way intercom","enum":[0,1,2,3,4]},"jt808.types.realtime_stream.RealtimeStreamDataType":{"type":"integer","description":"What a live stream carries\n\n- `0`: audio and video\n- `1`: video only\n- `2`: two-way intercom\n- `3`: listen-in (monitoring)\n- `4`: central broadcast\n- `5`: transparent transmission","enum":[0,1,2,3,4,5]},"jt808.types.realtime_stream.RealtimeStreamType":{"type":"integer","description":"Which of the camera's live streams to use\n\n- `0`: main stream (full quality)\n- `1`: sub stream (lower quality, less bandwidth)","enum":[0,1]},"jt808.types.text.SendTextOptions":{"type":"object","description":"How the device presents a text message","required":["emergency","display_by_terminal","tts","display_by_advertising_screen","central_navigation_info"],"properties":{"central_navigation_info":{"type":"boolean","description":"Mark it as navigation information from the control centre"},"display_by_advertising_screen":{"type":"boolean","description":"Show it on an attached advertising screen"},"display_by_terminal":{"type":"boolean","description":"Show it on the device's own display"},"emergency":{"type":"boolean","description":"Flag the message as an emergency"},"tts":{"type":"boolean","description":"Read it aloud (text-to-speech)"}}},"jt808.types.upload.VideoUploadAction":{"type":"integer","description":"What to do with an upload\n\n- `0`: pause\n- `1`: resume\n- `2`: cancel","enum":[0,1,2]},"web_server.middlewares.ApiError":{"type":"object","description":"Error response body\n\nEvery `4xx`/`5xx` from the API carries this body.","required":["status","error"],"properties":{"error":{"type":"string","description":"What went wrong, in a sentence"},"status":{"type":"integer","format":"uint16","description":"HTTP status code, repeated from the response","minimum":0}}},"web_server.routes.command.SendCtrlCmd":{"type":"object","description":"A terminal control command","required":["command"],"properties":{"command":{"type":"integer","format":"int64","description":"The command, as JT/T 808 numbers them:\n- `1`: firmware upgrade\n- `2`: connect to another server\n- `3`: power off\n- `4`: restart\n- `5`: factory reset\n- `6`: stop data communication\n- `7`: stop all wireless communication","examples":[4],"maximum":255,"minimum":0},"parameters":{"type":["string","null"],"description":"Arguments for commands `1` and `2`, separated by `;` in the order the\nstandard lists them; leave out for the others"}}},"web_server.routes.health.ComponentHealth":{"type":"object","description":"Each component's health; `true` means reachable and working","required":["redis","rabbitmq","mongo","sftpgo","jt808_server","jt1078_server"],"properties":{"jt1078_server":{"type":"boolean","description":"Server the cameras stream video to"},"jt808_server":{"type":"boolean","description":"Server the devices connect to for commands and location"},"mongo":{"type":"boolean","description":"Database of uploads"},"rabbitmq":{"type":"boolean","description":"Message broker that carries commands to devices"},"redis":{"type":"boolean","description":"Live device state store"},"sftpgo":{"type":"boolean","description":"FTP server that receives uploaded videos"}}},"web_server.routes.health.HealthCheckEntityResponse":{"type":"object","description":"Whether a device or camera is connected","required":["healthy"],"properties":{"healthy":{"type":"boolean","description":"`true` when it is connected"}}},"web_server.routes.health.HealthCheckResponse":{"type":"object","description":"The server's health","required":["healthy","components"],"properties":{"components":{"allOf":[{"$ref":"#/components/schemas/web_server.routes.health.ComponentHealth"},{"description":"Each component's health"}]},"healthy":{"type":"boolean","description":"`true` only when every component is healthy"}}},"web_server.routes.history.MemoryTypeInput":{"type":"integer","description":"Where the recording to play is stored\n\n- `1`: main storage\n- `2`: backup (disaster-recovery) storage","enum":[1,2]},"web_server.routes.history.StreamTypeInput":{"type":"integer","description":"Which of the camera's streams to play\n\n- `1`: main stream\n- `2`: sub stream","enum":[1,2]},"web_server.routes.text.SendText":{"type":"object","description":"A text message for a device","required":["text"],"properties":{"options":{"allOf":[{"$ref":"#/components/schemas/jt808.types.text.SendTextOptions"},{"description":"How to present it; leave out to send it as an emergency message"}]},"text":{"type":"string","description":"The message: at most 1024 bytes in the device's GBK encoding, where an\nASCII character takes 1 byte and any other character 2","examples":["Please call the depot"],"maxLength":1024,"minLength":1},"text_type":{"type":["string","null"],"description":"Category, `\"Notification\"` or `\"Service\"`; leave out for none","examples":["Notification"]}}},"web_server.routes.upload.UploadGeneralResponse":{"allOf":[{"$ref":"#/components/schemas/web_server.types.TerminalGeneralResponse"},{"type":"object","required":["video_id"],"properties":{"video_id":{"type":"string","description":"Upload id, for the other `/videos` endpoints","examples":["66fe5c2a9b1e8a3f4c2d1e0b"]}}}],"description":"An upload request's outcome"},"web_server.routes.upload.UploadedVideoListResp":{"type":"object","description":"A device's uploads","required":["total","videos"],"properties":{"total":{"type":"integer","description":"Number of uploads in `videos`","minimum":0},"videos":{"type":"array","items":{"$ref":"#/components/schemas/web_server.types.UploadedVideo"},"description":"The uploads, in no particular order"}}},"web_server.routes.wakeup.WakeupResponse":{"type":"object","description":"Wake-up outcome","required":["result"],"properties":{"result":{"type":"string","description":"Always `\"success\"`: the device answered","examples":["success"]}}},"web_server.types.TerminalGeneralResponse":{"type":"object","description":"The device's answer to a command","required":["response_id","result"],"properties":{"response_id":{"type":"string","description":"The command answered, as its JT/T 808 message id in hex","examples":["0x9101"]},"result":{"type":"string","description":"`success`, `failure`, `incorrectInfo` (the device found the command\nmalformed) or `unsupported`. From `GET /videos/upload` for a clip that\nalready has an upload, that upload's status instead.","examples":["success"]}}},"web_server.types.TerminalResourceListResponse":{"type":"object","description":"Recordings on a camera","required":["total_resources","resources"],"properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/web_server.types.VideoResource"},"description":"The recordings"},"total_resources":{"type":"integer","format":"uint32","description":"Number of recordings the camera reported","minimum":0}}},"web_server.types.UploadedVideo":{"type":"object","description":"An upload","required":["video_id","imei","channel","video_start_time","video_end_time","filesize","status"],"properties":{"channel":{"type":"integer","format":"uint8","description":"Camera channel","minimum":0},"filename":{"type":["string","null"],"description":"Name of the uploaded file; absent until the camera starts sending it"},"filesize":{"type":"integer","format":"int64","description":"Bytes received so far, which can drop if the camera restarts the\ntransfer"},"imei":{"type":"string","description":"Device identifier","examples":["018200000001"]},"status":{"type":"string","description":"`uploading`, `paused`, `completed`, `failed` or `cancelled`","examples":["uploading"]},"video_end_time":{"type":"string","format":"date-time","description":"End of the clip, RFC 3339 in the same offset","examples":["2026-10-03T10:05:00+05:30"]},"video_id":{"type":"string","description":"Upload id","examples":["66fe5c2a9b1e8a3f4c2d1e0b"]},"video_start_time":{"type":"string","format":"date-time","description":"Start of the clip, RFC 3339 in the camera's UTC offset when the upload\nwas requested","examples":["2026-10-03T10:00:00+05:30"]}}},"web_server.types.VideoResource":{"type":"object","description":"One recording on a camera","required":["logical_channel_no","playback_start_time","playback_end_time","alarm","resource_type","stream_type","memory_type","file_size"],"properties":{"alarm":{"type":"integer","format":"uint64","description":"Alarm flags raised during the recording, as a bitmask","minimum":0},"file_size":{"type":"integer","format":"uint32","description":"Size in bytes as the camera reports it; an uploaded file's size can\ndiffer","minimum":0},"logical_channel_no":{"type":"integer","format":"uint8","description":"Camera channel","minimum":0},"memory_type":{"allOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.MemoryType"},{"description":"Where the camera stored it"}]},"playback_end_time":{"type":"string","format":"date-time","description":"When the recording ends, RFC 3339 in the camera's UTC offset","examples":["2026-10-03T10:05:00+05:30"]},"playback_start_time":{"type":"string","format":"date-time","description":"When the recording starts, RFC 3339 in the camera's UTC offset","examples":["2026-10-03T10:00:00+05:30"]},"resource_type":{"allOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.ResourceType"},{"description":"What the recording contains"}]},"stream_type":{"allOf":[{"$ref":"#/components/schemas/jt808.types.history_stream.StreamType"},{"description":"Which stream it was recorded from"}]}}}}}}