{"openapi":"3.1.0","info":{"title":"TTVE API","version":"1.0.0","description":"TTVE (Total Video Experience)'s video platform API: upload, manage, publish, and measure video from your own code.\n\n## Authentication\n\nEvery request carries a workspace API key as a bearer token:\n\n    Authorization: Bearer ttve_live_...\n\nMint one in the dashboard under Settings → API keys. The key is shown once. It is\nscoped to a single workspace and cannot reach any other, so there is no workspace\nor tenant parameter anywhere in this API.\n\nKeys belong on a server. There are deliberately no CORS headers here: an API that\nadvertised itself as browser-callable would invite integrators to ship their keys\nto the client.\n\n## Response shape\n\nSuccess bodies always carry `\"ok\": true`; failures always carry `\"ok\": false` and\nan `error` object with a stable `code`. Branch on `code`, never on message text.\n\n## Rate limits\n\nPer key, per minute. Every response reports `X-RateLimit-Limit`,\n`X-RateLimit-Remaining`, and `X-RateLimit-Reset`; a 429 also sets `Retry-After`.\n\n## Uploading\n\nThree steps, because the bytes do not travel through this API:\n\n1. `POST /api/v1/uploads` — returns a one-shot `uploadUrl`\n2. `PUT` the entire file to that URL, with the headers returned alongside it\n3. `POST /api/v1/uploads/{id}/complete` — verifies the file and queues processing\n\nThen poll `GET /api/v1/videos/{id}` until `status` is `READY`.","x-logo":{"url":"https://ttve.ir/favicon.ico"}},"servers":[{"url":"https://ttve.ir","description":"This deployment."}],"security":[{"bearerAuth":[]}],"tags":[{"name":"me","description":"Identify the calling key and its workspace."},{"name":"usage","description":"Plan limits and current consumption."},{"name":"videos","description":"Read, update, and delete videos; read their playback manifests."},{"name":"uploads","description":"The three-step upload flow."},{"name":"collections","description":"Group videos into ordered collections."},{"name":"analytics","description":"Watch analytics for one video or the whole workspace."}],"paths":{"/api/v1/me":{"get":{"operationId":"getMe","summary":"Describe the calling key","description":"Returns the workspace this key belongs to, the scopes it was granted, the plan limits, and current usage. Call this first to confirm a key works and to discover what it may do.\n\n‏شناسایی کلید و فضای کاری","tags":["me"],"security":[{"bearerAuth":[]}],"x-ttve-scope":null,"parameters":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"plan":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"storageLimitBytes":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"bandwidthLimitBytes":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"monthlyViewsLimit":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"userLimit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["code","name","storageLimitBytes","bandwidthLimitBytes","monthlyViewsLimit","userLimit"],"additionalProperties":false}},"required":["id","name","plan"],"additionalProperties":false},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"role":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["videos:read","videos:write","uploads:write","collections:read","collections:write","subtitles:write","analytics:read"]}}},"required":["id","name","role","scopes"],"additionalProperties":false},"usage":{"type":"object","properties":{"storageUsedBytes":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"bandwidthUsedBytes":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"viewsThisPeriod":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"periodResetAt":{"anyOf":[{"type":"string","description":"ISO-8601 timestamp, UTC."},{"type":"null"}]}},"required":["storageUsedBytes","bandwidthUsedBytes","viewsThisPeriod","periodResetAt"],"additionalProperties":false},"rateLimit":{"type":"object","properties":{"requestsPerMinute":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["requestsPerMinute"],"additionalProperties":false}},"required":["workspace","key","usage","rateLimit"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/usage":{"get":{"operationId":"getUsage","summary":"Storage, bandwidth, and view usage against plan limits","description":"‏مصرف فضا، پهنای باند و بازدید","tags":["usage"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"analytics:read","parameters":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"storage":{"type":"object","properties":{"used":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"limit":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"status":{"type":"string"}},"required":["used","limit","status"],"additionalProperties":false},"bandwidth":{"type":"object","properties":{"used":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"limit":{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},"status":{"type":"string"}},"required":["used","limit","status"],"additionalProperties":false},"views":{"type":"object","properties":{"used":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"status":{"type":"string"}},"required":["used","limit","status"],"additionalProperties":false},"periodResetAt":{"anyOf":[{"type":"string","description":"ISO-8601 timestamp, UTC."},{"type":"null"}]}},"required":["storage","bandwidth","views","periodResetAt"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos":{"get":{"operationId":"listVideos","summary":"List videos in the workspace","description":"Paginated and filterable. Soft-deleted videos are never returned.\n\n‏فهرست ویدئوهای فضای کاری","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:read","parameters":[{"name":"q","in":"query","required":false,"description":"Case-insensitive title search.","schema":{"description":"Case-insensitive title search.","type":"string","maxLength":120}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ALL","UPLOADING","PROCESSING","READY","FAILED"]}},{"name":"visibility","in":"query","required":false,"schema":{"type":"string","enum":["ALL","PUBLIC","UNLISTED","PRIVATE"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["createdAt","title","views","duration","size"]}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"status":{"type":"string","enum":["UPLOADING","PROCESSING","READY","FAILED"]},"processingStage":{"type":"string","enum":["UPLOADING","PROCESSING","GENERATING_THUMBNAIL","TRANSCODING","GENERATING_STREAMING","READY","FAILED"]},"visibility":{"type":"string","enum":["PUBLIC","UNLISTED","PRIVATE"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sizeBytes":{"anyOf":[{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},{"type":"null"}]},"viewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Short-lived signed URL; do not cache."},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","title","status","processingStage","visibility","durationMs","sizeBytes","viewCount","thumbnailUrl","createdAt"],"additionalProperties":false}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pageSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total","page","pageSize","pageCount"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}":{"get":{"operationId":"getVideo","summary":"Fetch one video with its assets","description":"Includes rendition ladder, thumbnails, subtitles, and collection membership. Signed asset URLs in the response are short-lived and must not be cached.\n\n‏دریافت جزئیات یک ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:read","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"status":{"type":"string","enum":["UPLOADING","PROCESSING","READY","FAILED"]},"processingStage":{"type":"string","enum":["UPLOADING","PROCESSING","GENERATING_THUMBNAIL","TRANSCODING","GENERATING_STREAMING","READY","FAILED"]},"visibility":{"type":"string","enum":["PUBLIC","UNLISTED","PRIVATE"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sizeBytes":{"anyOf":[{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},{"type":"null"}]},"viewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Short-lived signed URL; do not cache."},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"mimeType":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"readyAt":{"anyOf":[{"type":"string","description":"ISO-8601 timestamp, UTC."},{"type":"null"}]},"uniqueViewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hasOriginal":{"type":"boolean"},"hasHls":{"type":"boolean"},"embedUrl":{"type":"string","description":"Absolute URL suitable for an <iframe> src."},"watchUrl":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bitrateKbps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["height","width","bitrateKbps","status"],"additionalProperties":false}},"thumbnails":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"source":{"type":"string"},"timestampMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isSelected":{"type":"boolean"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","source","timestampMs","isSelected","url"],"additionalProperties":false}},"subtitles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"format":{"type":"string"},"isDefault":{"type":"boolean"}},"required":["id","language","label","format","isDefault"],"additionalProperties":false}},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["id","title","status","processingStage","visibility","durationMs","sizeBytes","viewCount","thumbnailUrl","createdAt","description","tags","width","height","mimeType","failureReason","readyAt","uniqueViewCount","watchTimeMs","hasOriginal","hasHls","embedUrl","watchUrl","variants","thumbnails","subtitles","collections"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateVideo","summary":"Update a video's metadata or visibility","description":"Only the fields you send are changed. Visibility cannot be raised until the video reaches status READY.\n\n‏ویرایش اطلاعات یا سطح دسترسی ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":300},"description":{"type":"string","maxLength":5000},"tags":{"maxItems":20,"type":"array","items":{"type":"string"}},"visibility":{"type":"string","enum":["PUBLIC","UNLISTED","PRIVATE"]}}}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"video":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"status":{"type":"string","enum":["UPLOADING","PROCESSING","READY","FAILED"]},"processingStage":{"type":"string","enum":["UPLOADING","PROCESSING","GENERATING_THUMBNAIL","TRANSCODING","GENERATING_STREAMING","READY","FAILED"]},"visibility":{"type":"string","enum":["PUBLIC","UNLISTED","PRIVATE"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sizeBytes":{"anyOf":[{"type":"string","description":"Byte count as a decimal string (may exceed 2^53)."},{"type":"null"}]},"viewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"thumbnailUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Short-lived signed URL; do not cache."},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"mimeType":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"readyAt":{"anyOf":[{"type":"string","description":"ISO-8601 timestamp, UTC."},{"type":"null"}]},"uniqueViewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hasOriginal":{"type":"boolean"},"hasHls":{"type":"boolean"},"embedUrl":{"type":"string","description":"Absolute URL suitable for an <iframe> src."},"watchUrl":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bitrateKbps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["height","width","bitrateKbps","status"],"additionalProperties":false}},"thumbnails":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"source":{"type":"string"},"timestampMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isSelected":{"type":"boolean"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","source","timestampMs","isSelected","url"],"additionalProperties":false}},"subtitles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"format":{"type":"string"},"isDefault":{"type":"boolean"}},"required":["id","language","label","format","isDefault"],"additionalProperties":false}},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["id","title","status","processingStage","visibility","durationMs","sizeBytes","viewCount","thumbnailUrl","createdAt","description","tags","width","height","mimeType","failureReason","readyAt","uniqueViewCount","watchTimeMs","hasOriginal","hasHls","embedUrl","watchUrl","variants","thumbnails","subtitles","collections"],"additionalProperties":false}},"required":["video"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteVideo","summary":"Delete a video","description":"Removes the video from every collection, releases its storage quota, and deletes the stored objects. This is not reversible through the API.\n\n‏حذف ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}/playback":{"get":{"operationId":"getVideoPlayback","summary":"Signed playback manifest for a video","description":"Returns the HLS master playlist URL, the quality ladder, and subtitle tracks. Every URL is signed and expires; on a 403 from the media host, call this again.\n\n‏اطلاعات پخش ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:read","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"visibility":{"type":"string","enum":["PUBLIC","UNLISTED","PRIVATE"]},"posterUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Absolute, signed, and short-lived."},"hlsUrl":{"type":"string","description":"Absolute URL of the signed HLS master playlist. Expires; if the media host answers 403, fetch this endpoint again rather than retrying the URL."},"qualities":{"type":"array","items":{"type":"object","properties":{"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"label":{"type":"string"},"playlistUrl":{"type":"string"}},"required":["height","label","playlistUrl"],"additionalProperties":false}},"subtitles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"},"isDefault":{"type":"boolean"}},"required":["id","language","label","url","isDefault"],"additionalProperties":false}},"embedUrl":{"type":"string"}},"required":["videoId","title","durationMs","visibility","posterUrl","hlsUrl","qualities","subtitles","embedUrl"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}/collections":{"put":{"operationId":"setVideoCollections","summary":"Replace a video's collection membership","description":"‏تعیین مجموعه‌های یک ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"collectionIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Replaces the video's collection membership set."}},"required":["collectionIds"]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"updated":{"type":"boolean","const":true}},"required":["updated"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}/subtitles":{"get":{"operationId":"listSubtitles","summary":"List a video's subtitle tracks","description":"‏فهرست زیرنویس‌های ویدئو","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:read","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"format":{"type":"string"},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","language","label","format","isDefault","createdAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSubtitle","summary":"Upload a subtitle track","description":"Send multipart/form-data. WebVTT and SubRip are accepted; SubRip is converted to WebVTT.\n\n‏افزودن زیرنویس","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"subtitles:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"A .vtt or .srt file, at most 512 KB."},"language":{"type":"string","description":"BCP-47 tag, e.g. fa or en."},"label":{"type":"string","description":"Human-readable track name."},"isDefault":{"type":"string","description":"Make this the default track."}},"required":["file","language","label"]}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"format":{"type":"string"},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","language","label","format","isDefault","createdAt"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}/subtitles/{subtitleId}":{"patch":{"operationId":"updateSubtitle","summary":"Rename or re-tag a subtitle track","description":"‏ویرایش زیرنویس","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"subtitles:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}},{"name":"subtitleId","in":"path","required":true,"description":"The subtitle UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"language":{"type":"string","minLength":2,"maxLength":16},"label":{"type":"string","minLength":1,"maxLength":80},"isDefault":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"language":{"type":"string"},"label":{"type":"string"},"format":{"type":"string"},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","language","label","format","isDefault","createdAt"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteSubtitle","summary":"Delete a subtitle track","description":"‏حذف زیرنویس","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"subtitles:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}},{"name":"subtitleId","in":"path","required":true,"description":"The subtitle UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/videos/{id}/thumbnails":{"get":{"operationId":"listThumbnails","summary":"List a video's thumbnails","description":"‏فهرست تصاویر شاخص","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:read","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"source":{"type":"string"},"timestampMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isSelected":{"type":"boolean"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","source","timestampMs","isSelected","url"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"selectThumbnail","summary":"Choose which thumbnail represents the video","description":"Selects one of the frames the processing pipeline generated. Uploading a custom image is dashboard-only in v1.\n\n‏انتخاب تصویر شاخص","tags":["videos"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"videos:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"thumbnailId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["thumbnailId"]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"source":{"type":"string"},"timestampMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isSelected":{"type":"boolean"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","source","timestampMs","isSelected","url"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/uploads":{"post":{"operationId":"createUpload","summary":"Start an upload and get a one-shot URL","description":"Step 1 of 3. Reserves quota, creates the video record, and returns a short-lived URL. PUT the entire file to that URL, then call the complete endpoint. The URL is issued by TTVE, not by object storage, and is bound to this exact file size and content type.\n\n‏شروع بارگذاری و دریافت نشانی آپلود","tags":["uploads"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"uploads:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":300},"description":{"type":"string","maxLength":5000},"tags":{"maxItems":20,"type":"array","items":{"type":"string"}},"collectionId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"filename":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","description":"One of: video/mp4, video/quicktime, video/webm, video/x-matroska."},"sizeBytes":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Exact byte length of the file you will PUT."}},"required":["title","filename","contentType","sizeBytes"]}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadUrl":{"type":"string","description":"PUT the whole file here in one request. This is a TTVE-hosted capability URL, not an S3 presigned URL."},"method":{"type":"string","const":"PUT"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"Send these verbatim on the PUT."},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["videoId","uploadUrl","method","headers","expiresInSeconds"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/uploads/{id}/complete":{"post":{"operationId":"completeUpload","summary":"Finish an upload and queue processing","description":"Step 3 of 3. Verifies the stored byte count and the file's magic bytes, then queues transcoding. Safe to retry: calling it twice does not queue the job twice.\n\n‏پایان بارگذاری و ارسال به صف پردازش","tags":["uploads"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"uploads:write","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID returned by the upload step.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["UPLOADING","PROCESSING","READY","FAILED"]},"processingStage":{"type":"string","enum":["UPLOADING","PROCESSING","GENERATING_THUMBNAIL","TRANSCODING","GENERATING_STREAMING","READY","FAILED"]},"jobId":{"anyOf":[{"type":"string"},{"type":"null"}]},"alreadyQueued":{"type":"boolean"}},"required":["videoId","status","processingStage","jobId","alreadyQueued"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/collections":{"get":{"operationId":"listCollections","summary":"List collections","description":"‏فهرست مجموعه‌ها","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:read","parameters":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"description":{"type":"string"},"videoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","name","description","videoCount","createdAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createCollection","summary":"Create a collection","description":"‏ساخت مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":5000}},"required":["name"]}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"description":{"type":"string"},"videoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","name","description","videoCount","createdAt"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/collections/{id}":{"get":{"operationId":"getCollection","summary":"Fetch one collection with its videos in order","description":"‏دریافت جزئیات مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:read","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"description":{"type":"string"},"videoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."},"videos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"status":{"type":"string","enum":["UPLOADING","PROCESSING","READY","FAILED"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","title","status","durationMs","sortOrder"],"additionalProperties":false}}},"required":["id","name","description","videoCount","createdAt","videos"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateCollection","summary":"Rename a collection or change its description","description":"‏ویرایش مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":5000}}}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"description":{"type":"string"},"videoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string","description":"ISO-8601 timestamp, UTC."}},"required":["id","name","description","videoCount","createdAt"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteCollection","summary":"Delete a collection","description":"The videos inside are unlinked, not deleted.\n\n‏حذف مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}]}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/collections/{id}/videos":{"post":{"operationId":"addCollectionVideo","summary":"Add a video to a collection","description":"‏افزودن ویدئو به مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["videoId"]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"updated":{"type":"boolean","const":true}},"required":["updated"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeCollectionVideo","summary":"Remove a video from a collection","description":"‏حذف ویدئو از مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["videoId"]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"updated":{"type":"boolean","const":true}},"required":["updated"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/collections/{id}/order":{"put":{"operationId":"reorderCollection","summary":"Reorder the videos in a collection","description":"Send every video id currently in the collection. A partial list is rejected.\n\n‏تغییر ترتیب ویدئوهای مجموعه","tags":["collections"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"collections:write","parameters":[{"name":"id","in":"path","required":true,"description":"The resource UUID.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"videoIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Every video currently in the collection, in the new order."}},"required":["videoIds"]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"updated":{"type":"boolean","const":true}},"required":["updated"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/analytics/videos/{id}":{"get":{"operationId":"getVideoAnalytics","summary":"Watch analytics for one video","description":"‏آمار تماشای یک ویدئو","tags":["analytics"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"analytics:read","parameters":[{"name":"id","in":"path","required":true,"description":"The video UUID.","schema":{"type":"string","format":"uuid"}},{"name":"range","in":"query","required":false,"schema":{"type":"string","enum":["7d","30d","90d"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"videoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"range":{"type":"string"},"totals":{"type":"object","properties":{"views":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"uniqueViewers":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"averageWatchTimeMs":{"type":"number"},"completionRate":{"type":"number"},"averagePercentWatched":{"type":"number"}},"required":["views","uniqueViewers","watchTimeMs","averageWatchTimeMs","completionRate","averagePercentWatched"],"additionalProperties":false},"series":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","description":"YYYY-MM-DD, UTC."},"views":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["day","views","watchTimeMs"],"additionalProperties":false}},"engagement":{"type":"array","items":{"type":"object","properties":{"percent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"impressions":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["percent","impressions"],"additionalProperties":false}}},"required":["videoId","range","totals","series","engagement"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/analytics/workspace":{"get":{"operationId":"getWorkspaceAnalytics","summary":"Watch analytics across the workspace","description":"‏آمار تماشای کل فضای کاری","tags":["analytics"],"security":[{"bearerAuth":[]}],"x-ttve-scope":"analytics:read","parameters":[{"name":"range","in":"query","required":false,"schema":{"type":"string","enum":["7d","30d","90d"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},{"type":"object","properties":{"range":{"type":"string"},"totals":{"type":"object","properties":{"views":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"uniqueViewers":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"averageWatchTimeMs":{"type":"number"},"completionRate":{"type":"number"}},"required":["views","uniqueViewers","watchTimeMs","averageWatchTimeMs","completionRate"],"additionalProperties":false},"series":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","description":"YYYY-MM-DD, UTC."},"views":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["day","views","watchTimeMs"],"additionalProperties":false}},"topVideos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"views":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"watchTimeMs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","title","views","watchTimeMs"],"additionalProperties":false}}},"required":["range","totals","series","topVideos"],"additionalProperties":false}]}}}},"400":{"description":"The request failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded. Honour the Retry-After header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A workspace API key, e.g. `ttve_live_...`. Mint one under Settings → API keys."}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"type":"boolean","const":false},"error":{"type":"object","required":["code","message","messageFa","docs"],"properties":{"code":{"type":"string","description":"Stable machine-readable code. Safe to branch on.","examples":["unauthenticated","forbidden","validation","not_found","conflict","not_ready","too_large","quota_exceeded","internal"]},"message":{"type":"string","description":"English, for the developer."},"messageFa":{"type":"string","description":"Persian, safe to show an end user."},"field":{"type":"string","description":"The offending field, when one can be named."},"docs":{"type":"string","description":"Link to this error in the developer docs."}}}}}},"x-scopes":{"videos:read":"videos:read","videos:write":"videos:write","uploads:write":"uploads:write","collections:read":"collections:read","collections:write":"collections:write","subtitles:write":"subtitles:write","analytics:read":"analytics:read"},"x-errorCodes":{"unauthenticated":{"status":401,"message":"Missing or invalid API key. Send it as: Authorization: Bearer ttve_live_…"},"forbidden":{"status":403,"message":"This API key is not allowed to perform that action."},"validation":{"status":400,"message":"The request body or query string failed validation."},"not_found":{"status":404,"message":"No such resource in this workspace."},"conflict":{"status":409,"message":"That change conflicts with the resource's current state."},"not_ready":{"status":409,"message":"The video is still processing and cannot be published yet."},"too_large":{"status":413,"message":"The upload exceeds the maximum allowed size."},"quota_exceeded":{"status":413,"message":"The workspace has no storage left on its current plan."},"internal":{"status":500,"message":"Something went wrong on our side. Try again."}}}}