{"openapi":"3.1.0","info":{"title":"TeroVision API","version":"1.1.0","description":"API para integrar cámaras a TeroVision. La clave (`tv_live_…`) es de un espacio y va en `Authorization: Bearer`. Guía: /desarrolladores."},"servers":[{"url":"https://terovision.com/api/v1"}],"security":[{"apiKey":[]}],"paths":{"/me":{"get":{"operationId":"getMe","summary":"La clave, su espacio y su rol de hoy","x-scope":"-","security":[{"apiKey":[]}],"responses":{"200":{"description":"Clave","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/storage":{"get":{"operationId":"getStorage","summary":"Bucket del espacio (sin el secreto)","x-scope":"storage","security":[{"apiKey":[]}],"responses":{"200":{"description":"Bucket","content":{"application/json":{"schema":{"type":"object","properties":{"storage":{"$ref":"#/components/schemas/Storage"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"put":{"operationId":"putStorage","summary":"Configura el bucket. `secret_key` es de solo escritura","x-scope":"storage","security":[{"apiKey":[]}],"responses":{"200":{"description":"Guardado","content":{"application/json":{"schema":{"type":"object","properties":{"storage":{"$ref":"#/components/schemas/Storage"},"test":{"oneOf":[{"$ref":"#/components/schemas/StorageTest"},{"type":"null"}]}}}}}},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageInput"}}}}},"delete":{"operationId":"deleteStorage","summary":"Quita el bucket propio","x-scope":"storage","security":[{"apiKey":[]}],"responses":{"200":{"description":"Quitado","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/storage/test":{"post":{"operationId":"testStorage","summary":"Prueba el bucket (lista; con `write=true` también sube y borra)","x-scope":"storage","security":[{"apiKey":[]}],"responses":{"200":{"description":"Resultado","content":{"application/json":{"schema":{"type":"object","properties":{"test":{"$ref":"#/components/schemas/StorageTest"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"write","in":"query","schema":{"type":"boolean"}}]}},"/cameras":{"get":{"operationId":"listCameras","summary":"Cámaras que ve la clave","x-scope":"cameras:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Camera"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}]},"post":{"operationId":"createCamera","summary":"Alta: devuelve el QR (sin WiFi) una sola vez","x-scope":"cameras:write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Creada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Provisioned"}}}},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Repetir el pedido con la misma clave (24 h) devuelve la misma respuesta sin crear otro recurso."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":2,"maxLength":60},"group_ids":{"type":"array","items":{"type":"integer"}}}}}}}}},"/cameras/{camera}":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"getCamera","summary":"Una cámara","x-scope":"cameras:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Cámara","content":{"application/json":{"schema":{"type":"object","properties":{"camera":{"$ref":"#/components/schemas/Camera"}}}}}},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"delete":{"operationId":"deleteCamera","summary":"Baja (revoca credenciales, borra lo retenido)","x-scope":"cameras:write","security":[{"apiKey":[]}],"responses":{"202":{"description":"En curso","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"Ya estaba","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/status":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"getCameraStatus","summary":"Lo último que informó la cámara","x-scope":"cameras:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Estado","content":{"application/json":{"schema":{"type":"object","properties":{"camera_id":{"type":"string"},"status":{"$ref":"#/components/schemas/CameraStatus"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/commands/{command}":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."},{"name":"command","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getCommand","summary":"Resultado de un pedido a la cámara","x-scope":"cameras:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Comando","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/credentials/rotate":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"rotateCredentials","summary":"Rota credenciales: todas si no conectó (QR nuevo), el token de fotos si ya conectó","x-scope":"cameras:write","security":[{"apiKey":[]}],"responses":{"200":{"description":"QR nuevo (cámara sin conectar)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Provisioned"}}}},"202":{"description":"Token de fotos rotado (cámara conectada)","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/ptz/move":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"ptzMove","summary":"Un paso de 500 ms; repetir cada 300 ms para seguir","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"200":{"description":"Enviado","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["direction"],"properties":{"direction":{"type":"string","enum":["up","down","left","right","ul","ur","dl","dr"]}}}}}}}},"/cameras/{camera}/ptz/stop":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"ptzStop","summary":"Frena","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"200":{"description":"Enviado","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/ptz/home":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"ptzHome","summary":"Vuelve al inicio","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/ptz/goto":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"ptzGoto","summary":"Va a una posición del motor","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["x","y"],"properties":{"x":{"type":"integer"},"y":{"type":"integer"}}}}}}}},"/cameras/{camera}/ptz/presets":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"listPresets","summary":"Posiciones guardadas (`?refresh=1` le pregunta a la cámara)","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"200":{"description":"Posiciones","content":{"application/json":{"schema":{"type":"object","properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/Preset"}},"refreshing":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"refresh","in":"query","schema":{"type":"boolean"}}]},"post":{"operationId":"savePreset","summary":"Guarda la posición actual (pide rol de administrador)","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":30}}}}}}}},"/cameras/{camera}/ptz/presets/{preset}/goto":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."},{"name":"preset","in":"path","required":true,"schema":{"type":"integer"}}],"post":{"operationId":"gotoPreset","summary":"Va a una posición guardada","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/ptz/presets/{preset}":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."},{"name":"preset","in":"path","required":true,"schema":{"type":"integer"}}],"delete":{"operationId":"deletePreset","summary":"Borra una posición (pide rol de administrador)","x-scope":"ptz","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/cameras/{camera}/snapshots":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"takeSnapshot","summary":"Pide una foto","x-scope":"snapshots","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"get":{"operationId":"listSnapshots","summary":"Fotos de la cámara","x-scope":"snapshots","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Media"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}}]}},"/snapshots/{snapshot}":{"parameters":[{"name":"snapshot","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getSnapshot","summary":"Una foto con su URL firmada","x-scope":"snapshots","security":[{"apiKey":[]}],"responses":{"200":{"description":"Foto","content":{"application/json":{"schema":{"type":"object","properties":{"snapshot":{"$ref":"#/components/schemas/MediaWithUrl"}}}}}},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"502":{"$ref":"#/components/responses/E502"},"503":{"$ref":"#/components/responses/E503"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"download","in":"query","schema":{"type":"boolean"}}]}},"/cameras/{camera}/recording":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"getRecordingSettings","summary":"Grabación de la cámara","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"200":{"description":"Ajustes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingSettings"}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"put":{"operationId":"putRecordingSettings","summary":"Prende o apaga la grabación y la subida al bucket (pide rol de administrador)","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"},"upload":{"type":"boolean"},"segment_minutes":{"type":"integer","enum":[30,60]},"audio":{"type":"boolean"}}}}}}}},"/cameras/{camera}/recording/start":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"startRecording","summary":"Empieza a grabar en la tarjeta","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"segment_minutes":{"type":"integer","enum":[30,60]}}}}}}}},"/cameras/{camera}/recording/stop":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"stopRecording","summary":"Deja de grabar","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"202":{"description":"Pedido a la cámara. Seguilo con getCommand.","content":{"application/json":{"schema":{"type":"object","properties":{"command":{"$ref":"#/components/schemas/Command"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/recordings":{"get":{"operationId":"listRecordings","summary":"Grabaciones y timelapses","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Media"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"camera_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"kind","in":"query","schema":{"type":"string","enum":["recording","timelapse"]}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}}]}},"/recordings/{recording}":{"parameters":[{"name":"recording","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getRecording","summary":"Una grabación con su URL firmada","x-scope":"recordings","security":[{"apiKey":[]}],"responses":{"200":{"description":"Grabación","content":{"application/json":{"schema":{"type":"object","properties":{"recording":{"$ref":"#/components/schemas/MediaWithUrl"}}}}}},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"502":{"$ref":"#/components/responses/E502"},"503":{"$ref":"#/components/responses/E503"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"download","in":"query","schema":{"type":"boolean"}}]}},"/cameras/{camera}/live":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"createLiveSession","summary":"Abre el video: WebRTC (LiveKit, solo mirar) y HLS firmado","x-scope":"live","security":[{"apiKey":[]}],"responses":{"201":{"description":"Sesión","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveSession"}}}},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"protocols":{"type":"array","items":{"type":"string","enum":["webrtc","hls"]}}}}}}}}},"/cameras/{camera}/talk":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"post":{"operationId":"openTalk","summary":"Abre el canal de voz (semidúplex, 120 s)","x-scope":"talk","security":[{"apiKey":[]}],"responses":{"201":{"description":"Canal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalkChannel"}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"502":{"$ref":"#/components/responses/E502"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"delete":{"operationId":"closeTalk","summary":"Cierra el canal de voz","x-scope":"talk","security":[{"apiKey":[]}],"responses":{"200":{"description":"Cerrado","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/events":{"get":{"operationId":"listEvents","summary":"Eventos de las cámaras","x-scope":"events","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"camera_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"kind","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}]}},"/cameras/{camera}/events":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"listCameraEvents","summary":"Eventos de una cámara","x-scope":"events","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"kind","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}]}},"/cameras/{camera}/lease":{"parameters":[{"name":"camera","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Id de la cámara (`id`, no `device_uid`)."}],"get":{"operationId":"getLease","summary":"Quién tiene el control de la cámara","x-scope":"control","security":[{"apiKey":[]}],"responses":{"200":{"description":"Préstamo","content":{"application/json":{"schema":{"type":"object","properties":{"lease":{"oneOf":[{"$ref":"#/components/schemas/Lease"},{"type":"null"}]},"held_by_this_key":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}},"post":{"operationId":"takeLease","summary":"Toma o renueva el control (hasta 300 s por pedido y 30 min seguidos por clave). Mientras dura, las automatizaciones no mueven ni cambian la cámara","x-scope":"control","security":[{"apiKey":[]}],"responses":{"201":{"description":"Tomado","content":{"application/json":{"schema":{"type":"object","properties":{"lease":{"$ref":"#/components/schemas/Lease"},"renewed":{"type":"boolean","const":false}}}}}},"200":{"description":"Renovado","content":{"application/json":{"schema":{"type":"object","properties":{"lease":{"$ref":"#/components/schemas/Lease"},"renewed":{"type":"boolean","const":true}}}}}},"409":{"description":"Lo tiene otra clave (`lease_held`, con `lease`); esta clave llegó al tope de tenencia seguida y tiene que esperar (`lease_hold_limit`), o una persona la liberó desde el panel y no la puede volver a tomar por un rato (`lease_revoked_by_user`). Las dos últimas traen `retry_after`, `blocked_until` y el encabezado `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/E404"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"ttl_seconds":{"type":"integer","minimum":10,"maximum":300,"default":60}}}}}}},"delete":{"operationId":"releaseLease","summary":"Suelta el control","x-scope":"control","security":[{"apiKey":[]}],"responses":{"200":{"description":"Suelto","content":{"application/json":{"schema":{"type":"object","properties":{"released":{"type":"boolean"}}}}}},"409":{"description":"Lo tiene otra clave (`lease_held`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/automations":{"get":{"operationId":"listAutomations","summary":"Automatizaciones del espacio (pide rol de administrador)","x-scope":"automations:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Automation"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}]}},"/automations/{automation}":{"parameters":[{"name":"automation","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getAutomation","summary":"Una automatización, sus nodos (solo tipo) y sus últimas ejecuciones","x-scope":"automations:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Automatización","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"type":"object","properties":{"nodes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"}}}},"recent_runs":{"type":"array","items":{"$ref":"#/components/schemas/AutomationRun"}}}}]}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/automations/{automation}/enable":{"parameters":[{"name":"automation","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"enableAutomation","summary":"La prende (una pausada se despausa). Una administrada prende su función en la cámara","x-scope":"automations:write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Prendida","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"$ref":"#/components/schemas/Automation"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/automations/{automation}/disable":{"parameters":[{"name":"automation","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"disableAutomation","summary":"La apaga y corta lo que estaba corriendo","x-scope":"automations:write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Apagada","content":{"application/json":{"schema":{"type":"object","properties":{"automation":{"$ref":"#/components/schemas/Automation"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/automations/{automation}/run":{"parameters":[{"name":"automation","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"runAutomation","summary":"La ejecuta desde su disparador Manual, con los topes y el freno de siempre","x-scope":"automations:run","security":[{"apiKey":[]}],"responses":{"202":{"description":"Arrancó. Seguila con getAutomationRun.","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"$ref":"#/components/schemas/AutomationRun"}}}}}},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"camera_id":{"type":"string","format":"uuid","description":"La cámara \"del disparador\" para los nodos que la usan."},"data":{"type":"object","maxProperties":20,"additionalProperties":{"type":["string","number","boolean","null"]},"description":"Datos para el flujo (`{{ nombre }}`). Claves `[A-Za-z][A-Za-z0-9_]*`, textos de hasta 500."}}}}}}}},"/automations/{automation}/runs/{run}":{"parameters":[{"name":"automation","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"run","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getAutomationRun","summary":"Una ejecución, paso por paso","x-scope":"automations:read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Ejecución","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"allOf":[{"$ref":"#/components/schemas/AutomationRun"},{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"node":{"type":"string"},"type":{"type":"string"},"status":{"type":"string","enum":["blocked","pending","running","waiting","ok","failed","skipped"]},"code":{"type":["string","null"],"examples":["leased"]},"note":{"type":["string","null"]},"error":{"type":["string","null"]},"started_at":{"type":["string","null"]},"finished_at":{"type":["string","null"]}}}}}}]}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/webhooks":{"get":{"operationId":"listWebhooks","summary":"Webhooks de salida","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}]},"post":{"operationId":"createWebhook","summary":"Crea un webhook; la clave de firma se ve una vez","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string"}}}]}}}}}},"409":{"$ref":"#/components/responses/E409"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Repetir el pedido con la misma clave (24 h) devuelve la misma respuesta sin crear otro recurso."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","examples":["camera.*","camera.online","vision.result","*"]}}}}}}}}},"/webhooks/{webhook}":{"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"operationId":"updateWebhook","summary":"Prende, apaga o cambia eventos","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"200":{"description":"Webhook","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}}}}}},"404":{"$ref":"#/components/responses/E404"},"422":{"$ref":"#/components/responses/E422"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}}}}}}}},"delete":{"operationId":"deleteWebhook","summary":"Borra el webhook","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"200":{"description":"Borrado","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}},"/webhooks/{webhook}/deliveries":{"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"listDeliveries","summary":"Envíos e intentos","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"200":{"description":"Página","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}]}},"/webhooks/{webhook}/ping":{"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"operationId":"pingWebhook","summary":"Manda un ping firmado","x-scope":"webhooks","security":[{"apiKey":[]}],"responses":{"202":{"description":"Encolado","content":{"application/json":{"schema":{"type":"object","properties":{"delivery":{"$ref":"#/components/schemas/Delivery"}}}}}},"404":{"$ref":"#/components/responses/E404"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"tv_live_<prefijo>_<secreto>"}},"responses":{"E400":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E410":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E502":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E503":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","status"],"properties":{"code":{"type":"string","examples":["invalid_key","key_revoked","key_expired","creator_suspended","missing_scope","not_found","validation_failed","rate_limited","idempotency_mismatch","camera_leased","lease_held","lease_hold_limit","lease_revoked_by_user","kill_switch","automation_inactive","automation_capped","no_manual_trigger"]},"message":{"type":"string"},"status":{"type":"integer"},"request_id":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"retry_after":{"type":"integer"},"required_scope":{"type":"string"},"blocked_until":{"type":"string","format":"date-time","description":"Con `lease_hold_limit` y `lease_revoked_by_user`: desde cuándo la clave puede volver a tomar la cámara."},"lease":{"$ref":"#/components/schemas/Lease","description":"Con `camera_leased` y `lease_held`: quién tiene el control y hasta cuándo."}}}}},"PageMeta":{"type":"object","properties":{"page":{"type":"integer"},"per_page":{"type":"integer"},"has_more":{"type":"boolean"}}},"Me":{"type":"object","properties":{"key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"role_ceiling":{"type":"string"},"effective_role":{"type":"string","enum":["owner","admin","member","viewer"]},"rate_limit_per_minute":{"type":"integer"},"expires_at":{"type":["string","null"]}}},"space":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"}}},"acting_as":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}}}},"Storage":{"type":"object","properties":{"configured":{"type":"boolean"},"endpoint":{"type":"string"},"region":{"type":"string"},"bucket":{"type":"string"},"access_key_hint":{"type":"string"},"secret_key_set":{"type":"boolean"},"path_style":{"type":"boolean"},"key_prefix":{"type":"string"},"verified_at":{"type":["string","null"]},"last_error":{"type":["string","null"]}}},"StorageInput":{"type":"object","required":["endpoint","region","bucket"],"properties":{"endpoint":{"type":"string","examples":["https://s3.us-east-1.amazonaws.com"]},"region":{"type":"string"},"bucket":{"type":"string"},"access_key":{"type":"string","description":"Obligatoria la primera vez"},"secret_key":{"type":"string","writeOnly":true,"description":"Obligatoria la primera vez; después, solo si cambia"},"path_style":{"type":"boolean","default":true},"key_prefix":{"type":"string","default":"opencam/"},"test":{"type":"boolean"}}},"StorageTest":{"type":"object","properties":{"ok":{"type":"boolean"},"read":{"type":"boolean"},"write":{"type":["boolean","null"]},"message":{"type":"string"}}},"Camera":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"device_uid":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","active","revoking","revoked"]},"online":{"type":"boolean"},"connection":{"type":"string"},"stale":{"type":"boolean"},"firmware":{"type":["string","null"]},"capabilities":{"type":["array","null"],"items":{"type":"string"}},"features":{"type":"object","additionalProperties":{"type":"boolean"}},"permissions":{"type":"object","properties":{"view":{"type":"boolean"},"operate":{"type":"boolean"},"configure":{"type":"boolean"},"manage":{"type":"boolean"}}},"enrollment_expires_at":{"type":["string","null"]},"linked_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]},"created_at":{"type":"string"}}},"CameraStatus":{"type":"object","additionalProperties":true},"Provisioned":{"type":"object","properties":{"camera":{"$ref":"#/components/schemas/Camera"},"provisioning":{"type":"object","properties":{"format":{"type":"string","const":"TV1"},"expires_at":{"type":"string"},"sections":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"string"}}},"qr_text":{"type":"string","description":"Texto del QR sin [wifi]. Agregar la red en el equipo de quien lo arma."},"note":{"type":"string"}}}}},"Command":{"type":"object","properties":{"id":{"type":"string"},"camera_id":{"type":"string"},"cmd":{"type":"string"},"label":{"type":"string"},"status":{"type":"string","enum":["queued","pending","accepted","progress","done","failed","timeout","offline","rejected","unreachable","lost"]},"code":{"type":["string","null"]},"message":{"type":["string","null"]},"done":{"type":"boolean"},"actor":{"type":["string","null"],"description":"Quién lo pidió: `api:<nombre de la clave>`, `automation:<id>` o `user:<id>`","examples":["api:Integración del depósito"]},"created_at":{"type":"string"},"resolved_at":{"type":["string","null"]}}},"Preset":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"Media":{"type":"object","properties":{"id":{"type":"string"},"camera_id":{"type":"string"},"kind":{"type":"string","enum":["photo","recording","timelapse"]},"taken_at":{"type":"string"},"ended_at":{"type":["string","null"]},"duration_s":{"type":["integer","null"]},"size":{"type":["integer","null"]},"content_type":{"type":"string"},"storage":{"type":"string","enum":["panel","bucket"]}}},"MediaWithUrl":{"allOf":[{"$ref":"#/components/schemas/Media"},{"type":"object","properties":{"url":{"type":"string"},"url_expires_in":{"type":"integer"}}}]},"RecordingSettings":{"type":"object","properties":{"camera_id":{"type":"string"},"settings":{"oneOf":[{"type":"null"},{"type":"object","properties":{"enabled":{"type":"boolean"},"upload":{"type":"boolean"},"targets":{"type":"array","items":{"type":"string"}},"segment_minutes":{"type":"integer"},"audio":{"type":"boolean"}}}]},"storage":{"type":"object","properties":{"bucket_configured":{"type":"boolean"},"space_bucket":{"type":"boolean"}}},"loaded_at":{"type":["string","null"]}}},"LiveSession":{"type":"object","properties":{"camera_id":{"type":"string"},"webrtc":{"type":"object","properties":{"url":{"type":"string"},"token":{"type":"string"},"expires_in":{"type":"integer"},"can_publish":{"type":"boolean"}}},"hls":{"type":"object","properties":{"url":{"type":"string"},"embed_url":{"type":"string"},"expires_in":{"type":"integer"}}}}},"TalkChannel":{"type":"object","properties":{"camera_id":{"type":"string"},"ws_url":{"type":"string"},"connect_within_s":{"type":"integer"},"max_seconds":{"type":"integer"},"audio":{"type":"object","properties":{"format":{"type":"string","const":"pcm_s16le"},"sample_rate":{"type":"integer"},"channels":{"type":"integer"},"frame_ms":{"type":"integer"}}},"half_duplex":{"type":"boolean"}}},"Event":{"type":"object","properties":{"id":{"type":"integer"},"camera_id":{"type":"string"},"type":{"type":"string"},"kind":{"type":"string"},"message":{"type":["string","null"]},"data":{"type":"object"},"created_at":{"type":"string"}}},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"host":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"failures":{"type":"integer"},"disabled_at":{"type":["string","null"]},"disabled_reason":{"type":["string","null"]},"created_at":{"type":"string"}}},"Lease":{"type":"object","properties":{"camera_id":{"type":"string"},"holder":{"type":"string","description":"Nombre de la clave que lo tiene"},"acquired_at":{"type":"string"},"expires_at":{"type":"string"},"expires_in":{"type":"integer"},"renewals":{"type":"integer"},"hold_ends_at":{"type":["string","null"],"description":"Tope de tenencia seguida de esta clave: renovar no lleva `expires_at` más allá. Después, la clave espera antes de volver a tomarla"}}},"Automation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"},"active":{"type":"boolean"},"valid":{"type":"boolean"},"paused":{"type":"boolean"},"paused_reason":{"type":["string","null"]},"managed":{"oneOf":[{"type":"null"},{"type":"object","properties":{"feature":{"type":"string"},"camera_id":{"type":"string"}}}],"description":"La creó un ajuste de la cámara (modo sencillo)"},"triggers":{"type":"array","items":{"type":"string"}},"runnable":{"type":"boolean","description":"Tiene el disparador Manual: se puede ejecutar por la API"},"last_run_at":{"type":["string","null"]},"last_run_status":{"type":["string","null"]},"last_skip":{"oneOf":[{"type":"null"},{"type":"object","properties":{"reason":{"type":"string","examples":["rate_limit","concurrency","leased"]},"message":{"type":"string"},"at":{"type":["string","null"]}}}]},"version":{"type":"integer"},"updated_at":{"type":["string","null"]}}},"AutomationRun":{"type":"object","properties":{"id":{"type":"string"},"automation_id":{"type":"string"},"status":{"type":"string","enum":["running","waiting","ok","failed","cancelled","skipped"]},"status_text":{"type":"string"},"reason":{"type":["string","null"]},"error":{"type":["string","null"]},"test":{"type":"boolean"},"trigger":{"type":"string"},"camera_id":{"type":["string","null"]},"done":{"type":"boolean"},"created_at":{"type":"string"},"finished_at":{"type":["string","null"]}}},"Delivery":{"type":"object","properties":{"id":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"next_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"created_at":{"type":"string"}}}}}}