{
    "openapi": "3.0.3",
    "info": {
        "title": "Minimus API",
        "version": "1.0.0",
        "description": "The Minimus API is the panel's own API: the dashboard is built on it, so\neverything you do there can be done with a script, an integration or an AI app.\n\nEvery call is made **as an account** (a staff member, a reseller…) and can\nnever do more than that account can in the dashboard. An API key or an AI app\nis further limited by its scopes: `read`, `write` and `manage`.\n\nSend requests to your own panel's address, with an API key in the\n`Authorization` header. Guides: https://docs.minimus.tv\n"
    },
    "paths": {
        "/auth/groups/": {
            "get": {
                "operationId": "auth_groups_list",
                "description": "Groups you can see, a page at a time, by name: those you manage and your own.",
                "summary": "List groups",
                "parameters": [
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "`mine`: groups you created; `subtree`: the groups below yours; `all`: every group (for those who may see all)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name, or the name of a permission it gives."
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedGroupListList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "auth_groups_create",
                "description": "A reseller creates groups under their own and gives only permissions they hold. Trial and refund rules are set by panel operators; a reseller's new group starts with its parent's.",
                "summary": "Create a group",
                "tags": [
                    "Groups and permissions"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Group"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/groups/{group_id}/permissions/": {
            "post": {
                "operationId": "auth_groups_permissions_create",
                "description": "Replace a group's permissions with these, by codename (e.g. `add_stream`). A reseller gives only permissions they hold.",
                "summary": "Set a group's permissions",
                "parameters": [
                    {
                        "in": "path",
                        "name": "group_id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPermissionsRequestDocRequest"
                            },
                            "examples": {
                                "AssignPermissionsRequest": {
                                    "value": {
                                        "permission_codenames": [
                                            "add_stream",
                                            "change_stream",
                                            "delete_stream"
                                        ]
                                    },
                                    "summary": "Assign permissions request"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPermissionsRequestDocRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPermissionsRequestDocRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AssignPermissionsToGroupResponseDoc"
                                },
                                "examples": {
                                    "AssignPermissionsToGroupResponse": {
                                        "value": {
                                            "message": "Assigned 3 permissions to group Reseller",
                                            "group": {
                                                "id": 1,
                                                "name": "Reseller"
                                            },
                                            "assigned_permissions": [
                                                "add_stream",
                                                "change_stream"
                                            ],
                                            "not_assigned": []
                                        },
                                        "summary": "Assign permissions to group response"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/groups/{group_id}/remove-user/{user_id}/": {
            "post": {
                "operationId": "auth_groups_remove_user_create",
                "description": "Take an account out of a group you manage. A staff account can't leave its last reseller group.",
                "summary": "Remove a user from a group",
                "parameters": [
                    {
                        "in": "path",
                        "name": "group_id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "user_id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RemoveUserFromGroupResponseDoc"
                                },
                                "examples": {
                                    "RemoveUserFromGroupResponse": {
                                        "value": {
                                            "message": "User 'john' has been removed from group 'Reseller' successfully",
                                            "user_id": "550e8400-e29b-41d4-a716-446655440000",
                                            "group_id": 1,
                                            "group_name": "Reseller"
                                        },
                                        "summary": "Remove user from group response"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/groups/{id}/": {
            "get": {
                "operationId": "auth_groups_retrieve",
                "description": "One group, with its members and permissions.",
                "summary": "Get a group",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Group"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "auth_groups_update",
                "description": "Change a group you manage. You can give only permissions you hold; trial and refund rules are changed by panel operators only.",
                "summary": "Replace a group",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/GroupWriteRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Group"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "auth_groups_partial_update",
                "description": "Change some of a group you manage. You can give only permissions you hold; trial and refund rules are changed by panel operators only.",
                "summary": "Update a group",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedGroupWriteRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedGroupWriteRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedGroupWriteRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Group"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "auth_groups_destroy",
                "description": "Delete a group you manage. A reseller group can't be deleted while it would leave a member with no reseller group.",
                "summary": "Delete a group",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/groups/assignable/": {
            "get": {
                "operationId": "auth_groups_assignable_list",
                "description": "The groups you may choose for a staff user you create. `required` marks one that must stay chosen.",
                "summary": "List groups you can put a new staff user in",
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/AssignableGroup"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/line-users/": {
            "get": {
                "operationId": "auth_line_users_list",
                "description": "The lines you can see, a page at a time: yours first, then the newest. Each comes with its settings (`line_profile`), its current package and how many connections it has open.",
                "summary": "List lines",
                "parameters": [
                    {
                        "in": "query",
                        "name": "group",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only lines in this group."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "owner",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The id of the account that created the line, or `none` for lines with no owner."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "`mine`: lines you created; `subtree`: those and the lines of everyone below you; `all`: every line (for those who may see all lines, otherwise the same as `subtree`)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the username, the owner's username or part of the id."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "active",
                                "banned",
                                "disabled",
                                "expired",
                                "online",
                                "restreamer",
                                "trial"
                            ]
                        },
                        "description": "`active`: can watch now; `disabled`: can't watch and is not banned; `online`: watching now."
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedLineUserWithProfileList"
                                },
                                "examples": {
                                    "APageOfLines": {
                                        "value": {
                                            "count": 128,
                                            "next": "https://panel.example.com/streams/?page=3&page_size=20",
                                            "previous": "https://panel.example.com/streams/?page=1&page_size=20",
                                            "results": [
                                                {
                                                    "id": "8a3e6f10-2b7c-4d9e-a5f1-6c0b3d8e2a47",
                                                    "username": "alice",
                                                    "email": "",
                                                    "first_name": "",
                                                    "last_name": "",
                                                    "phone_number": "",
                                                    "phone_country_code": "",
                                                    "is_staff": false,
                                                    "is_active": true,
                                                    "groups": [],
                                                    "created_at": "2026-11-13T10:00:00Z",
                                                    "updated_at": "2026-11-13T10:00:00Z",
                                                    "profile": {
                                                        "user_type": "line",
                                                        "user_type_display": "Line User",
                                                        "created_at": "2026-11-13T10:00:00Z",
                                                        "updated_at": "2026-11-13T10:00:00Z"
                                                    },
                                                    "line_profile": {
                                                        "status": "active",
                                                        "status_display": "Active",
                                                        "max_connections": 1,
                                                        "expire_date": "2026-12-13T10:00:00Z",
                                                        "allowed_user_agent": "",
                                                        "allowed_ips": "",
                                                        "blocked_ips": "",
                                                        "reseller_notes": "",
                                                        "is_expired": false,
                                                        "created_at": "2026-11-13T10:00:00Z",
                                                        "updated_at": "2026-11-13T10:00:00Z",
                                                        "last_activity": "2026-11-13T18:42:10Z",
                                                        "created_by_username": "reseller1",
                                                        "bouquets": [
                                                            "0b8f3c52-6d1e-4a7b-9c2f-5e8d1a4b7c30"
                                                        ],
                                                        "bouquets_display": [
                                                            {
                                                                "id": "0b8f3c52-6d1e-4a7b-9c2f-5e8d1a4b7c30",
                                                                "name": "Sports"
                                                            }
                                                        ],
                                                        "is_trial": false,
                                                        "is_restreamer": false,
                                                        "forced_countries": "",
                                                        "lock_to_isp": false,
                                                        "locked_isp": "",
                                                        "forced_server": null,
                                                        "forced_server_name": null,
                                                        "output_formats": "",
                                                        "package": {
                                                            "id": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85",
                                                            "name": "1 month",
                                                            "is_trial": false,
                                                            "assigned_at": "2026-11-13T10:00:00Z",
                                                            "expires_at": "2026-12-13T10:00:00Z"
                                                        }
                                                    },
                                                    "active_connections": 1,
                                                    "is_online": true
                                                }
                                            ]
                                        },
                                        "summary": "A page of lines"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "auth_line_users_create",
                "description": "Make a line. A `package` sets its length, connections, restrictions and bouquets; what you send overrides it, except that a reseller must give a package, pays its price (`charge`), and gets the length, trial flag and connections it sets.",
                "summary": "Create a line",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserCreateRequest"
                            },
                            "examples": {
                                "AResellerMakesALineWithAPackage": {
                                    "value": {
                                        "username": "alice",
                                        "password": "k7Qm2xVr9p",
                                        "password_confirm": "k7Qm2xVr9p",
                                        "package": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85",
                                        "reseller_notes": "Flat 4, pays monthly"
                                    },
                                    "summary": "A reseller makes a line with a package"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineCreated"
                                },
                                "examples": {
                                    "Created": {
                                        "value": {
                                            "id": "8a3e6f10-2b7c-4d9e-a5f1-6c0b3d8e2a47",
                                            "username": "alice",
                                            "email": "",
                                            "first_name": "",
                                            "last_name": "",
                                            "is_active": true,
                                            "expire_date": "2026-12-13T10:00:00Z",
                                            "max_connections": 1,
                                            "is_trial": false,
                                            "forced_server": null,
                                            "charge": {
                                                "amount": "10.00",
                                                "balance_after": "440.00"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/auth/line-users/{id}/": {
            "get": {
                "operationId": "auth_line_users_retrieve",
                "description": "One line you can see, with its settings, current package and open connections.",
                "summary": "Get a line",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineUserWithProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "auth_line_users_update",
                "description": "Change a line's details and settings. A reseller can't change the expiry, connections or trial flag (extend the line with a package instead), nor give bouquets its package doesn't have. Answers the line as `GET` does.",
                "summary": "Replace a line",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUpdateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUpdateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUpdateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineUserWithProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "auth_line_users_partial_update",
                "description": "Change some of a line's details and settings. A reseller can't change the expiry, connections or trial flag (extend the line with a package instead), nor give bouquets its package doesn't have. Answers the line as `GET` does.",
                "summary": "Update a line",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedLineUpdateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedLineUpdateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedLineUpdateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineUserWithProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "auth_line_users_destroy",
                "description": "Delete a line. When the payer's group refunds deleted lines and the last payment is recent enough, it is given back: `refunded` and `to` say how much and to whom.",
                "summary": "Delete a line",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineDeleted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/line-users/{id}/extend/": {
            "post": {
                "operationId": "auth_line_users_extend_create",
                "description": "Add the package's length to the line's time left (from now if it has expired) and apply its connections and restrictions. The line keeps its bouquets and own settings unless you ask for `reset_bouquets` or `reset_settings`. You pay the package's price: `charge`.",
                "summary": "Extend a line with a package",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LineExtendRequest"
                            },
                            "examples": {
                                "ExtendByOneMonth": {
                                    "value": {
                                        "package": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85"
                                    },
                                    "summary": "Extend by one month"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/LineExtendRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/LineExtendRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineExtended"
                                },
                                "examples": {
                                    "Extended": {
                                        "value": {
                                            "detail": "Line extended with \"1 month\".",
                                            "previous_expire_date": "2026-12-13T10:00:00Z",
                                            "expire_date": "2027-01-12T10:00:00Z",
                                            "package": {
                                                "id": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85",
                                                "name": "1 month"
                                            },
                                            "assignment_id": "c41e7b2d-9f3a-4e6c-8b5d-2a1f0e9c7d36",
                                            "line": {
                                                "id": "8a3e6f10-2b7c-4d9e-a5f1-6c0b3d8e2a47",
                                                "username": "alice",
                                                "email": "",
                                                "first_name": "",
                                                "last_name": "",
                                                "phone_number": "",
                                                "phone_country_code": "",
                                                "is_staff": false,
                                                "is_active": true,
                                                "groups": [],
                                                "created_at": "2026-11-13T10:00:00Z",
                                                "updated_at": "2026-11-13T10:00:00Z",
                                                "profile": {
                                                    "user_type": "line",
                                                    "user_type_display": "Line User",
                                                    "created_at": "2026-11-13T10:00:00Z",
                                                    "updated_at": "2026-11-13T10:00:00Z"
                                                },
                                                "line_profile": {
                                                    "status": "active",
                                                    "status_display": "Active",
                                                    "max_connections": 1,
                                                    "expire_date": "2027-01-12T10:00:00Z",
                                                    "allowed_user_agent": "",
                                                    "allowed_ips": "",
                                                    "blocked_ips": "",
                                                    "reseller_notes": "",
                                                    "is_expired": false,
                                                    "created_at": "2026-11-13T10:00:00Z",
                                                    "updated_at": "2026-11-13T10:00:00Z",
                                                    "last_activity": "2026-11-13T18:42:10Z",
                                                    "created_by_username": "reseller1",
                                                    "bouquets": [
                                                        "0b8f3c52-6d1e-4a7b-9c2f-5e8d1a4b7c30"
                                                    ],
                                                    "bouquets_display": [
                                                        {
                                                            "id": "0b8f3c52-6d1e-4a7b-9c2f-5e8d1a4b7c30",
                                                            "name": "Sports"
                                                        }
                                                    ],
                                                    "is_trial": false,
                                                    "is_restreamer": false,
                                                    "forced_countries": "",
                                                    "lock_to_isp": false,
                                                    "locked_isp": "",
                                                    "forced_server": null,
                                                    "forced_server_name": null,
                                                    "output_formats": "",
                                                    "package": {
                                                        "id": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85",
                                                        "name": "1 month",
                                                        "is_trial": false,
                                                        "assigned_at": "2026-11-13T10:00:00Z",
                                                        "expires_at": "2026-12-13T10:00:00Z"
                                                    }
                                                },
                                                "active_connections": 1,
                                                "is_online": true
                                            },
                                            "charge": {
                                                "amount": "10.00",
                                                "balance_after": "430.00"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/auth/line-users/{id}/refund-quote/": {
            "get": {
                "operationId": "auth_line_users_refund_quote_retrieve",
                "description": "What deleting the line now would give back, why, and to whom.",
                "summary": "Preview the refund for deleting a line",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineRefundQuote"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/line-users/{id}/set-password/": {
            "post": {
                "operationId": "auth_line_users_set_password_create",
                "description": "Give a line a new password. A line's password is never shown, so this is how a customer gets a new link.",
                "summary": "Set a line's password",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserSetPasswordRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserSetPasswordRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/LineUserSetPasswordRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PasswordSet"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/auth/line-users/summary/": {
            "get": {
                "operationId": "auth_line_users_summary_list",
                "description": "How many lines you can see, and how many of them can watch now.",
                "summary": "Count lines",
                "parameters": [
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "`mine`: lines you created; `subtree`: those and the lines of everyone below you; `all`: every line (for those who may see all lines, otherwise the same as `subtree`)."
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineSummary"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/permissions/": {
            "get": {
                "operationId": "auth_permissions_retrieve",
                "description": "Your username, whether you are staff or a superuser, every permission you hold (`app.codename`) and your groups.",
                "summary": "Get your own permissions",
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CurrentUserPermissionsResponseDoc"
                                },
                                "examples": {
                                    "CurrentUserPermissionsResponse": {
                                        "value": {
                                            "username": "admin",
                                            "is_staff": true,
                                            "is_superuser": false,
                                            "permissions": [
                                                "streams.add_stream",
                                                "streams.change_stream"
                                            ],
                                            "groups": [
                                                "Super Reseller"
                                            ]
                                        },
                                        "summary": "Current user permissions response"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/permissions-list/": {
            "get": {
                "operationId": "auth_permissions_list_list",
                "description": "Every permission for a superuser; for anyone else, the ones they hold. One list, not paged.",
                "summary": "List permissions you can give",
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Permission"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/permissions/available/": {
            "get": {
                "operationId": "auth_permissions_available_retrieve",
                "description": "The permissions you can give, with how many there are, optionally for one app only.",
                "summary": "Filter permissions you can give by app",
                "parameters": [
                    {
                        "in": "query",
                        "name": "app",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only this app's permissions (e.g. `streams`)."
                    }
                ],
                "tags": [
                    "Groups and permissions"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AvailablePermissionsResponseDoc"
                                },
                                "examples": {
                                    "AvailablePermissionsResponse": {
                                        "value": {
                                            "permissions": [
                                                {
                                                    "id": 1,
                                                    "name": "Can add stream",
                                                    "codename": "add_stream",
                                                    "content_type": 7
                                                }
                                            ],
                                            "total_count": 1
                                        },
                                        "summary": "Available permissions response"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/auth/staff-users/": {
            "get": {
                "operationId": "auth_staff_users_list",
                "description": "Accounts with dashboard access (staff and resellers) you can see, by username.",
                "summary": "List staff users",
                "parameters": [
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "`mine`: accounts you created; `subtree` (default): those and everyone below them; `all`: every account (for those who may see all)."
                    }
                ],
                "tags": [
                    "Users"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedStaffUserListList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "auth_staff_users_create",
                "description": "Create an account with dashboard access, in the groups and with the permissions given. You can give only permissions you hold, and a reseller creates resellers only.",
                "summary": "Create a staff user",
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StaffUserCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StaffUserCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StaffUserCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StaffUserCreate"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/users/": {
            "get": {
                "operationId": "auth_users_list",
                "description": "Accounts you can see (staff, resellers and lines), a page at a time, by username.",
                "summary": "List users",
                "parameters": [
                    {
                        "in": "query",
                        "name": "group",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only members of this group."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "owner",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only accounts this account created."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "`mine`: accounts you created; `subtree`: those and everyone below them; `all`: every account (for those who may see all, otherwise the same as `subtree`)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the username, email, first or last name."
                    },
                    {
                        "in": "query",
                        "name": "user_type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "line",
                                "panel",
                                "staff",
                                "superuser"
                            ]
                        },
                        "description": "`panel`: every dashboard account (superusers and staff)."
                    }
                ],
                "tags": [
                    "Users"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedUserListList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "auth_users_create",
                "description": "Create an account, owned by you. A reseller creates only dashboard accounts (`is_staff`) in reseller groups here: lines are made with `POST /auth/line-users/`.",
                "summary": "Create a user",
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UserCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/UserCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UserCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserCreate"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/users/{id}/": {
            "get": {
                "operationId": "auth_users_retrieve",
                "description": "One account you can see, with its groups, permissions and credits.",
                "summary": "Get a user",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/User"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "auth_users_update",
                "description": "Change an account's details, status and groups. Only a superuser makes or unmakes a superuser.",
                "summary": "Replace a user",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UserRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/UserRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UserRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/User"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "auth_users_partial_update",
                "description": "Change some of an account's details, status or groups. Only a superuser makes or unmakes a superuser.",
                "summary": "Update a user",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/User"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "auth_users_destroy",
                "description": "Delete an account you can see. A reseller's credits go back to the reseller above them or are written off; their lines are kept.",
                "summary": "Delete a user",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/users/{id}/permissions/": {
            "get": {
                "operationId": "auth_users_permissions_list",
                "description": "Everything the account may do, from its groups and given to it directly, by model. `source` says where each one comes from.",
                "summary": "List a user's permissions",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/UserPermissionsResponseDoc"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "auth_users_permissions_update",
                "description": "Replace the permissions given to the account itself (its groups' stay) and answer the full list again. You can give only permissions you hold. Needs the permission to change users.",
                "summary": "Set the permissions given to a user",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPermissionIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPermissionIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPermissionIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/UserPermissionsResponseDoc"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/auth/users/{user_id}/groups/": {
            "post": {
                "operationId": "auth_users_groups_create",
                "description": "Put an account in these groups instead of its current ones. A reseller sets only groups they manage, on accounts below them; the account's other groups are kept.",
                "summary": "Set a user's groups",
                "parameters": [
                    {
                        "in": "path",
                        "name": "user_id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Users"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignGroupsRequestDocRequest"
                            },
                            "examples": {
                                "AssignGroupsRequest": {
                                    "value": {
                                        "group_ids": [
                                            1,
                                            2,
                                            3
                                        ]
                                    },
                                    "summary": "Assign groups request"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignGroupsRequestDocRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignGroupsRequestDocRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AssignUserToGroupsResponseDoc"
                                },
                                "examples": {
                                    "AssignUserToGroupsResponse": {
                                        "value": {
                                            "message": "Assigned user john to 2 groups",
                                            "user": {
                                                "id": "550e8400-e29b-41d4-a716-446655440000",
                                                "username": "john"
                                            },
                                            "groups": [
                                                "Reseller",
                                                "Super Reseller"
                                            ]
                                        },
                                        "summary": "Assign user to groups response"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/imports/": {
            "get": {
                "operationId": "backups_imports_list",
                "description": "Backup files uploaded or prepared for a restore in the last week, newest first, at most 20. Panel operators only.",
                "summary": "List backup imports",
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/BackupImport"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "backups_imports_create",
                "description": "Announces the file's name and size, then send it in pieces with \"Upload part of a backup file\". Refused (400) when the disk has not enough free space. Panel operators only.",
                "summary": "Start uploading a backup file",
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportStartRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportStartRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportStartRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/imports/{import_id}/": {
            "get": {
                "operationId": "backups_imports_retrieve",
                "description": "Its upload or restore progress, and what the file holds once checked. Panel operators only.",
                "summary": "Get a backup import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "import_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The backup import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "delete": {
                "operationId": "backups_imports_destroy",
                "description": "Removes the uploaded file. Refused (409) while it is uploading or restoring. Panel operators only.",
                "summary": "Delete a backup import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "import_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The backup import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/imports/{import_id}/check/": {
            "post": {
                "operationId": "backups_imports_check_create",
                "description": "Reads the whole file once uploaded: what it holds, which panel version made it, and its administrators against this panel's. An encrypted file needs its `passphrase`. Panel operators only.",
                "summary": "Check an uploaded backup file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "import_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The backup import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportCheckRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportCheckRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportCheckRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/imports/{import_id}/data/": {
            "put": {
                "operationId": "backups_imports_data_update",
                "description": "The raw bytes of the next piece, as the request body. When a piece is not where the upload stands, nothing is written and `expected_offset` says where to resume. Panel operators only.",
                "summary": "Upload part of a backup file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "import_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The backup import's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "offset",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Where this piece starts in the file, in bytes."
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/octet-stream": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/imports/{import_id}/restore/": {
            "post": {
                "operationId": "backups_imports_restore_create",
                "description": "Restores the whole database (`whole`) or only the chosen `components`, in the background (202). `keep_admins` keeps this panel's administrators so you can still sign in; `keys` also restores the key files the backup holds. Panel operators only.",
                "summary": "Restore an uploaded backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "import_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The backup import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportRestoreRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportRestoreRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupImportRestoreRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/overview/": {
            "get": {
                "operationId": "backups_overview_retrieve",
                "description": "What a backup can hold (with sizes), the choices for schedules and storage, free disk space, the last and next backup, and what the signed-in account may do. Panel operators only.",
                "summary": "Get the backups overview",
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupOverview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/backups/runs/": {
            "get": {
                "operationId": "backups_runs_list",
                "description": "Backups made by hand and by schedules, newest first, a page at a time. Panel operators only.",
                "summary": "List backups",
                "parameters": [
                    {
                        "in": "query",
                        "name": "include_deleted",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "`true` to list deleted backups too."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "plan",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only backups of this schedule (its id), or `manual` for those started by hand."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only these statuses, comma-separated: `pending`, `running`, `uploading`, `completed`, `failed`, `cancelled`."
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedBackupList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "backups_runs_create",
                "description": "Starts a backup in the background and answers with it (202); follow it with \"Get a backup\" or under Background tasks. Panel operators only.",
                "summary": "Start a backup",
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StartBackupRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StartBackupRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StartBackupRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Backup"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/runs/{id}/": {
            "get": {
                "operationId": "backups_runs_retrieve",
                "description": "Panel operators only.",
                "summary": "Get a backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Backup"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "delete": {
                "operationId": "backups_runs_destroy",
                "description": "Deletes every stored copy. Refused (409) while the backup is still running; 502 when a copy could not be deleted. Panel operators only.",
                "summary": "Delete a backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "502": {
                        "description": "A copy could not be deleted."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/runs/{id}/cancel/": {
            "post": {
                "operationId": "backups_runs_cancel_create",
                "description": "Stops a backup that is still running. Refused (409) once it has finished. Panel operators only.",
                "summary": "Cancel a backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Backup"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/runs/{id}/download-link/": {
            "post": {
                "operationId": "backups_runs_download_link_create",
                "description": "A link that downloads the backup file without signing in, valid for `expires_in` seconds. Needs the permission to download backups. Panel operators only.",
                "summary": "Get a download link for a backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupDownloadLink"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "No stored copy of this backup is left."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/runs/{id}/restore/": {
            "post": {
                "operationId": "backups_runs_restore_create",
                "description": "Prepares a restore from a stored backup and answers with a backup import (201). Then check it and restore it with the backup import calls. Panel operators only.",
                "summary": "Restore from a backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/schedules/": {
            "get": {
                "operationId": "backups_schedules_list",
                "description": "What each schedule backs up, when, where, and how many backups it keeps, with its last backup. Panel operators only.",
                "summary": "List backup schedules",
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/BackupPlan"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "backups_schedules_create",
                "description": "An encrypted schedule needs a `passphrase` (at least 8 characters); it is never returned. Panel operators only.",
                "summary": "Create a backup schedule",
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/schedules/{id}/": {
            "get": {
                "operationId": "backups_schedules_retrieve",
                "description": "Panel operators only.",
                "summary": "Get a backup schedule",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Schedule.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "backups_schedules_update",
                "description": "Panel operators only.",
                "summary": "Replace a backup schedule",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Schedule.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupPlanRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "backups_schedules_partial_update",
                "description": "Leave `passphrase` out to keep the one already set. Panel operators only.",
                "summary": "Update a backup schedule",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Schedule.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupPlanRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupPlanRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupPlanRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "backups_schedules_destroy",
                "description": "The backups it made are kept. Panel operators only.",
                "summary": "Delete a backup schedule",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Schedule.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/schedules/{id}/run/": {
            "post": {
                "operationId": "backups_schedules_run_create",
                "description": "Starts a backup from this schedule in the background and answers with it (202). Refused (409) while the schedule is already running. Panel operators only.",
                "summary": "Run a backup schedule now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Schedule.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Backup"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/schedules/preview/": {
            "post": {
                "operationId": "backups_schedules_preview_create",
                "description": "The next run times for the timing given, without saving anything. Panel operators only.",
                "summary": "Preview when a backup schedule runs",
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupScheduleTimingRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupScheduleTimingRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupScheduleTimingRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupSchedulePreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/storage/": {
            "get": {
                "operationId": "backups_storage_list",
                "description": "Where backups can be kept: folders on this server, or a folder in a storage bucket. Panel operators only.",
                "summary": "List backup storage",
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/BackupDestination"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "backups_storage_create",
                "description": "`kind` `local` needs a `folder`; `kind` `s3` needs a `storage` (a storage connection from Settings → Storage). Panel operators only.",
                "summary": "Add backup storage",
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupDestination"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/storage/{id}/": {
            "get": {
                "operationId": "backups_storage_retrieve",
                "description": "Panel operators only.",
                "summary": "Get backup storage",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Storage.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupDestination"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "backups_storage_update",
                "description": "Panel operators only.",
                "summary": "Replace backup storage",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Storage.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BackupDestinationRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupDestination"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "backups_storage_partial_update",
                "description": "Panel operators only.",
                "summary": "Update backup storage",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Storage.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupDestinationRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupDestinationRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBackupDestinationRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupDestination"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "backups_storage_destroy",
                "description": "Refused (409) while a backup schedule still uses it. Panel operators only.",
                "summary": "Delete backup storage",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Storage.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "409": {
                        "description": "Not now: the answer says why."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/backups/storage/{id}/check/": {
            "post": {
                "operationId": "backups_storage_check_create",
                "description": "Writes a small test file there and removes it again. Answers 200 when that worked, 400 with the reason when it did not. Panel operators only.",
                "summary": "Check backup storage",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Backup Storage.",
                        "required": true
                    }
                ],
                "tags": [
                    "Backups"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupStorageCheck"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackupStorageCheck"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/credits/accounts/": {
            "get": {
                "operationId": "credits_accounts_list",
                "description": "The resellers you can see, with their balance, spending this month and cheapest package price, a page at a time.",
                "summary": "List resellers' credits",
                "parameters": [
                    {
                        "in": "query",
                        "name": "low",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only resellers whose balance is below their cheapest package price (and not unlimited)."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "subtree"
                            ]
                        },
                        "description": "`subtree`: only the resellers below you, the ones you can give credits to."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the username."
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedAccountList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/accounts/{id}/": {
            "get": {
                "operationId": "credits_accounts_retrieve",
                "description": "One reseller's balance, spending this month and cheapest package price.",
                "summary": "Get a reseller's credits",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Account"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "credits_accounts_partial_update",
                "description": "With unlimited credits, a reseller's lines cost nothing whatever their balance. Panel operators who may add or remove credits only.",
                "summary": "Turn unlimited credits on or off",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUnlimitedRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUnlimitedRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUnlimitedRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Account"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/credits/accounts/{id}/adjust/": {
            "post": {
                "operationId": "credits_accounts_adjust_create",
                "description": "Add credits to a reseller's balance, or remove them with a negative amount; `reason` is shown in their history. Panel operators who may add or remove credits only.",
                "summary": "Add or remove credits",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreditAdjustmentRequest"
                            },
                            "examples": {
                                "AddCreditsAfterAPayment": {
                                    "value": {
                                        "amount": "100.00",
                                        "reason": "Bank transfer",
                                        "type": "payment",
                                        "reference": "INV-1042"
                                    },
                                    "summary": "Add credits after a payment"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CreditAdjustmentRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CreditAdjustmentRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditAdjusted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/credits/accounts/{id}/delete-quote/": {
            "get": {
                "operationId": "credits_accounts_delete_quote_retrieve",
                "description": "What deleting this reseller would do with their balance: returned to the reseller above them, or written off.",
                "summary": "Preview a reseller's credits on delete",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditDeleteQuote"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/accounts/{id}/give/": {
            "post": {
                "operationId": "credits_accounts_give_create",
                "description": "Move credits from your balance to a reseller below you, or take them back with a negative amount. Answers both history rows and both balances. Resellers who may give credits only.",
                "summary": "Give credits to a reseller",
                "parameters": [
                    {
                        "in": "header",
                        "name": "Idempotency-Key",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A fresh value (up to 100 characters) per action you may retry. Sent again with the same request, it answers what the first one did without doing it twice; with another request, 409. Kept 24 hours."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/GiveRequest"
                            },
                            "examples": {
                                "Give50Credits": {
                                    "value": {
                                        "amount": "50.00",
                                        "reason": "Monthly top-up"
                                    },
                                    "summary": "Give 50 credits"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/GiveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/GiveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditGiven"
                                },
                                "examples": {
                                    "Given": {
                                        "value": {
                                            "entries": [
                                                {
                                                    "id": 5121,
                                                    "created_at": "2026-11-13T10:24:05Z",
                                                    "account": {
                                                        "id": "6f1c2a8e-4d3b-4c8a-9e1f-2b7d5a0c3e91",
                                                        "username": "reseller1"
                                                    },
                                                    "account_name": "reseller1",
                                                    "amount": "-50.00",
                                                    "balance_after": "450.00",
                                                    "kind": "transfer_out",
                                                    "kind_label": "Given",
                                                    "type": "",
                                                    "type_label": "",
                                                    "description": "Given to alice",
                                                    "actor_name": "reseller1",
                                                    "by_me": true,
                                                    "counterparty_name": "alice",
                                                    "line": null,
                                                    "line_name": "",
                                                    "package_name": "",
                                                    "duration": "",
                                                    "expires_at": null,
                                                    "reason": "Monthly top-up",
                                                    "reference": ""
                                                },
                                                {
                                                    "id": 5122,
                                                    "created_at": "2026-11-13T10:24:05Z",
                                                    "account": {
                                                        "id": "3b7e9d24-1a6f-4e2b-8c5d-7f0a9e4b2c16",
                                                        "username": "alice"
                                                    },
                                                    "account_name": "alice",
                                                    "amount": "50.00",
                                                    "balance_after": "50.00",
                                                    "kind": "transfer_in",
                                                    "kind_label": "Given",
                                                    "type": "",
                                                    "type_label": "",
                                                    "description": "Given by reseller1",
                                                    "actor_name": "reseller1",
                                                    "by_me": true,
                                                    "counterparty_name": "reseller1",
                                                    "line": null,
                                                    "line_name": "",
                                                    "package_name": "",
                                                    "duration": "",
                                                    "expires_at": null,
                                                    "reason": "Monthly top-up",
                                                    "reference": ""
                                                }
                                            ],
                                            "balance": "50.00",
                                            "my_balance": "450.00"
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/credits/accounts/{id}/prices/": {
            "get": {
                "operationId": "credits_accounts_prices_list",
                "description": "Every package the reseller may sell, with their own price (if set) and what they pay for it.",
                "summary": "List a reseller's package prices",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/CreditPriceRow"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "credits_accounts_prices_update",
                "description": "Set or clear the reseller's own price for the packages listed; others are left as they are. A reseller sets prices only for the resellers below them, never under what they pay themselves. Needs the permission to manage reseller prices.",
                "summary": "Set a reseller's package prices",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/CreditPriceSetRequest"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/CreditPriceSetRequest"
                                }
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/CreditPriceSetRequest"
                                }
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/CreditPriceRow"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/credits/entries/": {
            "get": {
                "operationId": "credits_entries_list",
                "description": "Every change to the balances you can see, newest first, a page at a time: lines bought, extended and refunded, credits given, added and removed.",
                "summary": "List credit history",
                "parameters": [
                    {
                        "in": "query",
                        "name": "account",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this account's rows (a reseller you can see)."
                    },
                    {
                        "in": "query",
                        "name": "actor",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only what this account did."
                    },
                    {
                        "in": "query",
                        "name": "date_from",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (`2026-11-01`, the whole day) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "date_to",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (the whole day included) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Comma-separated kinds: `adjust`, `line_new`, `line_extend`, `line_trial`, `refund`, `transfer_out`, `transfer_in`, `returned`, `written_off`, `import`."
                    },
                    {
                        "in": "query",
                        "name": "line",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only rows about this line."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "subtree"
                            ]
                        },
                        "description": "`subtree`: your rows and those of every reseller below you. Default: yours only (everyone's for an account that sees all credits)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches names, the package, the reason and the reference."
                    },
                    {
                        "in": "query",
                        "name": "type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "correction",
                                "other",
                                "payment",
                                "promo",
                                "refund"
                            ]
                        },
                        "description": "Why an operator added or removed credits."
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedEntryList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/entries/export/": {
            "get": {
                "operationId": "credits_entries_export_retrieve",
                "description": "The rows the history list would show with the same filters, as a CSV file (one million rows at most).",
                "summary": "Export credit history as CSV",
                "parameters": [
                    {
                        "in": "query",
                        "name": "account",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this account's rows (a reseller you can see)."
                    },
                    {
                        "in": "query",
                        "name": "actor",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only what this account did."
                    },
                    {
                        "in": "query",
                        "name": "date_from",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (`2026-11-01`, the whole day) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "date_to",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (the whole day included) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Comma-separated kinds: `adjust`, `line_new`, `line_extend`, `line_trial`, `refund`, `transfer_out`, `transfer_in`, `returned`, `written_off`, `import`."
                    },
                    {
                        "in": "query",
                        "name": "line",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only rows about this line."
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "subtree"
                            ]
                        },
                        "description": "`subtree`: your rows and those of every reseller below you. Default: yours only (everyone's for an account that sees all credits)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches names, the package, the reason and the reference."
                    },
                    {
                        "in": "query",
                        "name": "type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "correction",
                                "other",
                                "payment",
                                "promo",
                                "refund"
                            ]
                        },
                        "description": "Why an operator added or removed credits."
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/me/": {
            "get": {
                "operationId": "credits_me_retrieve",
                "description": "Your balance and what you may do with credits: spending this month, what the resellers below you hold, your cheapest package price and your trial lines. Reseller-only figures are null for a panel operator.",
                "summary": "Get your credit balance",
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditBalance"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/quote/": {
            "get": {
                "operationId": "credits_quote_retrieve",
                "description": "What you would pay to put this package on a new line, or to extend `line` with it, and whether you may: `refused` says why not.",
                "summary": "Get the price of a package for a line",
                "parameters": [
                    {
                        "in": "query",
                        "name": "line",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The line to extend; leave out for a new line."
                    },
                    {
                        "in": "query",
                        "name": "package",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditQuote"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/credits/totals/": {
            "get": {
                "operationId": "credits_totals_retrieve",
                "description": "What the history rows the same filters select add up to, by kind, and what the accounts they cover hold now.",
                "summary": "Get credit history totals",
                "parameters": [
                    {
                        "in": "query",
                        "name": "account",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this account's rows (a reseller you can see)."
                    },
                    {
                        "in": "query",
                        "name": "actor",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only what this account did."
                    },
                    {
                        "in": "query",
                        "name": "date_from",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (`2026-11-01`, the whole day) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "date_to",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A date (the whole day included) or a date-time."
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Comma-separated kinds: `adjust`, `line_new`, `line_extend`, `line_trial`, `refund`, `transfer_out`, `transfer_in`, `returned`, `written_off`, `import`."
                    },
                    {
                        "in": "query",
                        "name": "line",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only rows about this line."
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "subtree"
                            ]
                        },
                        "description": "`subtree`: your rows and those of every reseller below you. Default: yours only (everyone's for an account that sees all credits)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches names, the package, the reason and the reference."
                    },
                    {
                        "in": "query",
                        "name": "type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "correction",
                                "other",
                                "payment",
                                "promo",
                                "refund"
                            ]
                        },
                        "description": "Why an operator added or removed credits."
                    }
                ],
                "tags": [
                    "Credits"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreditTotals"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/api/v1/jobs/{id}/": {
            "get": {
                "operationId": "editor_api_v1_jobs_retrieve",
                "description": "Its progress and log, and once it has ended, its result. Only tasks of the token's playlists.",
                "summary": "Get a background task",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/": {
            "get": {
                "operationId": "editor_api_v1_playlists_list",
                "description": "The playlists the token may use (at most 500), with their own login, how many channels, movies, TV shows and customers each has, and their version.",
                "summary": "List playlists",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorApiPlaylistList"
                                },
                                "examples": {
                                    "Playlists": {
                                        "value": {
                                            "results": [
                                                {
                                                    "id": "3f2b8c1e-5d4a-4e9b-9c7a-1b2c3d4e5f60",
                                                    "name": "Channel pack",
                                                    "username": "pack4m9",
                                                    "password": "x7c2v9b4",
                                                    "expiry": null,
                                                    "message": "",
                                                    "counts": {
                                                        "live": 1250,
                                                        "movie": 3400,
                                                        "series": 210,
                                                        "episodes": 9800,
                                                        "users": 12
                                                    },
                                                    "version": 318,
                                                    "last_synced_at": "2026-11-13T06:00:00Z",
                                                    "updated_at": "2026-11-13T06:02:11Z"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/": {
            "get": {
                "operationId": "editor_api_v1_playlists_retrieve",
                "summary": "Get a playlist",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorApiPlaylist"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/auto-backups/": {
            "get": {
                "operationId": "editor_api_v1_playlists_auto_backups_list",
                "description": "Private copies made twice a day when the playlist changed: kept a week, one a week kept a month. Latest first.",
                "summary": "List a playlist's automatic backups",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorAutoBackup"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/backup/": {
            "post": {
                "operationId": "editor_api_v1_playlists_backup_create",
                "description": "A backup file (`.mbk`) of the playlist, sent as it is written. `private` (the default) holds everything, customers and logins too, and restores only on this panel, over the playlist. `shareable` holds no customers and restores anywhere, as a new playlist. `sections` picks what it holds (default: all).",
                "summary": "Download a playlist backup",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/octet-stream": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/categories/{kind}/": {
            "get": {
                "operationId": "editor_api_v1_playlists_categories_retrieve",
                "description": "The categories of one kind, in order; the ones in the bin too (`deleted_at` set).",
                "summary": "List a playlist's categories",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorApiCategoryList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/streams/{kind}/": {
            "get": {
                "operationId": "editor_api_v1_playlists_streams_retrieve",
                "description": "A page of one kind, by id: up to `limit` entries (100 by default, at most 500) after the id `after`. Each row lists its values in the order of `columns`; pass `next` as `after` for the next page.",
                "summary": "List a playlist's channels, movies or TV shows",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "query",
                        "name": "after",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The last id of the previous page."
                    },
                    {
                        "in": "query",
                        "name": "deleted",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Entries in the bin too."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "limit",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Entries per page, at most 500."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorApiEntryPage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "patch": {
                "operationId": "editor_api_v1_playlists_streams_partial_update",
                "description": "Changes up to 5,000 entries of one kind in one edit you can undo: each item gives an entry `id` and the fields to change. Answers the changed rows.",
                "summary": "Update many entries at once",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorApiEntryBatchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorApiEntryBatchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorApiEntryBatchRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEditResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/updaters/": {
            "get": {
                "operationId": "editor_api_v1_playlists_updaters_list",
                "description": "Each one keeps the playlist in step with one of its providers, on a schedule.",
                "summary": "List a playlist's auto updaters",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorUpdater"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "post": {
                "operationId": "editor_api_v1_playlists_updaters_create",
                "description": "Keeps the playlist in step with one of its providers (`provider`), on the editor's schedule. `options` says per kind what a sync does (a kind left out is not synced); `mappings` ties the provider's categories to the playlist's. A playlist may have 20.",
                "summary": "Create an auto updater",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/updaters/{id}/": {
            "get": {
                "operationId": "editor_api_v1_playlists_updaters_retrieve",
                "summary": "Get an auto updater",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "patch": {
                "operationId": "editor_api_v1_playlists_updaters_partial_update",
                "description": "Send only what changes; `options` and `mappings` are replaced whole.",
                "summary": "Update an auto updater",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "delete": {
                "operationId": "editor_api_v1_playlists_updaters_destroy",
                "summary": "Delete an auto updater",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/updaters/{id}/run/": {
            "post": {
                "operationId": "editor_api_v1_playlists_updaters_run_create",
                "description": "Syncs now, in a background task: every kind it syncs, or only the `kinds` given. Refused while it is already running.",
                "summary": "Run an auto updater now",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/users/": {
            "get": {
                "operationId": "editor_api_v1_playlists_users_list",
                "description": "Everyone the playlist is handed to (up to 20,000), with their login, end date, categories and how many connections they have now.",
                "summary": "List a playlist's customers",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorCustomer"
                                    }
                                },
                                "examples": {
                                    "Customers": {
                                        "value": [
                                            [
                                                {
                                                    "id": 42,
                                                    "name": "Alice",
                                                    "username": "alice7k2",
                                                    "password": "q8w3e5r1",
                                                    "enabled": true,
                                                    "expiry": "2027-06-30T23:59:59Z",
                                                    "sync_expiry": false,
                                                    "max_connections": 2,
                                                    "message": "",
                                                    "notes": "",
                                                    "language": "",
                                                    "all_live": true,
                                                    "live_categories": [],
                                                    "all_movie": false,
                                                    "movie_categories": [
                                                        14,
                                                        15
                                                    ],
                                                    "all_series": true,
                                                    "series_categories": [],
                                                    "providers": [],
                                                    "copy_login": false,
                                                    "online": false,
                                                    "last_seen_at": null,
                                                    "connections": 0,
                                                    "synced_at": null,
                                                    "created_at": "2026-11-13T10:00:00Z"
                                                }
                                            ]
                                        ]
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "post": {
                "operationId": "editor_api_v1_playlists_users_create",
                "description": "Hands the playlist to someone with their own login and links. Every field may be left out: they get a random login, every category, and the provider's end date and connections (else a year and one connection). `providers` gives them their own provider lines: `[{\"provider\": id, \"username\", \"password\", \"dns\"}]`. Refused past the account's customer limit.",
                "summary": "Create a customer",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            },
                            "examples": {
                                "NewCustomer": {
                                    "value": {
                                        "name": "Alice",
                                        "expiry": "2027-06-30T23:59:59Z",
                                        "max_connections": 2,
                                        "all_movie": false,
                                        "movie_categories": [
                                            14,
                                            15
                                        ]
                                    },
                                    "summary": "New customer"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                },
                                "examples": {
                                    "CustomerMade": {
                                        "value": {
                                            "id": 42,
                                            "name": "Alice",
                                            "username": "alice7k2",
                                            "password": "q8w3e5r1",
                                            "enabled": true,
                                            "expiry": "2027-06-30T23:59:59Z",
                                            "sync_expiry": false,
                                            "max_connections": 2,
                                            "message": "",
                                            "notes": "",
                                            "language": "",
                                            "all_live": true,
                                            "live_categories": [],
                                            "all_movie": false,
                                            "movie_categories": [
                                                14,
                                                15
                                            ],
                                            "all_series": true,
                                            "series_categories": [],
                                            "providers": [],
                                            "copy_login": false,
                                            "online": false,
                                            "last_seen_at": null,
                                            "connections": 0,
                                            "synced_at": null,
                                            "created_at": "2026-11-13T10:00:00Z"
                                        },
                                        "summary": "Customer made"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/{pid}/users/{id}/": {
            "get": {
                "operationId": "editor_api_v1_playlists_users_retrieve",
                "summary": "Get a customer",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "patch": {
                "operationId": "editor_api_v1_playlists_users_partial_update",
                "description": "Send only what changes. A new username or password changes their links.",
                "summary": "Update a customer",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            },
            "delete": {
                "operationId": "editor_api_v1_playlists_users_destroy",
                "description": "Their login and links stop working.",
                "summary": "Delete a customer",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                }
            }
        },
        "/editor/api/v1/playlists/import/": {
            "post": {
                "operationId": "editor_api_v1_playlists_import_create",
                "description": "Makes a new playlist and fills it from a source in a background task: a provider login (`\"type\": \"xtream\"`), an M3U address or an uploaded M3U file. Answers the new playlist and its task. `kinds`: channels (`live`, the default), `movie` and `series`. `attributes`: what to take from the source besides names and links (default: category and logo). `categories`: per kind, the ids of the source's categories to take (from a read of its categories); the others come in already in the bin. A token limited to some playlists cannot make one.",
                "summary": "Import a new playlist",
                "parameters": [
                    {
                        "in": "header",
                        "name": "X-Token-Password",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The token's own password, when it was made with one."
                    }
                ],
                "tags": [
                    "Playlist editor API"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "editorToken": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                }
            }
        },
        "/editor/auto-backups/{id}/restore/": {
            "post": {
                "operationId": "editor_auto_backups_restore_create",
                "description": "Restores it over its playlist, in a background task: only the `sections` chosen (default: all). At most 5 a day per account.",
                "summary": "Restore an automatic backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/covers/search/": {
            "get": {
                "operationId": "editor_covers_search_list",
                "description": "Posters for a movie or TV show title, from TMDB.",
                "summary": "Search posters",
                "parameters": [
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`movie` or `series` (a TV show).",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "language",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A language code, e.g. `en` or `fr-FR`."
                    },
                    {
                        "in": "query",
                        "name": "n",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "How many: 6 by default, at most 24."
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The title.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorCover"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/epg/countries/": {
            "get": {
                "operationId": "editor_epg_countries_list",
                "description": "The countries Minimus EPG has a guide for, with how many channels each has, and `enabled` for the ones the panel imports.",
                "summary": "List the guide's countries",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorGuideCountry"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_epg_countries_create",
                "description": "Sets the countries the panel imports a guide for, by code, and answers the list as above. Panel operators only.",
                "summary": "Choose the guide's countries",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideCountriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideCountriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideCountriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorGuideCountry"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/epg/creator/": {
            "get": {
                "operationId": "editor_epg_creator_list",
                "description": "Guide channels made by hand, with how many programmes each has. Channels use one by its `tvg_id`.",
                "summary": "List your own guide channels",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorOwnGuideChannel"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_epg_creator_create",
                "description": "A guide channel you fill with programmes by hand. `tvg_id` is the guide id channels use (no spaces). An account may make 5,000.",
                "summary": "Create a guide channel",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOwnGuideChannelRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOwnGuideChannelRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOwnGuideChannelRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorOwnGuideChannel"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/epg/creator/{id}/": {
            "patch": {
                "operationId": "editor_epg_creator_partial_update",
                "summary": "Update a guide channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorOwnGuideChannelRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorOwnGuideChannelRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorOwnGuideChannelRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorOwnGuideChannel"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_epg_creator_destroy",
                "description": "With its programmes.",
                "summary": "Delete a guide channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/epg/creator/{id}/events/": {
            "get": {
                "operationId": "editor_epg_creator_events_list",
                "summary": "List a guide channel's programmes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorGuideEvent"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_epg_creator_events_create",
                "description": "From `start` to `stop` (at most a week), once or repeated (`repeat`). A guide channel may have 5,000.",
                "summary": "Add a programme to a guide channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideEventRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideEventRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorGuideEventRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGuideEvent"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/epg/creator/events/{id}/": {
            "patch": {
                "operationId": "editor_epg_creator_events_partial_update",
                "summary": "Update a guide programme",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideEventRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideEventRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideEventRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGuideEvent"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_epg_creator_events_destroy",
                "summary": "Delete a guide programme",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/epg/external/": {
            "get": {
                "operationId": "editor_epg_external_list",
                "description": "XMLTV guides added by their address, with their state and how many channels and programmes each holds.",
                "summary": "List outside guides",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorExternalGuide"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_epg_external_create",
                "description": "Adds an XMLTV guide by its address. It is checked first, in a background task: one that cannot be read is listed with the reason, one that passes is read in a minute or two. An account may add 10.",
                "summary": "Add an outside guide",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOutsideGuideRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOutsideGuideRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorOutsideGuideRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGuideCheckStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/epg/external/{id}/": {
            "patch": {
                "operationId": "editor_epg_external_partial_update",
                "summary": "Rename an outside guide",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideNameRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideNameRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorGuideNameRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorExternalGuide"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_epg_external_destroy",
                "description": "With the guide only it carried.",
                "summary": "Delete an outside guide",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/epg/external/{id}/refresh/": {
            "post": {
                "operationId": "editor_epg_external_refresh_create",
                "description": "Reads it again now (200). One that failed its check is checked again, in a background task (202).",
                "summary": "Read an outside guide again",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorExternalGuide"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGuideCheckStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/epg/programmes/": {
            "get": {
                "operationId": "editor_epg_programmes_list",
                "description": "One day of a guide channel's programmes, as players will get them.",
                "summary": "Preview a guide channel's programmes",
                "parameters": [
                    {
                        "in": "query",
                        "name": "date",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "description": "The day (default: today)."
                    },
                    {
                        "in": "query",
                        "name": "id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The guide id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "shift",
                        "schema": {
                            "type": "number",
                            "format": "double"
                        },
                        "description": "Hours to move it by, -24 to 24."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorProgramme"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/epg/sources/": {
            "get": {
                "operationId": "editor_epg_sources_list",
                "description": "The panel's guide sources this account may use, with how many channels have two days of guide or more, and `creator`: the account's own guide channels.",
                "summary": "List guide sources",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorGuideSource"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/epg/sources/{source}/channels/": {
            "get": {
                "operationId": "editor_epg_sources_channels_retrieve",
                "description": "A page of the channels a guide source has, best match first when searching: `q` looks in names, other names and guide ids. `count` is how many match in all.",
                "summary": "List a guide source's channels",
                "parameters": [
                    {
                        "in": "query",
                        "name": "limit",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Channels per page: 100 by default, at most 500."
                    },
                    {
                        "in": "query",
                        "name": "long",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Channels with two days or more (default true)."
                    },
                    {
                        "in": "query",
                        "name": "offset",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Channels to skip."
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Search text."
                    },
                    {
                        "in": "query",
                        "name": "short",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Channels with less than two days of guide (default true)."
                    },
                    {
                        "in": "path",
                        "name": "source",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A guide source's id, or `creator` for your own channels.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGuideChannelPage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/jobs/": {
            "get": {
                "operationId": "editor_jobs_list",
                "description": "The last 50, latest first, without their results and logs: your own, or everyone's for panel operators.",
                "summary": "List the playlist editor's background tasks",
                "parameters": [
                    {
                        "in": "query",
                        "name": "playlist",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this playlist's."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorTask"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/jobs/{id}/": {
            "get": {
                "operationId": "editor_jobs_retrieve",
                "description": "Its progress and log, and once it has ended, its result.",
                "summary": "Get a background task",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/jobs/{id}/cancel/": {
            "post": {
                "operationId": "editor_jobs_cancel_create",
                "description": "Refused when it has already ended.",
                "summary": "Cancel a background task",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/logins/check/": {
            "get": {
                "operationId": "editor_logins_check_retrieve",
                "description": "Whether `username` can be used as a playlist login, with a sentence to show.",
                "summary": "Check that a username is free",
                "parameters": [
                    {
                        "in": "query",
                        "name": "playlist",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "When renaming a playlist's login: that playlist's id (it may keep its own username)."
                    },
                    {
                        "in": "query",
                        "name": "username",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The username to check.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorLoginCheck"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/logins/random/": {
            "get": {
                "operationId": "editor_logins_random_retrieve",
                "description": "A free username and a random password, for a new login.",
                "summary": "Suggest a username and password",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorLogin"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/logos/search/": {
            "get": {
                "operationId": "editor_logos_search_list",
                "description": "Logos for a name, from the guide or Wikimedia (`engine`), then from the other to fill up.",
                "summary": "Search logos",
                "parameters": [
                    {
                        "in": "query",
                        "name": "engine",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "guide",
                                "wikimedia"
                            ]
                        },
                        "description": "Default `guide`."
                    },
                    {
                        "in": "query",
                        "name": "n",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "How many: 6 by default, at most 24."
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The name."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorLogo"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/": {
            "get": {
                "operationId": "editor_playlists_list",
                "description": "Your playlists in your order, and how many playlists and customers your account may have. Panel operators see every account's playlists and have no limits.",
                "summary": "List playlists",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistList"
                                },
                                "examples": {
                                    "Playlists": {
                                        "value": {
                                            "quotas": {
                                                "playlists": {
                                                    "used": 2,
                                                    "max": 20
                                                },
                                                "users": {
                                                    "used": 14,
                                                    "max": 200
                                                },
                                                "entries": 300000,
                                                "episodes": 1000000
                                            },
                                            "results": [
                                                {
                                                    "id": "3f6c1a2e-8b4d-4c1e-9a77-2d5e0b9c4f10",
                                                    "name": "Family",
                                                    "position": 1,
                                                    "owner": "alice",
                                                    "username": "k7Qm2xPa",
                                                    "password": "Zr4tW9bLqe",
                                                    "expiry": null,
                                                    "message": "",
                                                    "counts": {
                                                        "live": 1250,
                                                        "movie": 4200,
                                                        "series": 380,
                                                        "episodes": 15600,
                                                        "users": 12
                                                    },
                                                    "providers": [
                                                        {
                                                            "id": 7,
                                                            "type": "xtream",
                                                            "url": "http://provider.example.com:8080",
                                                            "label": "Main provider",
                                                            "source": ""
                                                        }
                                                    ],
                                                    "last_synced_at": "2026-11-13T06:00:12Z",
                                                    "updated_at": "2026-11-13T09:41:03Z",
                                                    "version": 318,
                                                    "custom_domain": ""
                                                },
                                                {
                                                    "id": "9b2d4e61-0c7a-4f3b-8e15-6a1f2c3d4e5f",
                                                    "name": "Sports",
                                                    "position": 2,
                                                    "owner": "alice",
                                                    "username": "p3Ns8vRc",
                                                    "password": "Hy6mQ2xTfa",
                                                    "expiry": null,
                                                    "message": "",
                                                    "counts": {
                                                        "live": 320,
                                                        "movie": 0,
                                                        "series": 0,
                                                        "episodes": 0,
                                                        "users": 2
                                                    },
                                                    "providers": [],
                                                    "last_synced_at": null,
                                                    "updated_at": "2026-11-13T09:41:03Z",
                                                    "version": 41,
                                                    "custom_domain": ""
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_playlists_create",
                "description": "A new, empty playlist with a login of its own, at the end of your list (named \"Playlist #n\" without a `name`). Refused (403) when your account already has as many playlists as it may.",
                "summary": "Create a playlist",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistCreateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/": {
            "get": {
                "operationId": "editor_playlists_retrieve",
                "description": "One playlist, with every setting.",
                "summary": "Get a playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                },
                                "examples": {
                                    "APlaylist": {
                                        "value": {
                                            "id": "3f6c1a2e-8b4d-4c1e-9a77-2d5e0b9c4f10",
                                            "name": "Family",
                                            "position": 1,
                                            "owner": "alice",
                                            "username": "k7Qm2xPa",
                                            "password": "Zr4tW9bLqe",
                                            "expiry": null,
                                            "message": "",
                                            "counts": {
                                                "live": 1250,
                                                "movie": 4200,
                                                "series": 380,
                                                "episodes": 15600,
                                                "users": 12
                                            },
                                            "providers": [
                                                {
                                                    "id": 7,
                                                    "type": "xtream",
                                                    "url": "http://provider.example.com:8080",
                                                    "label": "Main provider",
                                                    "source": ""
                                                }
                                            ],
                                            "last_synced_at": "2026-11-13T06:00:12Z",
                                            "updated_at": "2026-11-13T09:41:03Z",
                                            "version": 318,
                                            "custom_domain": "",
                                            "settings": {
                                                "max_connections": 1,
                                                "track_connections": true,
                                                "limit_connections": true,
                                                "time_shift": 0.0,
                                                "language": "en",
                                                "provider_vod_info": false,
                                                "auto_vod_info": true,
                                                "vod_info_options": {},
                                                "epg_gzip": false,
                                                "use_tvg_id": true,
                                                "epg_dummy_text": "",
                                                "epg_days": 4,
                                                "epg_fields": {
                                                    "sub_title": true,
                                                    "description": true,
                                                    "episode": true,
                                                    "categories": true,
                                                    "icon": true,
                                                    "credits": false,
                                                    "date": false,
                                                    "rating": false,
                                                    "live": true,
                                                    "new": true,
                                                    "plain_live_new": false,
                                                    "sub_title_in_title": false,
                                                    "episode_in_description": false,
                                                    "credits_in_description": false,
                                                    "categories_in_description": false,
                                                    "date_in_description": false
                                                },
                                                "epg_precision": 70,
                                                "epg_override": false,
                                                "epg_hide_short": false,
                                                "epg_show_ids": false,
                                                "logo_precision": 70,
                                                "logo_override": false,
                                                "hidden_provider": true,
                                                "custom_domain": "",
                                                "welcome": {},
                                                "app_color": "#2563eb",
                                                "app_logo": "",
                                                "stream_format": "ts"
                                            }
                                        },
                                        "summary": "A playlist"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_playlists_partial_update",
                "description": "Changes its name, the expiry date and message players are told, or any of its settings: only the fields sent change. Answers the playlist as `GET` does.",
                "summary": "Update a playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPlaylistUpdateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPlaylistUpdateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPlaylistUpdateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_playlists_destroy",
                "description": "Deletes the playlist for good, with its content, its history and the customers it is handed to.",
                "summary": "Delete a playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/add-source/": {
            "post": {
                "operationId": "editor_playlists_add_source_create",
                "description": "Adds what another source has to the playlist, in a background task. A link already in the playlist is not added again, and a category with the same name is reused. `kinds`: channels (`live`, the default), `movie` and `series`. `attributes`: what to take from the source besides names and links (default: category and logo). `categories`: per kind, the ids of the source's categories to take (from a read of its categories); the others come in already in the bin.",
                "summary": "Add content from another source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAddSourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAddSourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAddSourceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/auto-backups/": {
            "get": {
                "operationId": "editor_playlists_auto_backups_list",
                "description": "Private copies made twice a day when the playlist changed: kept a week, one a week kept a month. Latest first.",
                "summary": "List a playlist's automatic backups",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorAutoBackup"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/auto-backups/{id}/restore/": {
            "post": {
                "operationId": "editor_playlists_auto_backups_restore_create",
                "description": "Restores it over its playlist, in a background task: only the `sections` chosen (default: all). At most 5 a day per account.",
                "summary": "Restore an automatic backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorAutoRestoreRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/backup/": {
            "post": {
                "operationId": "editor_playlists_backup_create",
                "description": "A backup file (`.mbk`) of the playlist, sent as it is written. `private` (the default) holds everything, customers and logins too, and restores only on this panel, over the playlist. `shareable` holds no customers and restores anywhere, as a new playlist. `sections` picks what it holds (default: all).",
                "summary": "Download a playlist backup",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorBackupRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/octet-stream": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/": {
            "get": {
                "operationId": "editor_playlists_categories_list",
                "description": "The categories of one of the playlist's lists, in order, each with how many rows it shows, without the rows themselves.",
                "summary": "List categories",
                "parameters": [
                    {
                        "in": "query",
                        "name": "deleted",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "description": "`true` to include what is in the recycle bin."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorCategory"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/clone/": {
            "post": {
                "operationId": "editor_playlists_categories_clone_create",
                "description": "Copies the channels of category `id` into another category (`into`), or into a new one (`name`, by default \"<name> (copy)\").",
                "summary": "Copy a category of channels",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCloneRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCloneRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCloneRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/create/": {
            "post": {
                "operationId": "editor_playlists_categories_create_create",
                "description": "A new, empty category at the bottom of the list. Names may repeat.",
                "summary": "Create a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/delete/": {
            "post": {
                "operationId": "editor_playlists_categories_delete_create",
                "description": "Sends categories to the recycle bin with their rows; restoring a category brings its rows back as they were.",
                "summary": "Delete categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/empty/": {
            "post": {
                "operationId": "editor_playlists_categories_empty_create",
                "description": "Sends every row of the categories to the recycle bin; the categories stay.",
                "summary": "Empty categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/merge/": {
            "post": {
                "operationId": "editor_playlists_categories_merge_create",
                "description": "Moves every row of the categories of `ids` to the bottom of the category `into`, in order; the emptied categories go to the recycle bin. One change: undoing it brings them all back.",
                "summary": "Merge categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryMergeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryMergeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryMergeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/purge/": {
            "post": {
                "operationId": "editor_playlists_categories_purge_create",
                "description": "Removes categories that are in the recycle bin for good, with their rows (any other category refuses the request). This cannot be undone.",
                "summary": "Remove categories for good",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPurgeResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/reorder/": {
            "post": {
                "operationId": "editor_playlists_categories_reorder_create",
                "description": "The categories of `ids` keep their order and land just before or after another category (`before`, `after`), or at the bottom without either.",
                "summary": "Drag categories to a new place",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryReorderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryReorderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryReorderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/restore/": {
            "post": {
                "operationId": "editor_playlists_categories_restore_create",
                "description": "Brings categories out of the recycle bin, with their rows.",
                "summary": "Restore categories from the recycle bin",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategoryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/save/": {
            "post": {
                "operationId": "editor_playlists_categories_save_create",
                "description": "Renames categories or changes whether they are hidden (`hidden`) or take the provider's name at each sync (`sync_name`, set on each of their rows too). Only the fields sent change.",
                "summary": "Edit categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySaveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySaveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySaveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/categories/{kind}/sort/": {
            "post": {
                "operationId": "editor_playlists_categories_sort_create",
                "description": "A-Z, or Z-A with `desc: true`; categories without a name go last.",
                "summary": "Sort categories by name",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySortRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySortRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCategorySortRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/domain/check/": {
            "post": {
                "operationId": "editor_playlists_domain_check_create",
                "description": "Whether the playlist's own domain reaches this panel yet, and what was found, in a sentence.",
                "summary": "Check a playlist's own domain",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorDomainCheck"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/duplicate/": {
            "post": {
                "operationId": "editor_playlists_duplicate_create",
                "description": "A new playlist with the same settings and content, but new links and a new login. The content is copied in the background: the answer gives the new playlist and the background task (`job`) copying it.",
                "summary": "Duplicate a playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistCopy"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{entry_id}/": {
            "get": {
                "operationId": "editor_playlists_entries_retrieve",
                "description": "Everything about one row of the playlist, its full `info` included.",
                "summary": "Get a channel, movie or TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "entry_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The row's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEntry"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/change-type/": {
            "post": {
                "operationId": "editor_playlists_entries_change_type_create",
                "description": "Copies channels into movies or movies into channels (`to`, into `category` or a `new_category`), or into episodes of a TV show (`to: \"series\"`, with `series` or a `new_series`, from `season` and `episode`). Without `keep` the originals go to the recycle bin; rows already there (same name or address) are skipped, and `message` says what was done.",
                "summary": "Turn rows into another kind",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels) or `movie` (movies).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorChangeTypeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorChangeTypeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorChangeTypeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCopyResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/copy-edits/": {
            "post": {
                "operationId": "editor_playlists_entries_copy_edits_create",
                "description": "Copies values (`values`: guide ids, guide shifts, numbers, logos, addresses, names) from the rows of `scope` onto the matching rows of another playlist, matched by `match_by` (name, address, stream id or TMDB id). Handy after rebuilding a playlist from a fresh source.",
                "summary": "Copy edits to another playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCopyEditsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCopyEditsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCopyEditsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCopyEditsResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/create/": {
            "post": {
                "operationId": "editor_playlists_entries_create_create",
                "description": "A new row at the bottom of `category`, or at its top with `top: true`. A playlist holds each movie once (by name or address) and each TV show once (by name).",
                "summary": "Add a channel, movie or TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/delete/": {
            "post": {
                "operationId": "editor_playlists_entries_delete_create",
                "description": "Sends channels, movies or TV shows (`ids`) to the recycle bin, from where they can be restored.",
                "summary": "Delete rows",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/duplicates/": {
            "get": {
                "operationId": "editor_playlists_entries_duplicates_retrieve",
                "description": "Groups of rows that share the same `by` value, each group in grid order. Rows in the recycle bin are left out; stream ids are compared per provider.",
                "summary": "Find duplicate rows",
                "parameters": [
                    {
                        "in": "query",
                        "name": "by",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "epg_id",
                                "name",
                                "stream_id",
                                "url"
                            ],
                            "default": "url"
                        },
                        "description": "What to compare: the address, the name, the stream id at the end of the address, or the guide id."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorDuplicates"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/empty-bin/": {
            "post": {
                "operationId": "editor_playlists_entries_empty_bin_create",
                "description": "Removes everything in the recycle bin of this list for good, deleted categories included. This cannot be undone.",
                "summary": "Empty the recycle bin",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPurgeResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/move/": {
            "post": {
                "operationId": "editor_playlists_entries_move_create",
                "description": "Moves rows to the top or bottom (`place`) of `category`, or of their own category without one; a row in the recycle bin comes out of it. With `copy: true` channels are duplicated instead (movies and TV shows cannot be).",
                "summary": "Move rows to a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryMoveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryMoveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryMoveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/purge/": {
            "post": {
                "operationId": "editor_playlists_entries_purge_create",
                "description": "Removes rows that are in the recycle bin for good (any other row refuses the request). This cannot be undone.",
                "summary": "Remove rows for good",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPurgeResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/reorder/": {
            "post": {
                "operationId": "editor_playlists_entries_reorder_create",
                "description": "The rows keep their order and land just before or after a row (`before`, `after`) of `category`, or at its bottom without either.",
                "summary": "Drag rows to a new place",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryReorderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryReorderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryReorderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/restore/": {
            "post": {
                "operationId": "editor_playlists_entries_restore_create",
                "description": "Puts rows back where they were, or into `category`. Rows of a deleted category need a `category`, unless the category itself is restored.",
                "summary": "Restore rows from the recycle bin",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryRestoreRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryRestoreRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntryRestoreRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/save/": {
            "post": {
                "operationId": "editor_playlists_entries_save_create",
                "description": "Send `items` to give each row its own values, or `ids` with `set` to give many rows the same values; only the fields sent change. One change in the history, answered with the rows it changed.",
                "summary": "Edit channels, movies or TV shows",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySaveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySaveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySaveRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/sort/": {
            "post": {
                "operationId": "editor_playlists_entries_sort_create",
                "description": "Sorts the categories by name (`target: \"categories\"`), or by `by` the rows of every category (`all`), of one `category` or of a selection (`ids`, which keep the places they hold). `desc` sorts Z-A; empty values go last. `by: \"provider\"` puts the rows of `provider` first.",
                "summary": "Sort rows or categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySortRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySortRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEntrySortRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/{kind}/to-playlist/": {
            "post": {
                "operationId": "editor_playlists_entries_to_playlist_create",
                "description": "Copies rows into `category` (or a `new_category`) of another of your playlists (`playlist`), TV shows with their episodes; with `keep: false` the originals go to the recycle bin. Rows the other playlist already has are skipped, and a TV show it already has gets the new episodes.",
                "summary": "Copy rows to another playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToPlaylistRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToPlaylistRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToPlaylistRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorToPlaylistResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/live/numbers/": {
            "post": {
                "operationId": "editor_playlists_entries_live_numbers_create",
                "description": "Numbers channels in playlist order from `start`: every channel, or those of one `category` (with `continue: true`, the categories after it too, counting on).",
                "summary": "Number channels",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNumbersRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNumbersRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNumbersRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/live/numbers/reset/": {
            "post": {
                "operationId": "editor_playlists_entries_live_numbers_reset_create",
                "description": "Sets every channel's number back to none (-1).",
                "summary": "Remove channel numbers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorWriteResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/entries/series/purge-empty/": {
            "post": {
                "operationId": "editor_playlists_entries_series_purge_empty_create",
                "description": "Removes for good every TV show that has no episode. TV shows from a provider login (server, username and password) are kept: their episodes are only fetched when someone opens them.",
                "summary": "Remove TV shows without episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPurgeResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/epg/match/": {
            "post": {
                "operationId": "editor_playlists_epg_match_create",
                "description": "Gives the channels `scope` picks (`{\"ids\": [...]}`, `{\"categories\": [...]}` (category ids) or `{\"all\": true}`) a guide id found by their name. `source` limits it to one guide source, `precision` (40 to 100) is how close a name must be, and `override` also replaces the ids channels have. Up to 2,000 channels are matched at once (200); more in a background task (202).",
                "summary": "Match channels to the guide",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEditResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/epg/name-event/": {
            "post": {
                "operationId": "editor_playlists_epg_name_event_create",
                "description": "The channels `ids` show their own name as the programme, all day; with `on: false` they stop.",
                "summary": "Show channel names as their guide",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNameAsGuideRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNameAsGuideRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNameAsGuideRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEditResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/epg/remove-dead/": {
            "post": {
                "operationId": "editor_playlists_epg_remove_dead_create",
                "description": "Clears the guide ids nothing fills any more: gone from the guide, or with no programme left. Your own guide channels and channel names shown as the guide stay.",
                "summary": "Remove guide ids with no guide left",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEditResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/episodes/fetch/": {
            "post": {
                "operationId": "editor_playlists_episodes_fetch_create",
                "description": "Reads from the provider, in a background task, the episodes of TV shows that have none yet: every one, or the ones `scope` picks (`{\"ids\": [...]}`, `{\"categories\": [...]}` (category ids) or `{\"all\": true}`).",
                "summary": "Read TV shows' episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorFetchEpisodesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorFetchEpisodesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorFetchEpisodesRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/export-xc/": {
            "post": {
                "operationId": "editor_playlists_export_xc_create",
                "description": "Writes the playlist's names, logos, guide ids and numbers (`fields`) back into the panel a provider login (`type: \"xtream\"`, by `provider`) comes from: SQL statements to paste (`mode: \"sql\"`) or a Python script to run on its server (`mode: \"python\"`, with its database in `db`). Existing streams are updated, never added.",
                "summary": "Export edits back to the source panel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourcePanelExportRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourcePanelExportRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourcePanelExportRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorSourcePanelExport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/grid/{kind}/": {
            "get": {
                "operationId": "editor_playlists_grid_retrieve",
                "description": "Every row of one of the playlist's lists, with its categories, in order. To stay small with hundreds of thousands of rows, each row is an array of values in the order `columns` names them. Compressed with gzip when the request accepts it.",
                "summary": "List channels, movies or TV shows",
                "parameters": [
                    {
                        "in": "query",
                        "name": "deleted",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "description": "`true` to include what is in the recycle bin."
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorGrid"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/history/": {
            "get": {
                "operationId": "editor_playlists_history_list",
                "description": "The playlist's history, latest change first, and whether there is a change to undo or to redo.",
                "summary": "List a playlist's changes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorHistory"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/history/{change_id}/": {
            "get": {
                "operationId": "editor_playlists_history_retrieve",
                "description": "One change and what it did, row by row: each row's fields before (`b`) and after (`a`) it. Lists 2,000 rows at most; `more` counts the others.",
                "summary": "Get a change",
                "parameters": [
                    {
                        "in": "path",
                        "name": "change_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The change's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorChangeDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/history/{change_id}/revert/": {
            "post": {
                "operationId": "editor_playlists_history_revert_create",
                "description": "Puts back what that change replaced, as a new change in the history.",
                "summary": "Revert a change",
                "parameters": [
                    {
                        "in": "path",
                        "name": "change_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The change's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUndoResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorDetail"
                                }
                            }
                        },
                        "description": "It can no longer be put back: rows it touched were removed for good since. The change is marked as no longer undoable."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/history/redo/": {
            "post": {
                "operationId": "editor_playlists_history_redo_create",
                "description": "Redoes the change undone last.",
                "summary": "Redo the last undone change",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUndoResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorDetail"
                                }
                            }
                        },
                        "description": "It can no longer be put back: rows it touched were removed for good since. The change is marked as no longer undoable."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/history/undo/": {
            "post": {
                "operationId": "editor_playlists_history_undo_create",
                "description": "Undoes the playlist's latest change that can still be undone.",
                "summary": "Undo the last change",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUndoResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorDetail"
                                }
                            }
                        },
                        "description": "It can no longer be put back: rows it touched were removed for good since. The change is marked as no longer undoable."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/info/match/": {
            "post": {
                "operationId": "editor_playlists_info_match_create",
                "description": "Finds the movies or TV shows (`kind`) `scope` picks (`{\"ids\": [...]}`, `{\"categories\": [...]}` (category ids) or `{\"all\": true}`) on TMDB by name and fills in their details, poster, rating and TMDB id, in a background task. `override` says which of `name`, `logo`, `rating` and `tmdb` may replace what they have (by default all but the name).",
                "summary": "Fill in movie or TV show details",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorInfoMatchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorInfoMatchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorInfoMatchRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/login/": {
            "post": {
                "operationId": "editor_playlists_login_create",
                "description": "The username and password players sign in with to this playlist. The username must not be used by another playlist, customer or line. Answers the playlist.",
                "summary": "Set a playlist's login",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistLoginRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistLoginRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistLoginRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/logos/match/": {
            "post": {
                "operationId": "editor_playlists_logos_match_create",
                "description": "Gives the channels `scope` picks (`{\"ids\": [...]}`, `{\"categories\": [...]}` (category ids) or `{\"all\": true}`) a logo found by their name. `precision` (40 to 100) is how close a name must be, and `override` also replaces the logos channels have. Up to 2,000 channels are matched at once (200); more in a background task (202).",
                "summary": "Match channel logos",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorMatchRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEditResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/manual-updater/{kind}/import/": {
            "post": {
                "operationId": "editor_playlists_manual_updater_import_create",
                "description": "Adds entries listed by a finished read of a source (`job`): the ones whose `keys` are given, or every new one with `all`. They go to `category` when given, else to the category named as the source's (made when missing). One edit you can undo.",
                "summary": "Add picked entries from a source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPickedEntriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPickedEntriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPickedEntriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPickedImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/manual-updater/{kind}/scan/": {
            "post": {
                "operationId": "editor_playlists_manual_updater_scan_create",
                "description": "Reads the channels, movies or TV shows (by `kind`) a source lists, in a background task. The finished task lists them by category, each marked `exists` when the playlist has it already; add the ones you pick with `POST …/manual-updater/{kind}/import/`.",
                "summary": "Read a source's list to pick from",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceReadRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceReadRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceReadRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/migrate/{job}/candidates/": {
            "get": {
                "operationId": "editor_playlists_migrate_candidates_list",
                "description": "The new provider's channels or movies whose name has `q`, the same name first, to pair one by hand.",
                "summary": "Search the new provider's entries",
                "parameters": [
                    {
                        "in": "path",
                        "name": "job",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The comparison: the task `POST …/migrate/analyze/` started.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie"
                            ]
                        },
                        "description": "Default `live`."
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Text in the name."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorCandidate"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/migrate/{job}/pairs/": {
            "get": {
                "operationId": "editor_playlists_migrate_pairs_retrieve",
                "description": "A page of a comparison's pairs: each entry of the playlist with the new provider's entry it would take.",
                "summary": "List the pairs of a provider comparison",
                "parameters": [
                    {
                        "in": "query",
                        "name": "band",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "none",
                                "sure",
                                "unsure"
                            ]
                        },
                        "description": "Which pairs: all (default), sure, unsure, or entries with none."
                    },
                    {
                        "in": "path",
                        "name": "job",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The comparison: the task `POST …/migrate/analyze/` started.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "limit",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "500 by default, at most 2,000."
                    },
                    {
                        "in": "query",
                        "name": "offset",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Text in the entry's name."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPairPage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/migrate/analyze/": {
            "post": {
                "operationId": "editor_playlists_migrate_analyze_create",
                "description": "Pairs the playlist's channels and movies with a new source's, in a background task, before moving the playlist to it. Read the pairs with `GET …/migrate/{job}/pairs/`, then move with `POST …/migrate/apply/`.",
                "summary": "Compare a playlist with a new provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewProviderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewProviderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewProviderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/migrate/apply/": {
            "post": {
                "operationId": "editor_playlists_migrate_apply_create",
                "description": "Moves the playlist to the provider a comparison (`job`) read, in a background task: each entry takes its pair's link, or the one `choices` gives (entry id → the new provider's key, `\"\"` for none). Entries without one are deleted, hidden or kept (`missing`), and the old providers replaced, merged or kept (`providers`). When they are replaced, `users` drops customers' own lines on them, so customers follow the playlist.",
                "summary": "Move a playlist to a new provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderMoveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderMoveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderMoveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/outputs/": {
            "get": {
                "operationId": "editor_playlists_outputs_retrieve",
                "description": "Every way to open the playlist: its M3U and guide links, the login players sign in with, and the same as text to send. With `user`, a customer's own links.",
                "summary": "Get a playlist's links",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "user",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A customer's id: their links instead."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorLinks"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/providers/": {
            "get": {
                "operationId": "editor_playlists_providers_list",
                "description": "Where the playlist's channels, movies and TV shows come from, with how many entries each one gave. Passwords are never shown.",
                "summary": "List a playlist's providers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorProvider"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_playlists_providers_create",
                "description": "`url` is the address its streams start with; `param1` and `param2` are its login (username and password, key, MAC address…, by `type`). An M3U address provider may also have `source_url`, the address of its list.",
                "summary": "Add a provider to a playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorProviderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProvider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/providers/{id}/": {
            "patch": {
                "operationId": "editor_playlists_providers_partial_update",
                "description": "A new label is saved at once (200). A new address or login also rewrites every link that comes from the provider, in a background task (202).",
                "summary": "Update a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProvider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_playlists_providers_destroy",
                "description": "Forgets the provider. What came from it stays in the playlist, unless `streams=1`: then it is deleted for good too. Answers how many entries went.",
                "summary": "Delete a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "streams",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Also delete for good every entry that came from it."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProviderRemoved"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/reset-content/": {
            "post": {
                "operationId": "editor_playlists_reset_content_create",
                "description": "Removes every channel (`live`), movie (`movie`) or TV show (`series`) of the playlist for good, with their categories and episodes. This cannot be undone and clears the history. Answers the playlist.",
                "summary": "Remove a playlist's content",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetContentRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetContentRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetContentRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/reset-links/": {
            "post": {
                "operationId": "editor_playlists_reset_links_create",
                "description": "New playlist and guide links (`m3u`, `epg`) and/or a new username and password (`login`); the old ones stop working at once, for links that leaked. Answers the playlist.",
                "summary": "Renew a playlist's links or login",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetLinksRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetLinksRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorResetLinksRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/": {
            "get": {
                "operationId": "editor_playlists_series_episodes_retrieve",
                "description": "The TV show and its episodes by season and number, those in the recycle bin included (`deleted_at` set). Episodes from a provider login (server, username and password) are fetched from the provider the first time; `error` says why when it did not send them.",
                "summary": "List a TV show's episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodeList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/create/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_create_create",
                "description": "A new episode of the TV show. Without a `number` it takes the next free one of its season.",
                "summary": "Add an episode",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeCreateRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/delete/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_delete_create",
                "description": "Sends episodes of the TV show to the recycle bin.",
                "summary": "Delete episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/move/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_move_create",
                "description": "Moves episodes into the TV show `series`. One whose season and number that TV show already has is skipped, or with `collisions: \"renumber\"` takes the next free number of its season.",
                "summary": "Move episodes to another TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeMoveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeMoveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeMoveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodeMoveResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/purge/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_purge_create",
                "description": "Removes episodes that are in the recycle bin for good (any other episode refuses the request). This cannot be undone.",
                "summary": "Remove episodes for good",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/restore/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_restore_create",
                "description": "Brings episodes of the TV show out of the recycle bin. Refused when another episode has taken their season and number, or their address, since.",
                "summary": "Restore episodes from the recycle bin",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeIdsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/save/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_save_create",
                "description": "Changes episodes' season, number, name or address (`items`); only the fields sent change. A TV show holds one episode per season and number, and a playlist each episode address once.",
                "summary": "Edit episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeSaveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeSaveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodeSaveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/series/{series_id}/episodes/to-channels/": {
            "post": {
                "operationId": "editor_playlists_series_episodes_to_channels_create",
                "description": "Copies episodes into a category of channels or movies (`kind`, `category`); with `keep: false` the episodes go to the recycle bin. Episodes whose name or address that list already has are skipped.",
                "summary": "Turn episodes into channels or movies",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "series_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The TV show's id (a row of the `series` list).",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodesToChannelsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodesToChannelsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorEpisodesToChannelsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorEpisodesToChannelsResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/tools/{kind}/{tool}/": {
            "post": {
                "operationId": "editor_playlists_tools_create",
                "description": "Runs a tool on the rows of `scope` as one change, or with `preview: true` only lists what would change (the first 500 differences). `target: \"categories\"` works on category names instead (`optimize`, `replace`, `affix` and `case` only). Each tool takes its own `options`: `optimize` tidies names, `replace` searches and replaces in names, addresses or logos, `dedupe` sends duplicate channels to the recycle bin, `affix` adds or removes a prefix or suffix, `case` changes the case, `url` replaces text in addresses or logos, `format` rewrites the channel addresses of a provider login in another stream format, and `preset` runs a saved preset (or `steps`).",
                "summary": "Run a bulk tool",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Which list of the playlist: `live` (channels), `movie` (movies) or `series` (TV shows).",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "tool",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "affix",
                                "case",
                                "dedupe",
                                "format",
                                "optimize",
                                "preset",
                                "replace",
                                "url"
                            ]
                        },
                        "description": "The tool to run.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToolRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToolRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorToolRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorToolOutcome"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/updaters/": {
            "get": {
                "operationId": "editor_playlists_updaters_list",
                "description": "Each one keeps the playlist in step with one of its providers, on a schedule.",
                "summary": "List a playlist's auto updaters",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorUpdater"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_playlists_updaters_create",
                "description": "Keeps the playlist in step with one of its providers (`provider`), on the editor's schedule. `options` says per kind what a sync does (a kind left out is not synced); `mappings` ties the provider's categories to the playlist's. A playlist may have 20.",
                "summary": "Create an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUpdaterRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/updaters/{id}/": {
            "get": {
                "operationId": "editor_playlists_updaters_retrieve",
                "summary": "Get an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_playlists_updaters_partial_update",
                "description": "Send only what changes; `options` and `mappings` are replaced whole.",
                "summary": "Update an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_playlists_updaters_destroy",
                "summary": "Delete an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/updaters/{id}/categories/": {
            "get": {
                "operationId": "editor_playlists_updaters_categories_retrieve",
                "description": "The categories the updater's provider lists, to map them to the playlist's. At once when they were read in the last hour (200); otherwise a background task reads them (202), and its result holds them.",
                "summary": "List the provider's categories of an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProviderCategories"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/updaters/{id}/run/": {
            "post": {
                "operationId": "editor_playlists_updaters_run_create",
                "description": "Syncs now, in a background task: every kind it syncs, or only the `kinds` given. Refused while it is already running.",
                "summary": "Run an auto updater now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/updaters/{id}/runs/": {
            "get": {
                "operationId": "editor_playlists_updaters_runs_list",
                "description": "Its last 50 runs, latest first, with what each one added, renamed and removed, and its log.",
                "summary": "List an auto updater's runs",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorUpdaterRun"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/users/": {
            "get": {
                "operationId": "editor_playlists_users_list",
                "description": "Everyone the playlist is handed to (up to 20,000), with their login, end date, categories and how many connections they have now.",
                "summary": "List a playlist's customers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorCustomer"
                                    }
                                },
                                "examples": {
                                    "Customers": {
                                        "value": [
                                            [
                                                {
                                                    "id": 42,
                                                    "name": "Alice",
                                                    "username": "alice7k2",
                                                    "password": "q8w3e5r1",
                                                    "enabled": true,
                                                    "expiry": "2027-06-30T23:59:59Z",
                                                    "sync_expiry": false,
                                                    "max_connections": 2,
                                                    "message": "",
                                                    "notes": "",
                                                    "language": "",
                                                    "all_live": true,
                                                    "live_categories": [],
                                                    "all_movie": false,
                                                    "movie_categories": [
                                                        14,
                                                        15
                                                    ],
                                                    "all_series": true,
                                                    "series_categories": [],
                                                    "providers": [],
                                                    "copy_login": false,
                                                    "online": false,
                                                    "last_seen_at": null,
                                                    "connections": 0,
                                                    "synced_at": null,
                                                    "created_at": "2026-11-13T10:00:00Z"
                                                }
                                            ]
                                        ]
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_playlists_users_create",
                "description": "Hands the playlist to someone with their own login and links. Every field may be left out: they get a random login, every category, and the provider's end date and connections (else a year and one connection). `providers` gives them their own provider lines: `[{\"provider\": id, \"username\", \"password\", \"dns\"}]`. Refused past the account's customer limit.",
                "summary": "Create a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            },
                            "examples": {
                                "NewCustomer": {
                                    "value": {
                                        "name": "Alice",
                                        "expiry": "2027-06-30T23:59:59Z",
                                        "max_connections": 2,
                                        "all_movie": false,
                                        "movie_categories": [
                                            14,
                                            15
                                        ]
                                    },
                                    "summary": "New customer"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                },
                                "examples": {
                                    "CustomerMade": {
                                        "value": {
                                            "id": 42,
                                            "name": "Alice",
                                            "username": "alice7k2",
                                            "password": "q8w3e5r1",
                                            "enabled": true,
                                            "expiry": "2027-06-30T23:59:59Z",
                                            "sync_expiry": false,
                                            "max_connections": 2,
                                            "message": "",
                                            "notes": "",
                                            "language": "",
                                            "all_live": true,
                                            "live_categories": [],
                                            "all_movie": false,
                                            "movie_categories": [
                                                14,
                                                15
                                            ],
                                            "all_series": true,
                                            "series_categories": [],
                                            "providers": [],
                                            "copy_login": false,
                                            "online": false,
                                            "last_seen_at": null,
                                            "connections": 0,
                                            "synced_at": null,
                                            "created_at": "2026-11-13T10:00:00Z"
                                        },
                                        "summary": "Customer made"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/users/{id}/": {
            "get": {
                "operationId": "editor_playlists_users_retrieve",
                "summary": "Get a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_playlists_users_partial_update",
                "description": "Send only what changes. A new username or password changes their links.",
                "summary": "Update a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_playlists_users_destroy",
                "description": "Their login and links stop working.",
                "summary": "Delete a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/playlists/{pid}/users/{id}/connections/": {
            "get": {
                "operationId": "editor_playlists_users_connections_list",
                "description": "Their last 100 connections, latest first, each `online` when it was seen within the last few minutes (the tracking window of the editor's settings).",
                "summary": "List a customer's connections",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorConnection"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/{pid}/users/{id}/login/": {
            "post": {
                "operationId": "editor_playlists_users_login_create",
                "description": "Sets the `username` and `password` given, or random ones. Their old links stop working.",
                "summary": "Give a customer a new login",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/users/{id}/move/": {
            "post": {
                "operationId": "editor_playlists_users_move_create",
                "description": "Hands the customer to another of the account's playlists (`playlist`): their categories follow by name and their provider lines by address; what that playlist does not have falls back to its defaults.",
                "summary": "Move a customer to another playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/users/{id}/sync/": {
            "post": {
                "operationId": "editor_playlists_users_sync_create",
                "description": "Reads their end date and connections from the provider now, with their own provider line, else the playlist's.",
                "summary": "Read a customer's end date from the provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/users/bulk-categories/": {
            "post": {
                "operationId": "editor_playlists_users_bulk_categories_create",
                "description": "Adds, removes or sets (`mode: \"overwrite\"`) categories of the customers `ids`. `live`, `movie` and `series` are category ids; add and remove leave a kind without ids as it is, overwrite sets every kind given (an empty list: none). Answers how many customers it changed.",
                "summary": "Change the categories of many customers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomersCategoriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomersCategoriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomersCategoriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomersChanged"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/{pid}/users/export.csv": {
            "get": {
                "operationId": "editor_playlists_users_export_csv",
                "description": "Every customer with their links, login, end date, connections, message, notes and provider lines, as a spreadsheet file.",
                "summary": "Export customers as CSV",
                "parameters": [
                    {
                        "in": "path",
                        "name": "pid",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/playlists/import/": {
            "post": {
                "operationId": "editor_playlists_import_create",
                "description": "Makes a new playlist and fills it from a source in a background task: a provider login (`\"type\": \"xtream\"`), an M3U address or an uploaded M3U file. Answers the new playlist and its task. `kinds`: channels (`live`, the default), `movie` and `series`. `attributes`: what to take from the source besides names and links (default: category and logo). `categories`: per kind, the ids of the source's categories to take (from a read of its categories); the others come in already in the bin.",
                "summary": "Import a new playlist",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorImportRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/playlists/reorder/": {
            "post": {
                "operationId": "editor_playlists_reorder_create",
                "description": "Puts your playlists in the order of `ids`, and answers the list as `GET /editor/playlists/` does.",
                "summary": "Reorder playlists",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistReorderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistReorderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPlaylistReorderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/preferences/": {
            "get": {
                "operationId": "editor_preferences_retrieve",
                "description": "Your account's playlist editor preferences (default playlist, columns, layout…), as the dashboard saved them.",
                "summary": "Get editor preferences",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPreferences"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "editor_preferences_update",
                "description": "Replaces your account's playlist editor preferences: any JSON object, up to 64 KB.",
                "summary": "Save editor preferences",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPreferencesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPreferencesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPreferencesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPreferences"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/presets/": {
            "get": {
                "operationId": "editor_presets_list",
                "description": "Your account's presets: saved series of bulk-tool steps, run in one go. The first time, the account gets the built-in ones.",
                "summary": "List presets",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorPreset"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "editor_presets_create",
                "description": "A preset is a list of up to 20 `steps` (`[{tool, options}]`, the bulk tools' own); `kinds` limits the lists it is offered on (empty: every one). An account keeps at most 200 presets.",
                "summary": "Create a preset",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPreset"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/presets/{id}/": {
            "get": {
                "operationId": "editor_presets_retrieve",
                "description": "One of your presets.",
                "summary": "Get a preset",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPreset"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_presets_partial_update",
                "description": "Only the fields sent change; new `steps` are checked as when a preset is made.",
                "summary": "Update a preset",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPresetRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPresetRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorPresetRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPreset"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_presets_destroy",
                "description": "Deletes one of your presets.",
                "summary": "Delete a preset",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/presets/export/": {
            "get": {
                "operationId": "editor_presets_export_retrieve",
                "description": "Your account's presets, to import into another account or keep as a copy.",
                "summary": "Export presets",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPresetBundle"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/presets/import/": {
            "post": {
                "operationId": "editor_presets_import_create",
                "description": "Adds the presets of an export (`presets`), after your own; each is checked as a new preset is. Answers the presets made.",
                "summary": "Import presets",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetBundleRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetBundleRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetBundleRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorPreset"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/presets/reset/": {
            "post": {
                "operationId": "editor_presets_reset_create",
                "description": "Deletes your account's presets and gives it the built-in ones again. Answers the presets made.",
                "summary": "Reset presets to the built-in ones",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorPreset"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/presets/test/": {
            "post": {
                "operationId": "editor_presets_test_create",
                "description": "Runs `steps` on one line of text (`sample`) as they would run on rows of `kind`, and answers the text after each step. Nothing is saved.",
                "summary": "Try steps on a sample line",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetTestRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetTestRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorPresetTestRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPresetSample"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/providers/{id}/": {
            "patch": {
                "operationId": "editor_providers_partial_update",
                "description": "A new label is saved at once (200). A new address or login also rewrites every link that comes from the provider, in a background task (202).",
                "summary": "Update a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorProviderChangeRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProvider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_providers_destroy",
                "description": "Forgets the provider. What came from it stays in the playlist, unless `streams=1`: then it is deleted for good too. Answers how many entries went.",
                "summary": "Delete a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "streams",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Also delete for good every entry that came from it."
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProviderRemoved"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/restore/": {
            "post": {
                "operationId": "editor_restore_create",
                "description": "Restores a backup file in a background task. A private one goes over its playlist (or `playlist`); a shareable one becomes a new playlist. With `name` and no `playlist`, it becomes a new playlist of that name. Only the `sections` chosen are overwritten (default: all).",
                "summary": "Restore a playlist backup",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorRestoreRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorPlaylistTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/settings/": {
            "get": {
                "operationId": "editor_settings_retrieve",
                "description": "The playlist editor's panel-wide limits and timings (Settings → Editor): playlists and customers per reseller, rows per playlist, sync times, undo steps, backups. Panel operators only.",
                "summary": "Get playlist editor settings",
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_settings_partial_update",
                "description": "The playlist editor's panel-wide limits and timings (Settings → Editor): playlists and customers per reseller, rows per playlist, sync times, undo steps, backups. Panel operators only. Only the fields sent change; new limits apply at once.",
                "summary": "Update playlist editor settings",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/sources/scan/": {
            "post": {
                "operationId": "editor_sources_scan_create",
                "description": "Reads the categories of a source in a background task, to pick the ones to import. The finished task lists them by kind in its result.",
                "summary": "Read the categories of a source",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceScanRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceScanRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSourceScanRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/tmdb/{kind}/{tmdb_id}/": {
            "get": {
                "operationId": "editor_tmdb_retrieve",
                "description": "Its details: plot, cast, rating, posters, and a TV show's seasons.",
                "summary": "Get a movie or TV show from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`movie` or `series` (a TV show).",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "language",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A language code, e.g. `en` or `fr-FR`."
                    },
                    {
                        "in": "path",
                        "name": "tmdb_id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTitleDetail"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/tmdb/search/": {
            "get": {
                "operationId": "editor_tmdb_search_list",
                "description": "Up to 20 titles that match, from TMDB (set up under Settings → VOD).",
                "summary": "Search TMDB for a movie or TV show",
                "parameters": [
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`movie` or `series` (a TV show).",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "language",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A language code, e.g. `en` or `fr-FR`."
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The title.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "year",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorTitleHit"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/updaters/{id}/": {
            "get": {
                "operationId": "editor_updaters_retrieve",
                "summary": "Get an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_updaters_partial_update",
                "description": "Send only what changes; `options` and `mappings` are replaced whole.",
                "summary": "Update an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorUpdaterRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUpdater"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_updaters_destroy",
                "summary": "Delete an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/updaters/{id}/categories/": {
            "get": {
                "operationId": "editor_updaters_categories_retrieve",
                "description": "The categories the updater's provider lists, to map them to the playlist's. At once when they were read in the last hour (200); otherwise a background task reads them (202), and its result holds them.",
                "summary": "List the provider's categories of an auto updater",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorProviderCategories"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/updaters/{id}/run/": {
            "post": {
                "operationId": "editor_updaters_run_create",
                "description": "Syncs now, in a background task: every kind it syncs, or only the `kinds` given. Refused while it is already running.",
                "summary": "Run an auto updater now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorSyncNowRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorTaskStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/updaters/{id}/runs/": {
            "get": {
                "operationId": "editor_updaters_runs_list",
                "description": "Its last 50 runs, latest first, with what each one added, renamed and removed, and its log.",
                "summary": "List an auto updater's runs",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorUpdaterRun"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/uploads/": {
            "post": {
                "operationId": "editor_uploads_create",
                "description": "Keeps an M3U file (`.m3u`, `.m3u8` or `.txt`, up to 200 MB) for an import: pass the `upload` id it answers as the source, `{\"type\": \"file\", \"upload\": \"…\"}`.",
                "summary": "Upload an M3U file",
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorUploadRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorUploaded"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/users/{id}/": {
            "get": {
                "operationId": "editor_users_retrieve",
                "summary": "Get a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "editor_users_partial_update",
                "description": "Send only what changes. A new username or password changes their links.",
                "summary": "Update a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEditorCustomerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "editor_users_destroy",
                "description": "Their login and links stop working.",
                "summary": "Delete a customer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/editor/users/{id}/connections/": {
            "get": {
                "operationId": "editor_users_connections_list",
                "description": "Their last 100 connections, latest first, each `online` when it was seen within the last few minutes (the tracking window of the editor's settings).",
                "summary": "List a customer's connections",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EditorConnection"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/editor/users/{id}/login/": {
            "post": {
                "operationId": "editor_users_login_create",
                "description": "Sets the `username` and `password` given, or random ones. Their old links stop working.",
                "summary": "Give a customer a new login",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorNewLoginRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/users/{id}/move/": {
            "post": {
                "operationId": "editor_users_move_create",
                "description": "Hands the customer to another of the account's playlists (`playlist`): their categories follow by name and their provider lines by address; what that playlist does not have falls back to its defaults.",
                "summary": "Move a customer to another playlist",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EditorCustomerMoveRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/editor/users/{id}/sync/": {
            "post": {
                "operationId": "editor_users_sync_create",
                "description": "Reads their end date and connections from the provider now, with their own provider line, else the playlist's.",
                "summary": "Read a customer's end date from the provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist editor"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EditorCustomer"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/epg/channels/": {
            "get": {
                "operationId": "epg_channels_list",
                "description": "The channels the guide holds, a page at a time (25 by default), the closest names first when searching. Accounts that may add or change streams.",
                "summary": "List guide channels",
                "parameters": [
                    {
                        "in": "query",
                        "name": "country",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A country code, such as `UK`."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, guide id or another name."
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedEpgChannelRefList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/epg/countries/": {
            "get": {
                "operationId": "epg_countries_retrieve",
                "description": "The countries Minimus EPG offers, and those this panel imports. Panel operators only.",
                "summary": "List guide countries",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideCountries"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "epg_countries_update",
                "description": "The panel imports exactly the countries in `codes`: new ones are imported, and one left out is removed with the guide only it carried. Answers like \"List guide countries\". Panel operators only.",
                "summary": "Choose the guide countries",
                "tags": [
                    "TV guide"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CountriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CountriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CountriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideCountries"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/epg/countries/suggested/": {
            "get": {
                "operationId": "epg_countries_suggested_retrieve",
                "description": "Countries your streams come from that the panel does not import yet (from a tag in the name, such as `UK:`, or the category), with how many streams name each: what to add for more streams to find a guide. Up to 20. Panel operators only.",
                "summary": "Suggest guide countries",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideSuggestedCountries"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/epg/guide/": {
            "get": {
                "operationId": "epg_guide_retrieve",
                "description": "What a channel (`channel`: its guide id) shows now, next and in the `hours` ahead (24 by default, up to 14 days). Accounts that may add or change streams.",
                "summary": "Get a guide channel's programmes",
                "parameters": [
                    {
                        "in": "query",
                        "name": "channel",
                        "schema": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 255
                        },
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "hours",
                        "schema": {
                            "type": "integer",
                            "maximum": 336,
                            "minimum": 1,
                            "default": 24
                        }
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideChannelProgrammes"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/epg/refresh/": {
            "post": {
                "operationId": "epg_refresh_create",
                "description": "Every source in use is imported again on the next round. Panel operators only.",
                "summary": "Refresh every guide source",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "description": "No response body"
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/epg/settings/": {
            "get": {
                "operationId": "epg_settings_retrieve",
                "description": "The Minimus EPG connection and the import schedule. The key is never returned: `has_key` says whether one is saved. Panel operators only.",
                "summary": "Get the guide settings",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpgSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "epg_settings_partial_update",
                "description": "Changes the fields sent. An empty `api_key` keeps the saved key; a new key or address fetches the countries again at once. Panel operators only.",
                "summary": "Update the guide settings",
                "tags": [
                    "TV guide"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpgSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/epg/settings/test/": {
            "post": {
                "operationId": "epg_settings_test_create",
                "description": "Asks Minimus EPG which countries a key gives: the key sent, or the saved one when none is sent (to check a key before saving it). Panel operators only.",
                "summary": "Test a Minimus EPG key",
                "tags": [
                    "TV guide"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/KeyTestRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/KeyTestRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/KeyTestRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideKeyTest"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/epg/sources/": {
            "get": {
                "operationId": "epg_sources_list",
                "description": "Every guide source (Minimus EPG countries and XMLTV addresses) with how its last import went. Not paged. Panel operators only.",
                "summary": "List guide sources",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/EpgSource"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "epg_sources_create",
                "description": "Adds an XMLTV address (`url`, http or https); `name` defaults to its host. It is imported on the next round. Countries are added with \"Choose the guide countries\". Panel operators only.",
                "summary": "Add a guide source",
                "tags": [
                    "TV guide"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EpgSourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EpgSourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EpgSourceRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpgSource"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/epg/sources/{id}/": {
            "patch": {
                "operationId": "epg_sources_partial_update",
                "description": "Changes its name, address, priority or whether it is used. A Minimus EPG country's name and address cannot change. A new address is imported again. Panel operators only.",
                "summary": "Update a guide source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A unique integer value identifying this EPG source.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpgSourceRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpgSource"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "epg_sources_destroy",
                "description": "Removes the source and the guide only it carried. For a Minimus EPG country, the same as leaving it out of the countries. Panel operators only.",
                "summary": "Delete a guide source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A unique integer value identifying this EPG source.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/epg/sources/{id}/refresh/": {
            "post": {
                "operationId": "epg_sources_refresh_create",
                "description": "Downloads and imports the source again, even when it has not changed. Panel operators only.",
                "summary": "Refresh a guide source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A unique integer value identifying this EPG source.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "description": "No response body"
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/epg/status/": {
            "get": {
                "operationId": "epg_status_retrieve",
                "description": "The guide and how the streams are matched to it, in numbers. Panel operators only.",
                "summary": "Get the guide status",
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideStatus"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/epg/suggest/": {
            "get": {
                "operationId": "epg_suggest_retrieve",
                "description": "The guide channels a stream most likely is, from its name, category and provider guide id (`tvg_id`). Accounts that may add or change streams.",
                "summary": "Suggest guide channels for a stream",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true
                        }
                    },
                    {
                        "in": "query",
                        "name": "limit",
                        "schema": {
                            "type": "integer",
                            "maximum": 20,
                            "minimum": 1,
                            "default": 5
                        }
                    },
                    {
                        "in": "query",
                        "name": "name",
                        "schema": {
                            "type": "string",
                            "default": "",
                            "maxLength": 255
                        }
                    },
                    {
                        "in": "query",
                        "name": "tvg_id",
                        "schema": {
                            "type": "string",
                            "default": "",
                            "maxLength": 255
                        }
                    }
                ],
                "tags": [
                    "TV guide"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GuideSuggestions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/bootstrap/": {
            "post": {
                "operationId": "server_bootstrap_create",
                "description": "Makes a one-time registration token for a new streaming server, and the command to run on it, which installs it and adds it here. The token works once, for `ttl_minutes` (60 by default), and is shown only in this answer. Panel operators only.",
                "summary": "Get the install command for a new server",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ServerBootstrapCreateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ServerBootstrapCreateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ServerBootstrapCreateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerBootstrapResponse"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "The address is taken, or `replaces` is not a moved server."
                    },
                    "402": {
                        "description": "The license allows no more servers."
                    },
                    "409": {
                        "description": "`instance_id` is already used."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/database-health/": {
            "get": {
                "operationId": "instances_database_health_retrieve",
                "description": "How the panel's database is doing: response time, size, connections, largest tables and the last backup, with each problem found as a warning in plain words. Panel operators only.",
                "summary": "Get the database's health",
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DatabaseHealth"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/promote-panel/": {
            "post": {
                "operationId": "server_promote_panel",
                "description": "Makes the panel's own server a streaming server too, and returns the credentials its streaming software signs in with. The installer that adds streaming to the panel's server calls it; calling it again returns the same credentials unless `rotate` is true. Panel operators only.",
                "summary": "Let the panel's own server stream",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PromotePanelRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PromotePanelRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PromotePanelRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerCredentialsResponse"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/": {
            "get": {
                "operationId": "servers_list",
                "description": "Every server, a page at a time: the panel's own and each streaming server, with its addresses, limits, health and update state. Panel operators only.",
                "summary": "List servers",
                "parameters": [
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedServerList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/servers/{id}/": {
            "get": {
                "operationId": "server_detail",
                "description": "Panel operators only.",
                "summary": "Get a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Server"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "server_update",
                "description": "Changes a server's name, address, limits and switches; only the fields sent change. Turning `serves_streams` off moves the streams running there to other servers, and `stream_port` (443, or 1024–65535) asks a streaming server to move its streams to that port, viewers following once it has. Panel operators only.",
                "summary": "Update a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedServerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedServerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedServerRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Server"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "server_destroy",
                "description": "Removes a streaming server: its credentials stop working at once, so it can no longer reach the panel. The panel's own server cannot be deleted (400). Panel operators only.",
                "summary": "Delete a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Deleted."
                    },
                    "400": {
                        "description": "Refused: the panel's own server."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/{id}/analytics/": {
            "get": {
                "operationId": "server_analytics",
                "description": "The server's latest report: whether it is up, its streams and viewers against its limit, CPU, memory, network traffic (`load.bytes_in_rate_bps`, `load.bytes_out_rate_bps`) and version. Figures under `load` are null until the server has reported them; the history is `GET /instances/servers/metrics/?server=<id>`. Panel operators only.",
                "summary": "Get a server's load now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerAnalytics"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/servers/{id}/drain/": {
            "post": {
                "operationId": "server_drain",
                "description": "Takes the server out of rotation (`is_enabled` false): the streams it runs move to other servers and no new ones start there. Undo with `resume`. Panel operators only.",
                "summary": "Stop sending streams to a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Server"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/{id}/reconfigure-caddy/": {
            "post": {
                "operationId": "server_reconfigure_caddy",
                "description": "Applies the server's address to its web server again, e.g. after that web server restarted. The panel's own server does it at once (200, or 502 when it fails); a streaming server at its next check-in (202). Panel operators only.",
                "summary": "Set up a server's web address again",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerActionResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerActionResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerActionResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/{id}/restart/": {
            "post": {
                "operationId": "server_restart",
                "description": "Asks a streaming server to restart its streaming software at its next check-in (within 30 seconds). Not for the panel's own server (400). Panel operators only.",
                "summary": "Restart a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerActionResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerActionResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/{id}/resume/": {
            "post": {
                "operationId": "server_resume",
                "description": "Sends streams to a server stopped with `drain` again. Panel operators only.",
                "summary": "Put a server back in rotation",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Server"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/{id}/update/": {
            "post": {
                "operationId": "instances_servers_update_create",
                "description": "Asks a streaming server to install the release the panel runs, at its next check-in; `update_state` shows how it goes. The panel's own server is updated with the panel (`POST /instances/updates/panel/`). Panel operators only.",
                "summary": "Update a server to the panel's release",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Streaming Server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Server"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "It cannot be done now; `detail` says why."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/servers/metrics/": {
            "get": {
                "operationId": "servers_metrics",
                "description": "CPU, memory, network, streams and viewers over `range`, in time buckets (1 minute for `1h` up to 2 hours for `30d`; at most 360 points, oldest first). With `server`, that server's figures; without, all servers together (CPU averaged, the rest added up). A bucket with no sample is left out, so a chart shows a gap. Panel operators only.",
                "summary": "Get the load history of servers",
                "parameters": [
                    {
                        "in": "query",
                        "name": "range",
                        "schema": {
                            "enum": [
                                "1h",
                                "6h",
                                "24h",
                                "7d",
                                "30d"
                            ],
                            "type": "string",
                            "default": "1h",
                            "minLength": 1
                        },
                        "description": "How far back to look. Sets the bucket width too.\n\n* `1h` - 1h\n* `6h` - 6h\n* `24h` - 24h\n* `7d` - 7d\n* `30d` - 30d"
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "One server's id. Omit for the whole fleet."
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerMetrics"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "Unknown `range`, or `server` is not a server id."
                    },
                    "404": {
                        "description": "No server has that id."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/updates/": {
            "get": {
                "operationId": "instances_updates_retrieve",
                "description": "The release the panel runs, the newest one its license may have, whether a security update is due, the releases it may roll back to, and how the last update, streaming and address changes went. The releases are checked every few minutes; `refresh=1` checks now. Panel operators only.",
                "summary": "Check for updates",
                "parameters": [
                    {
                        "in": "query",
                        "name": "refresh",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "1"
                            ]
                        },
                        "description": "`1` asks the download server again now."
                    }
                ],
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UpdatesOverview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/instances/updates/addresses/": {
            "put": {
                "operationId": "instances_updates_addresses_update",
                "description": "New addresses and ports for the panel, its dashboard and the streaming on its own server (a port left out stays as it is). The server changes them once they lead to it, and keeps the present ones working except those in `remove` and `remove_ports`; follow `addresses` in `GET /instances/updates/`. Panel operators only.",
                "summary": "Change the panel's addresses and ports",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelAddressesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelAddressesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelAddressesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelAddressesState"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "It cannot be done now; `detail` says why."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/updates/nodes/": {
            "post": {
                "operationId": "instances_updates_nodes_create",
                "description": "Asks every streaming server that does not run the panel's release to install it. Answers which were asked and which cannot be updated from here. Panel operators only.",
                "summary": "Update every streaming server",
                "tags": [
                    "Servers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/NodesUpdateResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "503": {
                        "description": "The releases are not known right now: try again in a minute."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/updates/panel/": {
            "post": {
                "operationId": "instances_updates_panel_create",
                "description": "Moves the panel, its dashboard and the streaming on its own server to the newest release, or to `version` (a newer one, or one it may roll back to). The panel is away for a minute or two; follow `panel` in `GET /instances/updates/`. Panel operators only.",
                "summary": "Update the panel",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelUpdateRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelUpdateRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelUpdateRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelUpdateState"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "`version` is not a release."
                    },
                    "409": {
                        "description": "It cannot be done now; `detail` says why."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/updates/streaming/": {
            "post": {
                "operationId": "instances_updates_streaming_create",
                "description": "Installs streaming on the panel's own server, at `domain` (an address of its own that points at the server); `domain: null` stops it, and the server stops getting streams at once. Follow `streaming` in `GET /instances/updates/`. Panel operators only.",
                "summary": "Stream from the panel's own server",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelStreamingRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelStreamingRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PanelStreamingRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelStreamingState"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "`domain` is not a bare hostname."
                    },
                    "409": {
                        "description": "It cannot be done now; `detail` says why."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/instances/updates/streaming/addresses/": {
            "put": {
                "operationId": "instances_updates_streaming_addresses_update",
                "description": "The addresses viewers are sent to on the panel's own server, its main one first, and how each new viewer gets one (`rule`). Each must point at the server; they work as soon as they are saved. Panel operators only.",
                "summary": "Set the panel server's streaming addresses",
                "tags": [
                    "Servers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingAddressesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingAddressesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingAddressesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelStreamingState"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "The panel's own server does not stream."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/jobs/": {
            "get": {
                "operationId": "jobs_list",
                "description": "Every background task you may see (imports, mass edits, syncs, backups…), newest first, a page at a time. An account sees the tasks it started; panel operators allowed to manage a kind of task see everyone's.",
                "summary": "List background tasks",
                "parameters": [
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only these kinds, comma-separated: `import`, `bulk_delete`, `bulk_edit`, `ingest`, `series_import`, `provider_import`, `watch_scan`, `backup`, `panel_import`, `editor`."
                    },
                    {
                        "in": "query",
                        "name": "ordering",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Sort by `created_at`, `kind` or `state`; `-` in front for descending. Default `-created_at`."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the task's name, file or message."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only these states, comma-separated: `queued`, `running`, `waiting`, `stalled`, `completed`, `failed`, `cancelled`; `active` = queued + running."
                    }
                ],
                "tags": [
                    "Background tasks"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedBackgroundTaskList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/jobs/{kind}/{id}/": {
            "get": {
                "operationId": "jobs_retrieve",
                "description": "Its state, progress, details and what you may do to it now.",
                "summary": "Get a background task",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The task's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "backup",
                                "bulk_delete",
                                "bulk_edit",
                                "editor",
                                "import",
                                "ingest",
                                "panel_import",
                                "provider_import",
                                "series_import",
                                "watch_scan"
                            ]
                        },
                        "description": "The kind of task, as in its `kind`.",
                        "required": true
                    }
                ],
                "tags": [
                    "Background tasks"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackgroundTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/jobs/{kind}/{id}/{action}/": {
            "post": {
                "operationId": "jobs_create",
                "description": "Only the actions the task lists in `actions` work now; any other answers 409 saying why. `undo` answers with the new task that puts things back.",
                "summary": "Cancel, resume, retry or undo a background task",
                "parameters": [
                    {
                        "in": "path",
                        "name": "action",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "cancel",
                                "resume",
                                "retry",
                                "undo"
                            ]
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The task's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "backup",
                                "bulk_delete",
                                "bulk_edit",
                                "editor",
                                "import",
                                "ingest",
                                "panel_import",
                                "provider_import",
                                "series_import",
                                "watch_scan"
                            ]
                        },
                        "description": "The kind of task, as in its `kind`.",
                        "required": true
                    }
                ],
                "tags": [
                    "Background tasks"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackgroundTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "The task cannot do that now."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/jobs/options/": {
            "get": {
                "operationId": "jobs_options_retrieve",
                "description": "The kinds and states to filter the list by, with their labels.",
                "summary": "List background task kinds and states",
                "tags": [
                    "Background tasks"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackgroundTaskOptions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/jobs/summary/": {
            "get": {
                "operationId": "jobs_summary_retrieve",
                "description": "How many tasks are in each state, how many are active per kind, and how many failed in the last 24 hours, among the tasks you may see.",
                "summary": "Count background tasks",
                "tags": [
                    "Background tasks"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BackgroundTaskSummary"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/licensing/check/": {
            "post": {
                "operationId": "license_check",
                "description": "Has the license server confirm the license now instead of at its next check (every 15 minutes), then answers with the license status. Superusers only.",
                "summary": "Check the license now",
                "tags": [
                    "License"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LicenseStatus"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/licensing/status/": {
            "get": {
                "operationId": "license_status",
                "description": "The license's holder, plan, server limit, features and expiry; whether streaming is allowed right now and, if not, why (`streaming_allowed`, `problem`); and when the license server last confirmed it (`server_check`). `needs_setup` is true while no license is installed. The license itself is never returned. Panel operators only.",
                "summary": "Get the license status",
                "tags": [
                    "License"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LicenseStatus"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/licensing/upload/": {
            "post": {
                "operationId": "license_upload",
                "description": "Send the license as JSON `{\"token\": \"…\"}`, or its file as `file` in a multipart form. The panel checks it, installs it and has the license server confirm it; streaming starts once it has. Superusers only.",
                "summary": "Install or replace the license",
                "tags": [
                    "License"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LicenseUploadRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/LicenseUploadRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LicenseInstalled"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "License rejected: its signature, expiry or issuer is wrong."
                    },
                    "403": {
                        "description": "Only a superuser can change the panel license."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "license_clear",
                "description": "Streaming stops at once and stays stopped until a new license is installed. Superusers only.",
                "summary": "Remove the license",
                "tags": [
                    "License"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LicenseRemoved"
                                }
                            }
                        },
                        "description": ""
                    },
                    "403": {
                        "description": "Only a superuser can change the panel license."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/bouquets/": {
            "get": {
                "operationId": "management_bouquets_list",
                "description": "Bouquets you can see, a page at a time, in display order: every bouquet for a panel operator, those in the packages they sell for a reseller. What a bouquet holds is listed with `GET /management/bouquets/{id}/content/`.",
                "summary": "List bouquets",
                "parameters": [
                    {
                        "in": "query",
                        "name": "mine",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only the ones you built yourself."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedBouquetListList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "management_bouquets_create",
                "description": "`streams` fills it in the same call. Panel operators, and resellers whose group may build bouquets, from the streams in the bouquets they were given.",
                "summary": "Create a bouquet",
                "tags": [
                    "Bouquets"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Bouquet"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/management/bouquets/{id}/": {
            "get": {
                "operationId": "management_bouquets_retrieve",
                "description": "One bouquet, with how many streams, movies and TV shows it holds.",
                "summary": "Get a bouquet",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Bouquet"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "management_bouquets_update",
                "description": "`streams`, when sent, replaces every stream it holds. A reseller changes only bouquets they built.",
                "summary": "Replace a bouquet",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Bouquet"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "management_bouquets_partial_update",
                "description": "`streams`, when sent, replaces every stream it holds. A reseller changes only bouquets they built.",
                "summary": "Update a bouquet",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBouquetRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBouquetRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedBouquetRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Bouquet"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "management_bouquets_destroy",
                "description": "Packages and lines lose it; its streams, movies and TV shows stay. A reseller deletes only bouquets they built.",
                "summary": "Delete a bouquet",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/bouquets/{id}/content/": {
            "get": {
                "operationId": "management_bouquets_content_list",
                "description": "One kind at a time, a page at a time, with `in_bouquet` on each row. With `membership=out`, what you could add to it.",
                "summary": "List a bouquet's streams, movies or TV shows",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this category."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movies",
                                "series",
                                "streams"
                            ]
                        },
                        "description": "`series`: TV shows.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "membership",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "in",
                                "out"
                            ]
                        },
                        "description": "`in`: what it holds; `out`: what you could add; `all` (default): both."
                    },
                    {
                        "in": "query",
                        "name": "ordering",
                        "schema": {
                            "type": "string"
                        },
                        "description": "`name`, `category_name`, `is_active`, `in_bouquet`, and `status`, `is_on_demand` (streams) or `year`; `-` first for descending."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedBouquetContentRowList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "management_bouquets_content_create",
                "description": "Add or remove streams, movies or TV shows by id, or everything a search selects (`match`). You need the same rights as to edit the bouquet, and can add only what you could list with `membership=out`.",
                "summary": "Add or remove what a bouquet holds",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Bouquet.",
                        "required": true
                    }
                ],
                "tags": [
                    "Bouquets"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetContentChangeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetContentChangeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetContentChangeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BouquetContentChanged"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/management/bouquets/reorder/": {
            "post": {
                "operationId": "management_bouquets_reorder_create",
                "description": "Save a new order for one page of bouquets: they swap places among themselves, so other pages keep theirs. The order is the same for everyone who sees them. Needs the right to build bouquets.",
                "summary": "Reorder bouquets",
                "tags": [
                    "Bouquets"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetReorderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetReorderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BouquetReorderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BouquetReordered"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/management/packages/": {
            "get": {
                "operationId": "management_packages_list",
                "description": "Packages you can see, a page at a time, by name: every package for a panel operator; for a reseller, those their groups may sell and those they built, with what they pay for each (`my_price`).",
                "summary": "List packages",
                "parameters": [
                    {
                        "in": "query",
                        "name": "mine",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only the ones you built yourself."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name or the description."
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedPackageListList"
                                },
                                "examples": {
                                    "APageOfPackages": {
                                        "value": {
                                            "count": 128,
                                            "next": "https://panel.example.com/streams/?page=3&page_size=20",
                                            "previous": "https://panel.example.com/streams/?page=1&page_size=20",
                                            "results": [
                                                {
                                                    "id": "5d2a9e71-3c4b-4f8a-b1e6-9a7c2d0f4e85",
                                                    "name": "1 month",
                                                    "description": "Every channel, 30 days",
                                                    "is_enabled": true,
                                                    "is_trial": false,
                                                    "credit_cost": "12.00",
                                                    "duration_value": 1,
                                                    "duration_type": "months",
                                                    "max_connections": 1,
                                                    "is_restreamer": false,
                                                    "forced_countries": "",
                                                    "lock_to_isp": false,
                                                    "forced_server": null,
                                                    "forced_server_name": null,
                                                    "output_formats": "",
                                                    "allowed_groups": [
                                                        3
                                                    ],
                                                    "allowed_groups_data": [
                                                        {
                                                            "id": 3,
                                                            "name": "Reseller"
                                                        }
                                                    ],
                                                    "bouquets_count": 2,
                                                    "bouquet_ids": [
                                                        "0b8f3c52-6d1e-4a7b-9c2f-5e8d1a4b7c30",
                                                        "7e4d1a96-2f5b-4c3e-8a0d-1b6c9f2e5a73"
                                                    ],
                                                    "my_price": "10.00",
                                                    "my_price_source": "own",
                                                    "created_by": "2c9d4e1f-7a3b-4b8c-9d6e-0f5a1b2c3d4e",
                                                    "created_by_username": "admin",
                                                    "created_at": "2026-10-01T09:00:00Z",
                                                    "updated_at": "2026-11-02T14:30:00Z"
                                                }
                                            ]
                                        },
                                        "summary": "A page of packages"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "management_packages_create",
                "description": "Panel operators, and resellers whose group may build packages: a reseller's package uses only bouquets from the packages they sell, and may not give more for less than those.",
                "summary": "Create a package",
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Package"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/packages/{id}/": {
            "get": {
                "operationId": "management_packages_retrieve",
                "description": "One package, with its bouquets.",
                "summary": "Get a package",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Package"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "management_packages_update",
                "description": "A reseller changes only packages they built. `warnings` names the packages resellers built from this one that now give more than it (a panel operator's change).",
                "summary": "Replace a package",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PackageRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PackageUpdated"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "management_packages_partial_update",
                "description": "A reseller changes only packages they built. `warnings` names the packages resellers built from this one that now give more than it (a panel operator's change).",
                "summary": "Update a package",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPackageRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PackageUpdated"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "management_packages_destroy",
                "description": "A reseller deletes only packages they built.",
                "summary": "Delete a package",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/packages/{id}/assign/": {
            "post": {
                "operationId": "management_packages_assign_create",
                "description": "Adds the package to the line's package history, without changing the line or charging anyone. Panel operators only. To renew a line, extend it with a package instead.",
                "summary": "Record a package in a line's history",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Package.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPackageRequestDocRequest"
                            },
                            "examples": {
                                "AssignPackageRequest": {
                                    "value": {
                                        "line_user_id": "550e8400-e29b-41d4-a716-446655440000"
                                    },
                                    "summary": "Assign package request"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPackageRequestDocRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/AssignPackageRequestDocRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/packages/available_bouquets/": {
            "get": {
                "operationId": "management_packages_available_bouquets_list",
                "description": "Active bouquets you may use in a package you build: every one for a panel operator; for a reseller, those in the packages their groups may sell. One list, not paged.",
                "summary": "List bouquets you can put in a package",
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Bouquet"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/management/packages/out-of-line/": {
            "get": {
                "operationId": "management_packages_out_of_line_list",
                "description": "Packages resellers built that give more than the packages they come from. Nothing is changed. Panel operators only.",
                "summary": "List reseller packages that give too much",
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "package": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid"
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    }
                                                }
                                            },
                                            "built_by": {
                                                "type": "string",
                                                "nullable": true,
                                                "description": "Its reseller."
                                            },
                                            "why": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/management/packages/price-floor/": {
            "get": {
                "operationId": "management_packages_price_floor_retrieve",
                "description": "Before a reseller saves a package: the lowest price these terms may have, the package that sets it, and what saving would refuse. All null for a panel operator.",
                "summary": "Get the lowest price for a package you build",
                "parameters": [
                    {
                        "in": "query",
                        "name": "bouquets",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Comma-separated bouquet ids."
                    },
                    {
                        "in": "query",
                        "name": "duration_type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "days",
                                "hours",
                                "months",
                                "weeks"
                            ]
                        },
                        "description": "Default `days`."
                    },
                    {
                        "in": "query",
                        "name": "duration_value",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Default 30."
                    },
                    {
                        "in": "query",
                        "name": "is_trial",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "in": "query",
                        "name": "max_connections",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Default 1."
                    },
                    {
                        "in": "query",
                        "name": "package",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The package being edited, if any."
                    },
                    {
                        "in": "query",
                        "name": "parents",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Comma-separated ids of the packages it comes from; default: all those you may sell."
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PackagePriceFloor"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/management/user-packages/": {
            "get": {
                "operationId": "management_user_packages_list",
                "description": "Lines' package history, newest first, a page at a time: everything for a panel operator, what they gave for a reseller.",
                "summary": "List packages given to lines",
                "parameters": [
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedUserPackageList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "management_user_packages_create",
                "description": "Panel operators only. Changes neither the line nor anyone's credits.",
                "summary": "Add to a line's package history",
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/user-packages/{id}/": {
            "get": {
                "operationId": "management_user_packages_retrieve",
                "description": "One entry of a line's package history: every one for a panel operator, those they gave for a reseller.",
                "summary": "Get a package given to a line",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this User Package Assignment.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "management_user_packages_update",
                "description": "Panel operators only. Changes neither the line nor anyone's credits.",
                "summary": "Replace an entry of a line's package history",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this User Package Assignment.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/UserPackageRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "management_user_packages_partial_update",
                "description": "Panel operators only. Changes neither the line nor anyone's credits.",
                "summary": "Update an entry of a line's package history",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this User Package Assignment.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserPackageRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserPackageRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedUserPackageRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "management_user_packages_destroy",
                "description": "Panel operators only. Changes neither the line nor anyone's credits.",
                "summary": "Delete an entry of a line's package history",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this User Package Assignment.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/user-packages/{id}/deactivate/": {
            "post": {
                "operationId": "management_user_packages_deactivate_create",
                "description": "Panel operators only. Changes neither the line nor anyone's credits.",
                "summary": "Mark a line's package as no longer active",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this User Package Assignment.",
                        "required": true
                    }
                ],
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UserPackageDeactivated"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/management/user-packages/active/": {
            "get": {
                "operationId": "management_user_packages_active_list",
                "description": "Packages given to lines that are active and not expired, newest first. One list, not paged.",
                "summary": "List packages lines hold now",
                "tags": [
                    "Packages"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/UserPackage"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/movies/": {
            "get": {
                "operationId": "movies_list",
                "description": "The movie library, a page at a time. Resellers see only the movies they added.",
                "summary": "List movies",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only movies in this category."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only active, or only inactive, movies."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only movies with a copy on this server (its id or instance id)."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "failed",
                                "ingesting",
                                "no_media",
                                "ready"
                            ]
                        },
                        "description": "The file's state; `no_media`: no file yet."
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedMovieList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "movies_create",
                "description": "Adds a movie to the library. Give it a file afterwards: download one to a server, upload one, use one already on a server, or play it from a link.",
                "summary": "Create a movie",
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/": {
            "get": {
                "operationId": "movies_retrieve",
                "description": "One movie, with its file and the servers that hold a copy.",
                "summary": "Get a movie",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "movies_update",
                "description": "Saves every field of a movie.",
                "summary": "Replace a movie",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/MovieRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "movies_partial_update",
                "description": "Saves only the fields sent.",
                "summary": "Update a movie",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedMovieRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedMovieRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedMovieRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "movies_destroy",
                "description": "Deletes the movie, and its file from every server in the background.",
                "summary": "Delete a movie",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/movies/{id}/adopt-file/": {
            "post": {
                "operationId": "movies_adopt_file_create",
                "description": "Uses a file already in a server's incoming folder as the movie's file: nothing is copied. `path` is relative to that folder (GET /vod/browse/ lists it). The server checks the file and reports its size and tracks.",
                "summary": "Give a movie a file already on a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/ingest/": {
            "post": {
                "operationId": "movies_ingest_create",
                "description": "Copies the movie's file from a link (`method: url`) or a bucket object (`method: s3`, `s3_key`, and `storage` for another bucket than the VOD one) onto a server that keeps movies and episodes. It runs in the background: the answer (202) is the transfer, listed on GET /vod/jobs/.",
                "summary": "Download a movie's file to a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/IngestJob"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/jobs/": {
            "get": {
                "operationId": "movies_jobs_retrieve",
                "description": "The movie's latest 20 file transfers, newest first. Not paged.",
                "summary": "List a movie's file transfers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/IngestJob"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/movies/{id}/media/": {
            "delete": {
                "operationId": "movies_media_destroy",
                "description": "Removes the movie's file from every server. The movie stays, ready for another file.",
                "summary": "Remove a movie's file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/movies/{id}/preview/": {
            "post": {
                "operationId": "movies_preview_create",
                "description": "A short-lived link to play the movie yourself. It opens a viewing session, closed with DELETE on the same address (opening another title closes it too). A title played by redirect answers its source link and no session.",
                "summary": "Watch a movie from the dashboard",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TitlePreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "No file is ready yet."
                    },
                    "503": {
                        "description": "No server can play it now."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "movies_preview_destroy",
                "description": "Ends the viewing session a preview opened. Answers 204 even when there is nothing to close.",
                "summary": "Close a movie preview",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "session_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The session the preview answered (or in the body)."
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/proxy-source/": {
            "post": {
                "operationId": "movies_proxy_source_create",
                "description": "The movie plays from a link (`url`) or a bucket object (`s3_key`) and nothing is stored. `delivery: proxy`: `server` relays it and viewers never see the source. `delivery: redirect`: viewers are sent to the source itself; `server` only checks it first. Answers 201 with the new file.",
                "summary": "Play a movie from a link without storing it",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProxySourceResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "description": "The server could not read the source."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/replicas/": {
            "post": {
                "operationId": "movies_replicas_create",
                "description": "Copies the movie's file to `server` from a server that holds it, in the background. Answers 202 with the movie: its file's copies show how far it has got.",
                "summary": "Copy a movie to another server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "movies_replicas_destroy",
                "description": "Deletes the copy of the movie's file that `server` holds.",
                "summary": "Remove a movie's copy from a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server (or in the body)."
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/movies/{id}/tmdb-refresh/": {
            "post": {
                "operationId": "movies_tmdb_refresh_create",
                "description": "Fills the movie's plot, date, rating, genre, people, country and artwork again from TMDB; its name is kept. 400 when the movie has no TMDB id.",
                "summary": "Refresh a movie's details from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Movie"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/{id}/upload-ticket/": {
            "post": {
                "operationId": "movies_upload_ticket_create",
                "description": "Prepares an upload from your computer straight to a server that keeps movies and episodes, from the same address that asked. Send the file to `upload_url` in PUT requests of at most `chunk_size` bytes, each with a `Content-Range` header; a HEAD answers how much has arrived (`X-Vod-Offset`).",
                "summary": "Start uploading a movie's file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The movie's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UploadTicket"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/movies/summary/": {
            "get": {
                "operationId": "movies_summary_retrieve",
                "description": "Counters over every movie the list's filters select, not just one page.",
                "summary": "Count movies",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only movies in this category."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only active, or only inactive, movies."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only movies with a copy on this server (its id or instance id)."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "failed",
                                "ingesting",
                                "no_media",
                                "ready"
                            ]
                        },
                        "description": "The file's state; `no_media`: no file yet."
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MovieCounts"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/movies/tmdb/detail/{tmdb_id}/": {
            "get": {
                "operationId": "movies_tmdb_detail_retrieve",
                "description": "Everything the movie form can fill in from one TMDB movie: plot, date, rating, genre, people, country and artwork.",
                "summary": "Get a movie's details from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "tmdb_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The TMDB id, e.g. 603.",
                        "required": true
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbTitle"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/movies/tmdb/search/": {
            "get": {
                "operationId": "movies_tmdb_search_retrieve",
                "description": "Movies on TMDB whose title matches `query` (and `year`, if given), best first. Answers 400 with `configured: false` when no TMDB key is set (Settings → VOD).",
                "summary": "Search TMDB for a movie",
                "parameters": [
                    {
                        "in": "query",
                        "name": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The title to look for.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "year",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only titles of this year."
                    }
                ],
                "tags": [
                    "Movies"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbSearch"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/ping/": {
            "get": {
                "operationId": "ping_retrieve",
                "description": "Answers `{\"message\": \"pong\"}` without signing in.",
                "summary": "Check that the panel answers",
                "tags": [
                    "System"
                ],
                "security": [
                    {}
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/MessageResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                }
            }
        },
        "/resellers/accounts/{id}/domain/": {
            "get": {
                "operationId": "resellers_accounts_domain_retrieve",
                "description": "A reseller's domain and its status, where their lines' links point now, and the DNS record to make. For panel operators allowed to manage resellers' domains.",
                "summary": "Get a reseller's domain",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "resellers_accounts_domain_update",
                "description": "A domain or subdomain (like tv.example.com) for the reseller's lines' links. For panel operators allowed to manage resellers' domains.",
                "summary": "Set a reseller's domain",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "resellers_accounts_domain_destroy",
                "description": "Their lines' links go back to the domain above them, or the panel's own address. For panel operators allowed to manage resellers' domains.",
                "summary": "Remove a reseller's domain",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "There is no domain to remove."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/accounts/{id}/domain/check/": {
            "post": {
                "operationId": "resellers_accounts_domain_check_create",
                "description": "Checks now whether the domain reaches the panel. For panel operators allowed to manage resellers' domains.",
                "summary": "Check a reseller's domain now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "Set a domain first."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/accounts/{id}/domain/old/{name}/": {
            "delete": {
                "operationId": "resellers_accounts_domain_old_destroy",
                "description": "The reseller's players still set up with that domain stop working. For panel operators allowed to manage resellers' domains.",
                "summary": "Remove one of a reseller's old domains",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "name",
                        "schema": {
                            "type": "string"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "That is not one of the old domains."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/domain/": {
            "get": {
                "operationId": "resellers_domain_retrieve",
                "description": "Your own domain and its status, where your lines' links point now, and the DNS record to make. Resellers only: an operator sets a domain for a reseller instead.",
                "summary": "Get your domain",
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "resellers_domain_update",
                "description": "A domain or subdomain (like tv.example.com) for your lines' links, and your sub-resellers' until they set their own. Links use it once it reaches the panel and has a certificate. Resellers only: an operator sets a domain for a reseller instead.",
                "summary": "Set your domain",
                "tags": [
                    "Resellers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ResellerDomainNameRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "resellers_domain_destroy",
                "description": "Your lines' links go back to the domain above you, or the panel's own address. Resellers only: an operator sets a domain for a reseller instead.",
                "summary": "Remove your domain",
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "There is no domain to remove."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/domain/check/": {
            "post": {
                "operationId": "resellers_domain_check_create",
                "description": "Checks now whether your domain reaches the panel, instead of at the next regular check. Resellers only: an operator sets a domain for a reseller instead.",
                "summary": "Check your domain now",
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "Set a domain first."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/domain/old/{name}/": {
            "delete": {
                "operationId": "resellers_domain_old_destroy",
                "description": "An old domain keeps serving your lines after a change, until it is removed here: players still set up with it stop working. Resellers only: an operator sets a domain for a reseller instead.",
                "summary": "Remove one of your old domains",
                "parameters": [
                    {
                        "in": "path",
                        "name": "name",
                        "schema": {
                            "type": "string"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ResellerDomainAccount"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "description": "That is not one of the old domains."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/resellers/domains/": {
            "get": {
                "operationId": "resellers_domains_list",
                "description": "Every reseller, their domain and where their lines' links point, a page at a time. For panel operators allowed to manage resellers' domains.",
                "summary": "List resellers' domains",
                "parameters": [
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the username or the domain."
                    },
                    {
                        "in": "query",
                        "name": "with_domain",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "`true`: only resellers with a domain."
                    }
                ],
                "tags": [
                    "Resellers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedResellerDomainRowList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/resellers/lines/{id}/links/": {
            "get": {
                "operationId": "resellers_lines_links_retrieve",
                "description": "The domain the line's links and playlist use: its reseller's, one inherited from above, or the panel's own address. Anyone who may open the line may ask.",
                "summary": "Get where a line's links point",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Lines"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LineLinks"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/settings/categories/": {
            "get": {
                "operationId": "settings_categories_list",
                "description": "Categories in display order, all at once unless `page` or `page_size` is sent. Hidden ones are left out unless `include_inactive=1` or `is_active` is sent. Any signed-in account may read them.",
                "summary": "List categories",
                "parameters": [
                    {
                        "in": "query",
                        "name": "include_inactive",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "1",
                                "true"
                            ]
                        },
                        "description": "Hidden categories too."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only shown (`true`) or only hidden (`false`) categories."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name."
                    },
                    {
                        "in": "query",
                        "name": "type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "custom",
                                "movies",
                                "streams",
                                "tv_shows"
                            ]
                        },
                        "description": "Only categories of this type."
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedCategoryList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "settings_categories_create",
                "description": "Adds a category of one `type`. It goes last in its type unless `order` is sent. Panel operators, or staff allowed to change categories.",
                "summary": "Create a category",
                "tags": [
                    "Categories"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Category"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/settings/categories/{id}/": {
            "get": {
                "operationId": "settings_categories_retrieve",
                "description": "Shown or hidden. Any signed-in account may read it.",
                "summary": "Get a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Category.",
                        "required": true
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Category"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "settings_categories_update",
                "description": "A category's `type` cannot change. Panel operators, or staff allowed to change categories.",
                "summary": "Replace a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Category.",
                        "required": true
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Category"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "settings_categories_partial_update",
                "description": "Rename, hide or show a category, or change its order. Its `type` cannot change. Panel operators, or staff allowed to change categories.",
                "summary": "Update a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Category.",
                        "required": true
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedCategoryRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedCategoryRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedCategoryRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Category"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "settings_categories_destroy",
                "description": "Deletes a category, never what is filed under it: items that are only also listed under it lose that listing. A category that is still the main one of a stream, movie or TV show is refused (409) unless `move_to` names another category of the same type to move everything to. Panel operators, or staff allowed to change categories.",
                "summary": "Delete a category",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Category.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "move_to",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A category of the same type that takes over its content."
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Deleted."
                    },
                    "400": {
                        "description": "`move_to` is not another category of the same type."
                    },
                    "409": {
                        "description": "It still holds content, or names would clash where it moves."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/categories/reorder/": {
            "post": {
                "operationId": "settings_categories_reorder_create",
                "description": "Saves a new display order for categories of one type, e.g. one page of the list: they swap places among themselves and the rest keep theirs. Panel operators, or staff allowed to change categories.",
                "summary": "Reorder categories",
                "tags": [
                    "Categories"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryReorderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryReorderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CategoryReorderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CategoryReorderResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "`ids` are not categories of one type (`error` says why)."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/settings/categories/summary/": {
            "get": {
                "operationId": "settings_categories_summary_retrieve",
                "description": "How many categories a type has (and how many are hidden), and how many streams, movies and TV shows are filed under them. Only `type` narrows it.",
                "summary": "Count categories and their content",
                "parameters": [
                    {
                        "in": "query",
                        "name": "type",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "custom",
                                "movies",
                                "streams",
                                "tv_shows"
                            ]
                        },
                        "description": "Only categories of this type."
                    }
                ],
                "tags": [
                    "Categories"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CategorySummary"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/settings/panel/": {
            "get": {
                "operationId": "settings_panel_retrieve",
                "description": "How the panel itself behaves (timeouts, cleanup, imports, mass changes): the values, and each one's label, help, bounds and default. Needs the permission to view or change panel settings.",
                "summary": "Get panel settings",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelSettingsPage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "patch": {
                "operationId": "settings_panel_partial_update",
                "description": "Changes only the settings sent; a name that is not a setting is refused (400). Answers like the GET. Needs the permission to change panel settings.",
                "summary": "Update panel settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPanelSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPanelSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedPanelSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelSettingsPage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/security/": {
            "get": {
                "operationId": "settings_security_retrieve",
                "description": "Which viewers are refused (from datacenters, pull tools, on too many devices, for too long), automatic blocks against attacks, and Under attack mode. `diagnostics`, `limits` and `protection` are read-only: what each rule can do here, the bounds of each number, and what attack protection did lately. Panel operators only.",
                "summary": "Get security settings",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SecuritySettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "settings_security_update",
                "description": "Panel operators only.",
                "summary": "Replace security settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SecuritySettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SecuritySettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SecuritySettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SecuritySettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "settings_security_partial_update",
                "description": "Changes only the settings sent. Panel operators only.",
                "summary": "Update security settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSecuritySettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSecuritySettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSecuritySettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SecuritySettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/storage/": {
            "get": {
                "operationId": "settings_storage_list",
                "description": "S3-compatible buckets the panel uses for video files and backups. Secrets are never returned: `has_secret` says whether one is set. Panel operators only.",
                "summary": "List storage buckets",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/StorageConnection"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "settings_storage_create",
                "description": "S3-compatible buckets the panel uses for video files and backups. Secrets are never returned: `has_secret` says whether one is set. Panel operators only.",
                "summary": "Add a storage bucket",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageConnection"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/storage/{id}/": {
            "get": {
                "operationId": "settings_storage_retrieve",
                "description": "Panel operators only.",
                "summary": "Get a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageConnection"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "settings_storage_update",
                "description": "An empty `secret_key` keeps the stored one. Panel operators only.",
                "summary": "Replace a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageConnectionRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageConnection"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "settings_storage_partial_update",
                "description": "An empty `secret_key` keeps the stored one. Panel operators only.",
                "summary": "Update a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStorageConnectionRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStorageConnectionRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStorageConnectionRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageConnection"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "settings_storage_destroy",
                "description": "Refused (409) while something uses it: `used_by` says what. Panel operators only.",
                "summary": "Delete a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Deleted."
                    },
                    "409": {
                        "description": "Still used; `detail` says by what."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/storage/{id}/browse/": {
            "get": {
                "operationId": "settings_storage_browse_retrieve",
                "description": "One folder of the bucket: its folders and files, up to 1000 at a time. Panel operators only.",
                "summary": "Browse a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "path",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The folder, e.g. `movies/2024/`."
                    },
                    {
                        "in": "query",
                        "name": "token",
                        "schema": {
                            "type": "string"
                        },
                        "description": "`next_token` of the previous answer, for the next entries."
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageBrowse"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "The bucket refused; `detail` says why."
                    },
                    "502": {
                        "description": "The bucket could not be reached."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/settings/storage/{id}/check/": {
            "post": {
                "operationId": "settings_storage_check_create",
                "description": "Proves the panel can list, write and delete in the bucket, and keeps the result on it. 400 with `ok: false` when it cannot. Panel operators only.",
                "summary": "Test a storage bucket",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Storage Connection.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageCheckRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageCheckRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StorageCheckRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageCheckResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StorageCheckResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/streaming/": {
            "get": {
                "operationId": "settings_streaming_retrieve",
                "description": "What viewers see while a channel cannot start (a video, and for how long), and whether streaming servers may use their video card. Panel operators only.",
                "summary": "Get streaming settings",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamingSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "settings_streaming_update",
                "description": "Panel operators only.",
                "summary": "Replace streaming settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamingSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamingSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "settings_streaming_partial_update",
                "description": "Panel operators only.",
                "summary": "Update streaming settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamingSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamingSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamingSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamingSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/streaming/down-video/": {
            "put": {
                "operationId": "settings_streaming_down_video_update",
                "description": "Your own video for channels that cannot start (MP4, MKV, MOV, TS or WebM, up to 200 MB), sent in chunks as raw bytes. The last chunk puts it in use, and its answer also holds the streaming settings. Panel operators only.",
                "summary": "Upload the channel-down video",
                "parameters": [
                    {
                        "in": "query",
                        "name": "name",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The file's name, e.g. `no-signal.mp4`.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "offset",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Where this chunk starts in the file.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "size",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The whole file's size in bytes.",
                        "required": true
                    }
                ],
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/octet-stream": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DownVideoChunk"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "delete": {
                "operationId": "settings_streaming_down_video_destroy",
                "description": "Goes back to the Minimus \"No signal\" video. Panel operators only.",
                "summary": "Remove the channel-down video",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamingSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/settings/vod/": {
            "get": {
                "operationId": "settings_vod_retrieve",
                "description": "Movie and TV show settings: the TMDB key and language for details and posters, the storage bucket for video files, and how long playback and upload links last. The TMDB key is never returned: `tmdb_configured` says whether one is set. Panel operators only.",
                "summary": "Get VOD settings",
                "tags": [
                    "Settings"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VodSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "settings_vod_update",
                "description": "Panel operators only.",
                "summary": "Replace VOD settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/VodSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/VodSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/VodSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VodSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            },
            "patch": {
                "operationId": "settings_vod_partial_update",
                "description": "Changes only the settings sent; an empty `tmdb_api_key` removes the key. Panel operators only.",
                "summary": "Update VOD settings",
                "tags": [
                    "Settings"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedVodSettingsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedVodSettingsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedVodSettingsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VodSettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/": {
            "get": {
                "operationId": "streams_list",
                "description": "Streams a page at a time (`page`, `page_size` up to 200), in the order of `ordering` (by default their number, then name). The filters also work on the counters (`/streams/summary/`), the CSV export and the `filters` of a bulk selection.",
                "summary": "List streams",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams filed under this category, as their main one or not."
                    },
                    {
                        "in": "query",
                        "name": "current_server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The server playing it: the server's id or its name from the install."
                    },
                    {
                        "in": "query",
                        "name": "epg",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "manual",
                                "mapped",
                                "unmapped"
                            ]
                        },
                        "description": "With a guide channel, without one, picked by the panel, or picked by hand."
                    },
                    {
                        "in": "query",
                        "name": "has_clients",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Watched by someone now (true), or by nobody (false)."
                    },
                    {
                        "in": "query",
                        "name": "import_job",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams one playlist import added."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Turned on (true) or off (false)."
                    },
                    {
                        "in": "query",
                        "name": "is_on_demand",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Started only when someone watches (true), or always running (false)."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "provider",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Streams that follow this provider or play from one of its addresses."
                    },
                    {
                        "in": "query",
                        "name": "provider_link",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "gone",
                                "linked",
                                "none"
                            ]
                        },
                        "description": "Streams that follow a provider channel, one the provider no longer lists, or none (with `provider`: that play from it without following it)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, or the stream id."
                    },
                    {
                        "in": "query",
                        "name": "source_line",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Streams with a source on this provider line, written `server|username`, e.g. `line.example.com:8080|user1`."
                    },
                    {
                        "in": "query",
                        "name": "source_problem",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "any",
                                "error",
                                "full",
                                "login",
                                "missing",
                                "no_host",
                                "no_media",
                                "other",
                                "refused",
                                "unreachable"
                            ]
                        },
                        "description": "Streams with a source the servers last found down, for this reason."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "error",
                                "offline",
                                "online",
                                "starting"
                            ]
                        },
                        "description": "What the stream is doing now."
                    },
                    {
                        "in": "query",
                        "name": "streaming_engine",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "ffmpeg",
                                "gstreamer"
                            ]
                        }
                    },
                    {
                        "in": "query",
                        "name": "tidy",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "disabled",
                                "ended",
                                "failing",
                                "unlisted",
                                "unwatched"
                            ]
                        },
                        "description": "One group of `GET /streams/tidy/`."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedStreamList"
                                },
                                "examples": {
                                    "OnePageOfStreams": {
                                        "value": {
                                            "count": 128,
                                            "next": "https://panel.example.com/streams/?page=3&page_size=20",
                                            "previous": "https://panel.example.com/streams/?page=1&page_size=20",
                                            "results": [
                                                {
                                                    "id": "3f6c2a1e-8b7d-4c1a-9e2f-5a4b3c2d1e0f",
                                                    "xtream_id": 1201,
                                                    "name": "Channel A",
                                                    "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                                    "category_name": "News",
                                                    "categories": [
                                                        "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718"
                                                    ],
                                                    "bouquets": [
                                                        "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
                                                    ],
                                                    "sources": [
                                                        {
                                                            "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                            "source_name": "Channel A main",
                                                            "source_url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                            "source_health": "online",
                                                            "source_health_at": "2026-11-13T09:58:02Z",
                                                            "source_is_active": true,
                                                            "order": 0
                                                        }
                                                    ],
                                                    "description": "",
                                                    "thumbnail": "https://logos.example.com/channel-a.png",
                                                    "logo_auto": false,
                                                    "epg_channel_id": "channela.example",
                                                    "epg_auto": true,
                                                    "epg_channel": {
                                                        "id": "channela.example",
                                                        "name": "Channel A",
                                                        "icon": "",
                                                        "countries": [
                                                            "GB"
                                                        ],
                                                        "has_guide": true
                                                    },
                                                    "tvg_id": "",
                                                    "streaming_engine": "gstreamer",
                                                    "engine_config": {},
                                                    "transcoding_profile": null,
                                                    "transcoding_profile_name": null,
                                                    "allow_passthrough": true,
                                                    "user_agent": "",
                                                    "http_proxy": "",
                                                    "http_headers": "",
                                                    "is_active": true,
                                                    "is_stopped": false,
                                                    "is_on_demand": false,
                                                    "is_direct": false,
                                                    "routing_mode": "auto",
                                                    "pinned_servers": [],
                                                    "auto_eligible_servers": [],
                                                    "current_server": "e4f5a6b7-c8d9-4e0f-a1b2-c3d4e5f6a7b8",
                                                    "current_source": {
                                                        "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                        "name": "Channel A main",
                                                        "url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                        "health": "online",
                                                        "health_at": "2026-11-13T09:58:02Z",
                                                        "probed_video_codec": "h264",
                                                        "probed_audio_codec": "aac",
                                                        "probed_fps": 25.0,
                                                        "probed_width": 1920,
                                                        "probed_height": 1080,
                                                        "probed_audio_tracks": 1,
                                                        "probed_at": "2026-11-13T08:00:04Z"
                                                    },
                                                    "status": "online",
                                                    "online_since": "2026-11-13T08:00:05Z",
                                                    "live_stats": {
                                                        "fps": 25.0,
                                                        "video_codec": "h264",
                                                        "audio_codec": "aac"
                                                    },
                                                    "check_state": "ready",
                                                    "check_detail": "",
                                                    "checked_at": "2026-11-13T08:00:09Z",
                                                    "sort_order": 1,
                                                    "active_sessions_count": 3,
                                                    "restart_count": 0,
                                                    "stream_config": {
                                                        "engine": "gstreamer",
                                                        "allow_passthrough": true,
                                                        "transcoding_profile": null
                                                    },
                                                    "created_by": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
                                                    "created_by_username": "alice",
                                                    "created_at": "2026-11-01T10:15:00Z",
                                                    "updated_at": "2026-11-13T08:00:09Z",
                                                    "provider_link": null,
                                                    "archive_days": 0,
                                                    "archive_server": null,
                                                    "catchup": null,
                                                    "created_channel": null,
                                                    "delayed": null,
                                                    "feeds_delays": false
                                                }
                                            ]
                                        },
                                        "summary": "One page of streams"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_create",
                "description": "Create its source first (`POST /streams/sources/`), then list it in `sources` with `order` 0; backups follow with 1, 2… Give `category` or `categories`. An always-on stream with a source starts at once; `check_state` says whether it plays yet.",
                "summary": "Create a stream",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            },
                            "examples": {
                                "ALiveStreamWithOneSource": {
                                    "value": {
                                        "name": "Channel A",
                                        "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                        "sources": [
                                            {
                                                "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                "order": 0
                                            }
                                        ]
                                    },
                                    "summary": "Name, category and its main source"
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                },
                                "examples": {
                                    "TheStream,Starting": {
                                        "value": {
                                            "id": "3f6c2a1e-8b7d-4c1a-9e2f-5a4b3c2d1e0f",
                                            "xtream_id": 1201,
                                            "name": "Channel A",
                                            "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                            "category_name": "News",
                                            "categories": [
                                                "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718"
                                            ],
                                            "bouquets": [],
                                            "sources": [
                                                {
                                                    "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                    "source_name": "Channel A main",
                                                    "source_url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                    "source_health": "online",
                                                    "source_health_at": "2026-11-13T09:58:02Z",
                                                    "source_is_active": true,
                                                    "order": 0
                                                }
                                            ],
                                            "description": "",
                                            "thumbnail": "https://logos.example.com/channel-a.png",
                                            "logo_auto": false,
                                            "epg_channel_id": "",
                                            "epg_auto": false,
                                            "epg_channel": null,
                                            "tvg_id": "",
                                            "streaming_engine": "gstreamer",
                                            "engine_config": {},
                                            "transcoding_profile": null,
                                            "transcoding_profile_name": null,
                                            "allow_passthrough": true,
                                            "user_agent": "",
                                            "http_proxy": "",
                                            "http_headers": "",
                                            "is_active": true,
                                            "is_stopped": false,
                                            "is_on_demand": false,
                                            "is_direct": false,
                                            "routing_mode": "auto",
                                            "pinned_servers": [],
                                            "auto_eligible_servers": [],
                                            "current_server": null,
                                            "current_source": null,
                                            "status": "starting",
                                            "online_since": null,
                                            "live_stats": {},
                                            "check_state": "checking",
                                            "check_detail": "",
                                            "checked_at": null,
                                            "sort_order": 1,
                                            "active_sessions_count": 0,
                                            "restart_count": 0,
                                            "stream_config": {
                                                "engine": "gstreamer",
                                                "allow_passthrough": true,
                                                "transcoding_profile": null
                                            },
                                            "created_by": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
                                            "created_by_username": "alice",
                                            "created_at": "2026-11-01T10:15:00Z",
                                            "updated_at": "2026-11-13T08:00:09Z",
                                            "provider_link": null,
                                            "archive_days": 0,
                                            "archive_server": null,
                                            "catchup": null,
                                            "created_channel": null,
                                            "delayed": null,
                                            "feeds_delays": false
                                        },
                                        "summary": "The stream, starting"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/": {
            "get": {
                "operationId": "streams_retrieve",
                "summary": "Get a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_update",
                "description": "A change to how the stream plays (its sources, engine, profile, routing…) restarts it for its viewers; a new guide channel, logo or name does not.",
                "summary": "Replace a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "streams_partial_update",
                "description": "Only the fields sent change. A change to how the stream plays (its sources, engine, profile, routing…) restarts it for its viewers; a new guide channel, logo or name does not.",
                "summary": "Update a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedStreamRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_destroy",
                "description": "Stops it first. Refused (409) while delayed streams play its recording: delete them first.",
                "summary": "Delete a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDeleteRefused"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/{id}/catchup/": {
            "get": {
                "operationId": "streams_catchup_retrieve",
                "description": "What the recording server keeps of the channel, and every past programme of its guide in that time, oldest first, marked recorded or not. `days` is 0 without catch-up.",
                "summary": "Get a stream's catch-up",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamCatchup"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/{id}/catchup/preview/": {
            "post": {
                "operationId": "streams_catchup_preview_create",
                "description": "An address to watch `minutes` (up to 1440) from `start` of a channel with catch-up, as MPEG-TS (`url`) or HLS (`hls_url`). It counts as a viewer under your own name until you close it with `DELETE`.",
                "summary": "Watch a past stretch of a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamCatchupStretchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamCatchupStretchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamCatchupStretchRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamCatchupPreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "That stretch is not recorded."
                    },
                    "503": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "The recording server is not available."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_catchup_preview_destroy",
                "description": "Ends your catch-up preview: send `{\"session_id\": …}` from the preview as the body.",
                "summary": "Close a catch-up preview",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/check/": {
            "post": {
                "operationId": "streams_check_create",
                "description": "Reads the stream's source again (a created channel: its schedule) and sets `check_state`. Refused (409) for a stream that is turned off. Answers with the stream.",
                "summary": "Check whether a stream plays",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/delay/": {
            "get": {
                "operationId": "streams_delay_retrieve",
                "description": "The delay in seconds, the channel it plays later (or, for one with its own source, its source addresses and guide channel), and the server holding the recording. 404 for a stream that is not delayed.",
                "summary": "Get a delayed stream's settings",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDelaySettings"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRefusal"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/{id}/guide/": {
            "get": {
                "operationId": "streams_guide_retrieve",
                "description": "The titles a created channel plays, in order, each with what its guide says by itself (`made`) and your own words for it (`edit`, or null). 404 for other streams.",
                "summary": "List a created channel's guide titles",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "page",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "From 1."
                    },
                    {
                        "in": "query",
                        "name": "page_size",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "1 to 200; 50 by default."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreatedChannelGuidePage"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_guide_update",
                "description": "Your own title, subtitle and description for some titles (by `key`), shown while the plan's guide is `edited`. All three empty: back to the title's own words. Answers how many were kept.",
                "summary": "Edit a created channel's guide",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreatedChannelGuideEditsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/CreatedChannelGuideEditsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/CreatedChannelGuideEditsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreatedChannelGuideKept"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/plan/": {
            "get": {
                "operationId": "streams_plan_retrieve",
                "description": "What a created channel plays, in which order, at which fixed times and how it looks. It is written with the stream (`plan` in a create or an update). 404 for other streams.",
                "summary": "Get a created channel's plan",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreatedChannelPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/{id}/preview/": {
            "post": {
                "operationId": "streams_preview_create",
                "description": "A short-lived address to watch the stream yourself, even when it is not running (a server starts it for you). It counts as a viewer under your own name until you close it with `DELETE`. Optional `convert` (`audio` or `video`) asks the server to convert what a browser cannot play; `plays`, the codec families the player handles, lets the panel decide. A stream sent straight from its source answers `direct: true` and the source address.",
                "summary": "Preview a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamPreviewOptionsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamPreviewOptionsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamPreviewOptionsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamPreviewAddress"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "The stream has no working source."
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "The stream is turned off."
                    },
                    "503": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "No streaming server can play it now."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_preview_destroy",
                "description": "Ends your preview: send `{\"session_id\": …}` from the preview as the body. A stream the preview started is stopped again, unless someone else is watching it.",
                "summary": "Close a stream preview",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/restart/": {
            "post": {
                "operationId": "streams_restart_create",
                "description": "Stops the stream and starts it again, for instance after changing its sources or profile. Refused for a stream that is turned off. Answers with the stream.",
                "summary": "Restart a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                },
                                "examples": {
                                    "Restarting": {
                                        "value": {
                                            "id": "3f6c2a1e-8b7d-4c1a-9e2f-5a4b3c2d1e0f",
                                            "xtream_id": 1201,
                                            "name": "Channel A",
                                            "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                            "category_name": "News",
                                            "categories": [
                                                "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718"
                                            ],
                                            "bouquets": [
                                                "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
                                            ],
                                            "sources": [
                                                {
                                                    "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                    "source_name": "Channel A main",
                                                    "source_url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                    "source_health": "online",
                                                    "source_health_at": "2026-11-13T09:58:02Z",
                                                    "source_is_active": true,
                                                    "order": 0
                                                }
                                            ],
                                            "description": "",
                                            "thumbnail": "https://logos.example.com/channel-a.png",
                                            "logo_auto": false,
                                            "epg_channel_id": "channela.example",
                                            "epg_auto": true,
                                            "epg_channel": {
                                                "id": "channela.example",
                                                "name": "Channel A",
                                                "icon": "",
                                                "countries": [
                                                    "GB"
                                                ],
                                                "has_guide": true
                                            },
                                            "tvg_id": "",
                                            "streaming_engine": "gstreamer",
                                            "engine_config": {},
                                            "transcoding_profile": null,
                                            "transcoding_profile_name": null,
                                            "allow_passthrough": true,
                                            "user_agent": "",
                                            "http_proxy": "",
                                            "http_headers": "",
                                            "is_active": true,
                                            "is_stopped": false,
                                            "is_on_demand": false,
                                            "is_direct": false,
                                            "routing_mode": "auto",
                                            "pinned_servers": [],
                                            "auto_eligible_servers": [],
                                            "current_server": "e4f5a6b7-c8d9-4e0f-a1b2-c3d4e5f6a7b8",
                                            "current_source": {
                                                "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                "name": "Channel A main",
                                                "url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                "health": "online",
                                                "health_at": "2026-11-13T09:58:02Z",
                                                "probed_video_codec": "h264",
                                                "probed_audio_codec": "aac",
                                                "probed_fps": 25.0,
                                                "probed_width": 1920,
                                                "probed_height": 1080,
                                                "probed_audio_tracks": 1,
                                                "probed_at": "2026-11-13T08:00:04Z"
                                            },
                                            "status": "starting",
                                            "online_since": null,
                                            "live_stats": {
                                                "fps": 25.0,
                                                "video_codec": "h264",
                                                "audio_codec": "aac"
                                            },
                                            "check_state": "ready",
                                            "check_detail": "",
                                            "checked_at": "2026-11-13T08:00:09Z",
                                            "sort_order": 1,
                                            "active_sessions_count": 0,
                                            "restart_count": 0,
                                            "stream_config": {
                                                "engine": "gstreamer",
                                                "allow_passthrough": true,
                                                "transcoding_profile": null
                                            },
                                            "created_by": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
                                            "created_by_username": "alice",
                                            "created_at": "2026-11-01T10:15:00Z",
                                            "updated_at": "2026-11-13T08:00:09Z",
                                            "provider_link": null,
                                            "archive_days": 0,
                                            "archive_server": null,
                                            "catchup": null,
                                            "created_channel": null,
                                            "delayed": null,
                                            "feeds_delays": false
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRefusal"
                                }
                            }
                        },
                        "description": "Turned off."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/restarts/": {
            "get": {
                "operationId": "streams_restarts_retrieve",
                "description": "When the stream had to start again and which source it was reading, newest first (100 at most). `window_seconds` is the span `restart_count` counts over.",
                "summary": "List a stream's restarts",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRestarts"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/{id}/schedule/": {
            "get": {
                "operationId": "streams_schedule_retrieve",
                "description": "What a created channel plays on one day, in its own time zone. 404 for other streams.",
                "summary": "Get a created channel's schedule",
                "parameters": [
                    {
                        "in": "query",
                        "name": "day",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "description": "YYYY-MM-DD; today by default."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CreatedChannelDay"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/{id}/schedule/restart/": {
            "post": {
                "operationId": "streams_schedule_restart_create",
                "description": "Plays the channel again from its first title, now. A channel set to play once that ended is turned back on. 404 for other streams.",
                "summary": "Play a created channel from the start",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/start/": {
            "post": {
                "operationId": "streams_start_create",
                "description": "Starts a stream that is turned on and not already online. An on-demand stream is only marked to start: it plays when someone watches. Answers with the stream.",
                "summary": "Start a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                },
                                "examples": {
                                    "Starting": {
                                        "value": {
                                            "id": "3f6c2a1e-8b7d-4c1a-9e2f-5a4b3c2d1e0f",
                                            "xtream_id": 1201,
                                            "name": "Channel A",
                                            "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                            "category_name": "News",
                                            "categories": [
                                                "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718"
                                            ],
                                            "bouquets": [
                                                "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
                                            ],
                                            "sources": [
                                                {
                                                    "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                    "source_name": "Channel A main",
                                                    "source_url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                    "source_health": "online",
                                                    "source_health_at": "2026-11-13T09:58:02Z",
                                                    "source_is_active": true,
                                                    "order": 0
                                                }
                                            ],
                                            "description": "",
                                            "thumbnail": "https://logos.example.com/channel-a.png",
                                            "logo_auto": false,
                                            "epg_channel_id": "channela.example",
                                            "epg_auto": true,
                                            "epg_channel": {
                                                "id": "channela.example",
                                                "name": "Channel A",
                                                "icon": "",
                                                "countries": [
                                                    "GB"
                                                ],
                                                "has_guide": true
                                            },
                                            "tvg_id": "",
                                            "streaming_engine": "gstreamer",
                                            "engine_config": {},
                                            "transcoding_profile": null,
                                            "transcoding_profile_name": null,
                                            "allow_passthrough": true,
                                            "user_agent": "",
                                            "http_proxy": "",
                                            "http_headers": "",
                                            "is_active": true,
                                            "is_stopped": false,
                                            "is_on_demand": false,
                                            "is_direct": false,
                                            "routing_mode": "auto",
                                            "pinned_servers": [],
                                            "auto_eligible_servers": [],
                                            "current_server": "e4f5a6b7-c8d9-4e0f-a1b2-c3d4e5f6a7b8",
                                            "current_source": {
                                                "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                "name": "Channel A main",
                                                "url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                "health": "online",
                                                "health_at": "2026-11-13T09:58:02Z",
                                                "probed_video_codec": "h264",
                                                "probed_audio_codec": "aac",
                                                "probed_fps": 25.0,
                                                "probed_width": 1920,
                                                "probed_height": 1080,
                                                "probed_audio_tracks": 1,
                                                "probed_at": "2026-11-13T08:00:04Z"
                                            },
                                            "status": "starting",
                                            "online_since": null,
                                            "live_stats": {
                                                "fps": 25.0,
                                                "video_codec": "h264",
                                                "audio_codec": "aac"
                                            },
                                            "check_state": "ready",
                                            "check_detail": "",
                                            "checked_at": "2026-11-13T08:00:09Z",
                                            "sort_order": 1,
                                            "active_sessions_count": 0,
                                            "restart_count": 0,
                                            "stream_config": {
                                                "engine": "gstreamer",
                                                "allow_passthrough": true,
                                                "transcoding_profile": null
                                            },
                                            "created_by": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
                                            "created_by_username": "alice",
                                            "created_at": "2026-11-01T10:15:00Z",
                                            "updated_at": "2026-11-13T08:00:09Z",
                                            "provider_link": null,
                                            "archive_days": 0,
                                            "archive_server": null,
                                            "catchup": null,
                                            "created_channel": null,
                                            "delayed": null,
                                            "feeds_delays": false
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRefusal"
                                }
                            }
                        },
                        "description": "Turned off, or online."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/stop/": {
            "post": {
                "operationId": "streams_stop_create",
                "description": "Stops the stream and keeps it stopped until it is started again: servers do not start it by themselves. Answers with the stream.",
                "summary": "Stop a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                },
                                "examples": {
                                    "Stopped": {
                                        "value": {
                                            "id": "3f6c2a1e-8b7d-4c1a-9e2f-5a4b3c2d1e0f",
                                            "xtream_id": 1201,
                                            "name": "Channel A",
                                            "category": "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718",
                                            "category_name": "News",
                                            "categories": [
                                                "9b2e4f1a-6c3d-4e8f-a1b2-c3d4e5f60718"
                                            ],
                                            "bouquets": [
                                                "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
                                            ],
                                            "sources": [
                                                {
                                                    "source": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                    "source_name": "Channel A main",
                                                    "source_url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                    "source_health": "online",
                                                    "source_health_at": "2026-11-13T09:58:02Z",
                                                    "source_is_active": true,
                                                    "order": 0
                                                }
                                            ],
                                            "description": "",
                                            "thumbnail": "https://logos.example.com/channel-a.png",
                                            "logo_auto": false,
                                            "epg_channel_id": "channela.example",
                                            "epg_auto": true,
                                            "epg_channel": {
                                                "id": "channela.example",
                                                "name": "Channel A",
                                                "icon": "",
                                                "countries": [
                                                    "GB"
                                                ],
                                                "has_guide": true
                                            },
                                            "tvg_id": "",
                                            "streaming_engine": "gstreamer",
                                            "engine_config": {},
                                            "transcoding_profile": null,
                                            "transcoding_profile_name": null,
                                            "allow_passthrough": true,
                                            "user_agent": "",
                                            "http_proxy": "",
                                            "http_headers": "",
                                            "is_active": true,
                                            "is_stopped": true,
                                            "is_on_demand": false,
                                            "is_direct": false,
                                            "routing_mode": "auto",
                                            "pinned_servers": [],
                                            "auto_eligible_servers": [],
                                            "current_server": null,
                                            "current_source": {
                                                "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                                                "name": "Channel A main",
                                                "url": "http://provider.example.com:8080/live/user1/pass1/1201.ts",
                                                "health": "online",
                                                "health_at": "2026-11-13T09:58:02Z",
                                                "probed_video_codec": "h264",
                                                "probed_audio_codec": "aac",
                                                "probed_fps": 25.0,
                                                "probed_width": 1920,
                                                "probed_height": 1080,
                                                "probed_audio_tracks": 1,
                                                "probed_at": "2026-11-13T08:00:04Z"
                                            },
                                            "status": "offline",
                                            "online_since": null,
                                            "live_stats": {
                                                "fps": 25.0,
                                                "video_codec": "h264",
                                                "audio_codec": "aac"
                                            },
                                            "check_state": "ready",
                                            "check_detail": "",
                                            "checked_at": "2026-11-13T08:00:09Z",
                                            "sort_order": 1,
                                            "active_sessions_count": 0,
                                            "restart_count": 0,
                                            "stream_config": {
                                                "engine": "gstreamer",
                                                "allow_passthrough": true,
                                                "transcoding_profile": null
                                            },
                                            "created_by": "5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f",
                                            "created_by_username": "alice",
                                            "created_at": "2026-11-01T10:15:00Z",
                                            "updated_at": "2026-11-13T08:00:09Z",
                                            "provider_link": null,
                                            "archive_days": 0,
                                            "archive_server": null,
                                            "catchup": null,
                                            "created_channel": null,
                                            "delayed": null,
                                            "feeds_delays": false
                                        }
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/{id}/toggle-active/": {
            "post": {
                "operationId": "streams_toggle_active_create",
                "description": "Flips `is_active`. Turning off stops it; turning an always-on stream with a source back on starts it. Answers with the stream.",
                "summary": "Turn a stream on or off",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The stream's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Stream"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/activity/": {
            "get": {
                "operationId": "streams_activity_list",
                "description": "Connections that have ended, newest first, a page at a time (`page_size` up to 100). Rows of lines the caller may not manage are left out.",
                "summary": "List past connections",
                "parameters": [
                    {
                        "in": "query",
                        "name": "line",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The line's username, exactly."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "Whose lines: the caller's own (`mine`, the default for most), theirs and their resellers' (`subtree`), or every line (`all`, for accounts allowed to see them all)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the line, what was watched, the server or the address."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The server's name, exactly."
                    },
                    {
                        "in": "query",
                        "name": "since",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "description": "Started at or after."
                    },
                    {
                        "in": "query",
                        "name": "stream",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The stream's name, exactly."
                    },
                    {
                        "in": "query",
                        "name": "until",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "description": "Started before."
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedActivityLogList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/activity/clear/": {
            "post": {
                "operationId": "streams_activity_clear_create",
                "description": "Deletes ended connections from the history: all of them, or those older than `older_than_days`. Live connections are never touched. Panel operators only.",
                "summary": "Clear past connections",
                "tags": [
                    "Connections"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityClearRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityClearRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityClearRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ActivityCleared"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/activity/retention/": {
            "get": {
                "operationId": "streams_activity_retention_retrieve",
                "description": "Days ended connections are kept before they are deleted (0: for good). Panel operators only.",
                "summary": "Get how long past connections are kept",
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ActivityRetention"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_activity_retention_update",
                "description": "Ended connections older than `retention_days` are deleted once a day; 0 keeps them. Panel operators only.",
                "summary": "Set how long past connections are kept",
                "tags": [
                    "Connections"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityRetentionRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityRetentionRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ActivityRetentionRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ActivityRetention"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/blocked-ips/": {
            "get": {
                "operationId": "streams_blocked_ips_list",
                "description": "Addresses blocked for everything: the panel and every streaming server. Panel operators only. Blocks that ran out are left out unless `include_ended`.",
                "summary": "List blocked addresses",
                "parameters": [
                    {
                        "in": "query",
                        "name": "include_ended",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Also the automatic blocks that ran out, kept a week."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "search",
                        "required": false,
                        "in": "query",
                        "description": "A search term.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "source",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "manual"
                            ]
                        },
                        "description": "Only the blocks the panel placed by itself, or the ones made by hand."
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedBlockedIPList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_blocked_ips_create",
                "description": "Blocks an address, a block (`203.0.113.0/24`) or a range (`a-b`), for `duration` or until `expires_at`. Refused when it covers your own address or a server of the panel, or when a wider block holds it already. When that very entry is blocked already the answer is 409 with it: send `replace: true` to change it. Connections from inside it are ended.",
                "summary": "Block an address",
                "tags": [
                    "Connections"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BlockAddressRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BlockAddressRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BlockAddressRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BlockedAddressesAdded"
                                }
                            }
                        },
                        "description": "Blocked."
                    },
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BlockedAddressesAdded"
                                }
                            }
                        },
                        "description": "The existing block was changed (`replace`)."
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BlockedAddressAlready"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/blocked-ips/{id}/": {
            "get": {
                "operationId": "streams_blocked_ips_retrieve",
                "description": "Addresses blocked for everything: the panel and every streaming server. Panel operators only.",
                "summary": "Get a blocked address",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A unique integer value identifying this Blocked address.",
                        "required": true
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BlockedIP"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "delete": {
                "operationId": "streams_blocked_ips_destroy",
                "description": "A block you made is deleted; one the panel placed by itself is lifted and stays in the week's log.",
                "summary": "Unblock an address",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "A unique integer value identifying this Blocked address.",
                        "required": true
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/blocked-ips/match/": {
            "get": {
                "operationId": "streams_blocked_ips_match_retrieve",
                "description": "For up to 200 `address` values, the ones blocked now and the block holding each, as `{address: block}`.",
                "summary": "Check which addresses are blocked",
                "parameters": [
                    {
                        "in": "query",
                        "name": "address",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        },
                        "description": "An address to check; repeat for more.",
                        "required": true,
                        "explode": true
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "$ref": "#/components/schemas/BlockedIP"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/bulk-delete/": {
            "post": {
                "operationId": "streams_bulk_delete_create",
                "description": "Deletes the selection in the background. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Delete many streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedBackgroundTask"
                                }
                            }
                        },
                        "description": "The background task deleting them."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/bulk-delete/plan/": {
            "post": {
                "operationId": "streams_bulk_delete_plan_create",
                "description": "What deleting the selection would remove, touching nothing: streams, their sessions, the sources only they use (`sources_orphaned`) and the streams playing now. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Preview deleting many streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDeletePlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/bulk-edit/": {
            "post": {
                "operationId": "streams_bulk_edit_create",
                "description": "Applies `changes` to the selection in the background; a key left out leaves that field alone. Streams whose playback changes restart a few at a time. `sources` is changed on its own, never with other changes. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Edit many streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamBulkEditRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamBulkEditRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamBulkEditRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedBackgroundTask"
                                }
                            }
                        },
                        "description": "The background task editing them."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/bulk-edit/import-names/": {
            "get": {
                "operationId": "streams_bulk_edit_import_names_retrieve",
                "description": "The rule playlist imports apply to the names they add, or null.",
                "summary": "Get the renaming rule for imports",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ImportRenamingRule"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_bulk_edit_import_names_update",
                "description": "Keeps a rule every playlist import applies to the names it adds; `{\"rule\": null}` stops. Panel operators only.",
                "summary": "Set the renaming rule for imports",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportRenamingRuleRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportRenamingRuleRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportRenamingRuleRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ImportRenamingRule"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/bulk-edit/options/": {
            "get": {
                "operationId": "streams_bulk_edit_options_retrieve",
                "description": "The choices a bulk edit offers, the largest selection one task takes, and the pace it restarts streams at.",
                "summary": "Get the bulk edit options",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamBulkEditOptions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/bulk-edit/rename-preview/": {
            "post": {
                "operationId": "streams_bulk_edit_rename_preview_create",
                "description": "What a renaming rule would do to the selection, writing nothing: counts, the first names before and after, the ones refused because the new name is taken, and how many follow a provider's names. The rename itself is a bulk edit with `changes.rename`. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Preview renaming many streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRenamePreviewRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRenamePreviewRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamRenamePreviewRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRenamePreviewResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/bulk-edit/sources/lines/": {
            "post": {
                "operationId": "streams_bulk_edit_sources_lines_create",
                "description": "The provider lines (server and username) the selection's sources are on, most used first, with how many streams use each as main or backup. The provider of each is named for accounts that see the whole catalogue. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "List the provider lines of streams' sources",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamSourceLines"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/bulk-edit/sources/preview/": {
            "post": {
                "operationId": "streams_bulk_edit_sources_preview_create",
                "description": "What a change of `sources` would do to the selection, writing nothing: how many streams change, which find no match and why, a few before and after, and how many restart. Naming a provider is for accounts that see the whole catalogue. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Preview changing many streams' sources",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSourcesChangeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSourcesChangeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSourcesChangeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamSourcesPreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/connections/": {
            "get": {
                "operationId": "streams_connections_list",
                "description": "Everyone watching now: one row per connection with the line, what it watches, the server, the address and where it comes from, newest first. Not paged. Rows of lines the caller may not manage are left out.",
                "summary": "List live connections",
                "parameters": [
                    {
                        "in": "query",
                        "name": "scope",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "mine",
                                "subtree"
                            ]
                        },
                        "description": "Whose lines: the caller's own (`mine`, the default for most), theirs and their resellers' (`subtree`), or every line (`all`, for accounts allowed to see them all)."
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/LiveConnection"
                                    }
                                },
                                "examples": {
                                    "SomeoneWatching": {
                                        "value": [
                                            {
                                                "session_id": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
                                                "line": "alice",
                                                "line_id": 412,
                                                "owner": "reseller1",
                                                "groups": [
                                                    "Reseller"
                                                ],
                                                "stream_name": "Channel A",
                                                "kind": "live",
                                                "title": "Channel A",
                                                "server": "Server 1",
                                                "ip": "203.0.113.7",
                                                "player": "ExamplePlayer/2.1",
                                                "country_code": "GB",
                                                "isp": "Example Broadband",
                                                "city": "London",
                                                "output": "TS",
                                                "restreamer": false,
                                                "restreamer_reasons": [],
                                                "datacenter": false,
                                                "vpn": false,
                                                "tor": false,
                                                "started_at": "2026-11-13T09:41:12Z",
                                                "last_heartbeat": "2026-11-13T10:02:40Z"
                                            }
                                        ],
                                        "summary": "Someone watching"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/connections/{session_id}/disconnect/": {
            "post": {
                "operationId": "streams_connections_disconnect_create",
                "description": "Ends one live connection by its `session_id` and frees the line's connection. The player's immediate retry is refused for a short while (Settings → Panel).",
                "summary": "Disconnect a viewer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "session_id",
                        "schema": {
                            "type": "string"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Connections"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ConnectionDisconnected"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/delay-cost/": {
            "get": {
                "operationId": "streams_delay_cost_retrieve",
                "description": "Before saving a delayed stream: the disk it needs on the recording server, the room left there, whether the channel must now run all the time, and when it is ready. Give `original` (the channel to delay) or nothing (a delayed stream with its own source); `stream` when editing one.",
                "summary": "Estimate what a delay costs",
                "parameters": [
                    {
                        "in": "query",
                        "name": "original",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The channel to delay."
                    },
                    {
                        "in": "query",
                        "name": "seconds",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The delay: 120 to 604800 (7 days).",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server to record on, when nothing records the channel yet."
                    },
                    {
                        "in": "query",
                        "name": "stream",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The delayed stream being edited."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDelayCost"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRefusal"
                                }
                            }
                        },
                        "description": ""
                    },
                    "404": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamRefusal"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/duplicates/": {
            "get": {
                "operationId": "streams_duplicates_retrieve",
                "description": "Groups of streams that are the same channel (same source, or same guide channel and name), biggest first, a page at a time, each with the stream it would keep. `totals` counts every page.",
                "summary": "Find duplicate streams",
                "parameters": [
                    {
                        "in": "query",
                        "name": "page",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "From 1."
                    },
                    {
                        "in": "query",
                        "name": "page_size",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "1 to 100; 20 by default."
                    },
                    {
                        "in": "query",
                        "name": "reason",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "guide",
                                "source"
                            ]
                        },
                        "description": "Only groups found this way."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Groups with a stream named like this."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDuplicates"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/duplicates/merge/": {
            "post": {
                "operationId": "streams_duplicates_merge_create",
                "description": "`merge` folds each group into the stream it keeps, which takes the others' sources as backups, their bouquets and categories, and their guide channel and logo when it has none; then the others are deleted. `delete` only deletes the others. Give the groups ticked (`groups`) or every group (`all`, with the `reason` and `search` of the page, less `exclude`); `keep` picks another stream to keep in a group. Groups are found again first; `gone` counts the ones no longer there. Runs in the background.",
                "summary": "Merge or delete duplicate streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamDuplicatesMergeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamDuplicatesMergeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamDuplicatesMergeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamDuplicatesMergeTask"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/export/": {
            "get": {
                "operationId": "streams_export_retrieve",
                "description": "Every stream the list filters select, in the list order (`ordering`), as a CSV file. Not paged.",
                "summary": "Export streams as CSV",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams filed under this category, as their main one or not."
                    },
                    {
                        "in": "query",
                        "name": "current_server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The server playing it: the server's id or its name from the install."
                    },
                    {
                        "in": "query",
                        "name": "epg",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "manual",
                                "mapped",
                                "unmapped"
                            ]
                        },
                        "description": "With a guide channel, without one, picked by the panel, or picked by hand."
                    },
                    {
                        "in": "query",
                        "name": "has_clients",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Watched by someone now (true), or by nobody (false)."
                    },
                    {
                        "in": "query",
                        "name": "import_job",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams one playlist import added."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Turned on (true) or off (false)."
                    },
                    {
                        "in": "query",
                        "name": "is_on_demand",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Started only when someone watches (true), or always running (false)."
                    },
                    {
                        "in": "query",
                        "name": "provider",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Streams that follow this provider or play from one of its addresses."
                    },
                    {
                        "in": "query",
                        "name": "provider_link",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "gone",
                                "linked",
                                "none"
                            ]
                        },
                        "description": "Streams that follow a provider channel, one the provider no longer lists, or none (with `provider`: that play from it without following it)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, or the stream id."
                    },
                    {
                        "in": "query",
                        "name": "source_line",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Streams with a source on this provider line, written `server|username`, e.g. `line.example.com:8080|user1`."
                    },
                    {
                        "in": "query",
                        "name": "source_problem",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "any",
                                "error",
                                "full",
                                "login",
                                "missing",
                                "no_host",
                                "no_media",
                                "other",
                                "refused",
                                "unreachable"
                            ]
                        },
                        "description": "Streams with a source the servers last found down, for this reason."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "error",
                                "offline",
                                "online",
                                "starting"
                            ]
                        },
                        "description": "What the stream is doing now."
                    },
                    {
                        "in": "query",
                        "name": "streaming_engine",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "ffmpeg",
                                "gstreamer"
                            ]
                        }
                    },
                    {
                        "in": "query",
                        "name": "tidy",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "disabled",
                                "ended",
                                "failing",
                                "unlisted",
                                "unwatched"
                            ]
                        },
                        "description": "One group of `GET /streams/tidy/`."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/logos/": {
            "get": {
                "operationId": "streams_logos_retrieve",
                "description": "How many streams have no logo, how many have one the panel found, and whether the panel fills them in by itself (Settings → Panel).",
                "summary": "Count streams without a logo",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamLogoCounters"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_logos_create",
                "description": "`action: find` gives every stream without a logo (in the selection, if one is given) the one Minimus finds; with `mode: auto` it also picks again the ones it found before. `action: clear` takes back the logos the panel added; a logo you set is never touched. Runs in the background. A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Find or remove logos for streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamLogosChangeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamLogosChangeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamLogosChangeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedBackgroundTask"
                                }
                            }
                        },
                        "description": "The background task changing the logos."
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": "No stream needs this."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/m3u-imports/": {
            "get": {
                "operationId": "streams_m3u_imports_list",
                "description": "Imports newest first, a page at a time: the caller's own, or every one for an account that sees the whole catalogue.",
                "summary": "List playlist imports",
                "parameters": [
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the file name."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string"
                        },
                        "description": "One or more of `parsing`, `parsed`, `running`, `starting`, `completed`, `failed`, `cancelled`, separated by commas."
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedM3UImportList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_m3u_imports_create",
                "description": "Step one of an import: send the M3U file (`playlist_file`) or its text (`playlist_text`). The panel reads it in the background: poll the import until `status` is `parsed`, then choose its groups and options with `start`.",
                "summary": "Upload a playlist to import",
                "tags": [
                    "Playlist imports"
                ],
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/M3UUploadRequest"
                            }
                        },
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportTextRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/M3UImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/m3u-imports/{id}/": {
            "get": {
                "operationId": "streams_m3u_imports_retrieve",
                "description": "One import and its progress: poll it while the playlist is read and while the import runs.",
                "summary": "Get a playlist import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/M3UImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "delete": {
                "operationId": "streams_m3u_imports_destroy",
                "description": "Removes the import from the history; the streams it added stay. Refused (409) while it runs: cancel it first.",
                "summary": "Delete a playlist import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/m3u-imports/{id}/cancel/": {
            "post": {
                "operationId": "streams_m3u_imports_cancel_create",
                "description": "Stops a running import between two batches; what it added stays.",
                "summary": "Cancel a playlist import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/M3UImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/m3u-imports/{id}/provider-matches/": {
            "post": {
                "operationId": "streams_m3u_imports_provider_matches_create",
                "description": "Among the channels of the `groups` given (every group when none), how many \"Follow provider channels\" would match a provider channel by source or by name, and how many could be more than one. Writes nothing. Panel operators only.",
                "summary": "Count channels that would follow a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportGroupsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportGroupsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportGroupsRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PlaylistImportProviderMatches"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/m3u-imports/{id}/start/": {
            "post": {
                "operationId": "streams_m3u_imports_start_create",
                "description": "Step two: the groups to import (`groups`, as named in `group_summary`; \"\" for channels without a group) and what to apply to the streams it adds. The import runs in the background; poll it for its progress. `GET /streams/m3u-imports/options/` lists the choices and defaults.",
                "summary": "Start a playlist import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The playlist import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Playlist imports"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportStartRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportStartRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PlaylistImportStartRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/M3UImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/m3u-imports/options/": {
            "get": {
                "operationId": "streams_m3u_imports_options_retrieve",
                "description": "The choices and defaults of `start`, the import statuses, the largest playlist accepted, and above how many channels it is better to import them on demand.",
                "summary": "Get the playlist import options",
                "tags": [
                    "Playlist imports"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PlaylistImportOptions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/": {
            "get": {
                "operationId": "streams_providers_list",
                "description": "Every provider with its status, connections, counts and last sync, a page at a time. Panel operators only.",
                "summary": "List providers",
                "parameters": [
                    {
                        "in": "query",
                        "name": "ordering",
                        "schema": {
                            "type": "string"
                        },
                        "description": "`name`, `kind`, `address`, `status`, `expires_at`, `last_sync_at`, `next_sync_at`, `sync_every_minutes`, `linked_streams`, `gone_links`, `connections` or `created_at`; `-` in front for descending."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, address or username."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedProviderRowList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_providers_create",
                "description": "Saves a provider and, when it is enabled, starts its first sync, which reads its catalogue and checks the line. `kind` is `xtream` for a provider login (server, username, password) or `m3u` for a playlist address. `password` is write-only. Panel operators only.",
                "summary": "Add a provider",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Provider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/{id}/": {
            "get": {
                "operationId": "streams_providers_retrieve",
                "description": "One provider with everything its form edits. The password is never returned (`has_password` says whether one is saved), and the address is shown without a login in it. Panel operators only.",
                "summary": "Get a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Provider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_providers_update",
                "description": "Saves every field of a provider. An empty `password` keeps the saved one. A new login or link format syncs it again, and the streams that follow it get the new links. Panel operators only.",
                "summary": "Replace a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Provider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "streams_providers_partial_update",
                "description": "Changes only the fields sent. An empty `password` keeps the saved one. A new login or link format syncs it again, and the streams that follow it get the new links. Panel operators only.",
                "summary": "Update a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedProviderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedProviderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedProviderRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Provider"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_providers_destroy",
                "description": "Forgets the provider, its catalogue and its links. The streams that followed it keep their names and play as before; `unlinked` says how many they were. Panel operators only.",
                "summary": "Delete a provider",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderDeleted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/providers/{id}/categories/": {
            "get": {
                "operationId": "streams_providers_categories_retrieve",
                "description": "The categories of what the provider lists now, with how many each holds. Panel operators only.",
                "summary": "List a provider's categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "episode",
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Default `live`."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "id": {
                                                "type": "string"
                                            },
                                            "name": {
                                                "type": "string"
                                            },
                                            "count": {
                                                "type": "integer"
                                            }
                                        },
                                        "required": [
                                            "count",
                                            "id",
                                            "name"
                                        ]
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/{id}/items/": {
            "get": {
                "operationId": "streams_providers_items_list",
                "description": "The channels, movies, TV shows or episodes the provider lists, a page at a time: by category and name, what it no longer lists last. Panel operators only.",
                "summary": "List a provider's catalogue",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The provider's category id."
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "import_state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "done",
                                "failed",
                                "new",
                                "skipped"
                            ]
                        },
                        "description": "Movies and TV shows: waiting, imported, left out or failed."
                    },
                    {
                        "in": "query",
                        "name": "in_panel",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "no",
                                "yes"
                            ]
                        },
                        "description": "Movies and TV shows: already in the panel or not."
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "episode",
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "What to list (default `live`)."
                    },
                    {
                        "in": "query",
                        "name": "ordering",
                        "schema": {
                            "type": "string"
                        },
                        "description": "`name`, `category`, `item_id`, `added_at`, `changed_at` or `gone_at`; `-` in front for descending."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, or an exact id."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "changed",
                                "gone",
                                "new"
                            ]
                        },
                        "description": "New or changed in the last sync, or no longer listed."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedProviderCatalogueItemList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/{id}/runs/": {
            "get": {
                "operationId": "streams_providers_runs_retrieve",
                "description": "The last 50 syncs, newest first, when the provider keeps its history (empty otherwise). Panel operators only.",
                "summary": "List a provider's syncs",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "description": "One sync.",
                                        "properties": {
                                            "id": {
                                                "type": "integer"
                                            },
                                            "trigger": {
                                                "enum": [
                                                    "schedule",
                                                    "manual"
                                                ],
                                                "type": "string"
                                            },
                                            "started_at": {
                                                "type": "string",
                                                "format": "date-time"
                                            },
                                            "finished_at": {
                                                "type": "string",
                                                "format": "date-time"
                                            },
                                            "ok": {
                                                "type": "boolean"
                                            },
                                            "summary": {
                                                "type": "object",
                                                "additionalProperties": {}
                                            }
                                        },
                                        "required": [
                                            "finished_at",
                                            "id",
                                            "ok",
                                            "started_at",
                                            "summary",
                                            "trigger"
                                        ]
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/{id}/sync/": {
            "post": {
                "operationId": "streams_providers_sync_create",
                "description": "Reads the provider's catalogue again in the background and updates the streams that follow it. When a sync is already running, that one answers. Panel operators only.",
                "summary": "Sync a provider now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderSyncStarted"
                                },
                                "examples": {
                                    "SyncStarted": {
                                        "value": {
                                            "syncing": true
                                        },
                                        "summary": "Sync started"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/{id}/vod-categories/": {
            "get": {
                "operationId": "streams_providers_vod_categories_retrieve",
                "description": "What a category mapping maps: the provider's own categories with how many titles each holds, and the genres the details come with. Panel operators only.",
                "summary": "List a provider's movie or TV show categories",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Default `movie`."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderVodCategories"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/{id}/vod-import/": {
            "post": {
                "operationId": "streams_providers_vod_import_create",
                "description": "Imports what waits. With nothing waiting, a sync looks for what is new first and imports it. Importing movies or TV shows must be on for the provider. Panel operators only.",
                "summary": "Import a provider's movies and TV shows now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderVodImportStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/{id}/vod-imports/": {
            "get": {
                "operationId": "streams_providers_vod_imports_retrieve",
                "description": "The last 30 imports of movies and TV shows, newest first. Panel operators only.",
                "summary": "List a provider's imports",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The provider id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/ProviderVodImport"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/alerts/": {
            "get": {
                "operationId": "streams_providers_alerts_retrieve",
                "description": "Provider lines that look down (many of their channels failed to open lately), and lines about to end, full, or refused by the provider. Panel operators only.",
                "summary": "List provider alerts",
                "parameters": [
                    {
                        "in": "query",
                        "name": "provider",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only this provider's alerts."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderAlerts"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/items/search/": {
            "get": {
                "operationId": "streams_providers_items_search_retrieve",
                "description": "Channels of every enabled provider, closest names first, grouped by provider, a page at a time (25 by default): what to pick for a stream to follow. Panel operators only.",
                "summary": "Search the channels of every provider",
                "parameters": [
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "episode",
                                "live",
                                "movie",
                                "series"
                            ]
                        },
                        "description": "Default `live`."
                    },
                    {
                        "in": "query",
                        "name": "page",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "page_size",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "At most 200."
                    },
                    {
                        "in": "query",
                        "name": "provider",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only this provider."
                    },
                    {
                        "in": "query",
                        "name": "q",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, or an exact id."
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderItemSearch"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/providers/links/apply/": {
            "post": {
                "operationId": "streams_providers_links_apply_create",
                "description": "Makes each stream follow the channel given. Streams you may not change and channels the provider does not list are skipped. The `sync_*` switches, when sent, set what each stream takes from its channel. Panel operators who may change streams.",
                "summary": "Link streams to provider channels",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinksApplyRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinksApplyRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinksApplyRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinksApplied"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/links/match/": {
            "post": {
                "operationId": "streams_providers_links_match_create",
                "description": "Proposes a channel for each stream chosen, of one `provider` or any: the channel its sources play, else the channel of the same name, with whether linking would rename it. Nothing is saved: send the pairs you keep to \"Link streams to provider channels\". The totals count every stream; the first 2,000 pairs are listed. Streams are chosen by `stream_ids`, or by `filter` (the stream list's own filters, `{}` for every stream) less `exclude`. Panel operators who may change streams.",
                "summary": "Match streams to provider channels",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkMatchQueryRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkMatchQueryRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkMatchQueryRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinkMatches"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/links/remove/": {
            "post": {
                "operationId": "streams_providers_links_remove_create",
                "description": "The chosen streams no longer follow a channel; they keep their names and play as before. Streams are chosen by `stream_ids`, or by `filter` (the stream list's own filters, `{}` for every stream) less `exclude`. Panel operators who may change streams.",
                "summary": "Stop streams following provider channels",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSelectionRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSelectionRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSelectionRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinksRemoved"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/providers/links/settings/": {
            "post": {
                "operationId": "streams_providers_links_settings_create",
                "description": "Turns the name, logo or guide id switches on or off for the chosen streams' links, and applies what was switched on now. Streams are chosen by `stream_ids`, or by `filter` (the stream list's own filters, `{}` for every stream) less `exclude`. Panel operators who may change streams.",
                "summary": "Switch what streams take from their channel",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSwitchesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSwitchesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSwitchesRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinkSettingsChanged"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/links/suggest/": {
            "post": {
                "operationId": "streams_providers_links_suggest_create",
                "description": "The channels a stream not saved yet most likely is, from its name and source addresses (main first): the channel its sources play, then channels of the same or a similar name. Panel operators only.",
                "summary": "Suggest channels for a new stream",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSuggestQueryRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSuggestQueryRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderLinkSuggestQueryRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinkSuggestions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/providers/test/": {
            "post": {
                "operationId": "streams_providers_test_create",
                "description": "Asks the provider about a login without saving anything: its status, connections and expiry, then how many channels, movies and TV shows it lists. Send `id` to test with a saved provider's password. Panel operators only.",
                "summary": "Test a provider login",
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderTestRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderTestRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProviderTestRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderTestResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sort/": {
            "post": {
                "operationId": "streams_sort_create",
                "description": "Moves the selection by the rules, in the background. New categories are made first. With `save`, playlist imports sort what they add by these rules too (panel operators only). Each rule matches names that start with, contain or end with `text` and puts them in `category`, or in a category named `new_category` made for it. With `unlist_old` (the default) a stream leaves the category it was in.",
                "summary": "Sort streams into categories",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QueuedBackgroundTask"
                                }
                            }
                        },
                        "description": "The background task moving them."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sort/preview/": {
            "post": {
                "operationId": "streams_sort_preview_create",
                "description": "Where each stream of the selection would go, writing nothing. Each rule matches names that start with, contain or end with `text` and puts them in `category`, or in a category named `new_category` made for it. With `unlist_old` (the default) a stream leaves the category it was in.",
                "summary": "Preview sorting streams into categories",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortPreviewRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortPreviewRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamSortPreviewRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamSortPreviewResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sort/rules/": {
            "get": {
                "operationId": "streams_sort_rules_retrieve",
                "description": "The rules that sort the streams playlist imports add.",
                "summary": "Get the sorting rules for imports",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ImportSortRules"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_sort_rules_update",
                "description": "Replaces the rules that sort what playlist imports add; an empty list stops sorting them. Panel operators only. Each rule matches names that start with, contain or end with `text` and puts them in `category`, or in a category named `new_category` made for it. With `unlist_old` (the default) a stream leaves the category it was in.",
                "summary": "Set the sorting rules for imports",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportSortRuleListRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportSortRuleListRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportSortRuleListRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ImportSortRules"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sort/suggest/": {
            "post": {
                "operationId": "streams_sort_suggest_create",
                "description": "A rule for each code often found at the start of the names in the selection (`UK:`, `|FR|`…). A `selection` is the streams ticked (`ids`) or every stream the list filters select (`all_matching: true` with `filters`, less `exclude`).",
                "summary": "Suggest rules to sort streams",
                "tags": [
                    "Streams"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SelectedStreamsRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamSortSuggestions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sources/": {
            "get": {
                "operationId": "streams_sources_list",
                "description": "Sources a page at a time (`page`, `page_size` up to 200), newest first. An account that does not see the whole catalogue gets only the sources it created.",
                "summary": "List sources",
                "parameters": [
                    {
                        "in": "query",
                        "name": "health",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "down",
                                "online",
                                "unknown"
                            ]
                        },
                        "description": "How the servers last found it."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only turned-on (true) or turned-off (false) sources."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name or the address."
                    },
                    {
                        "in": "query",
                        "name": "unused",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only sources no stream reads from."
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedSourceList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_sources_create",
                "description": "A source is one address a stream is read from. Create it here, then list its id in a stream's `sources`.",
                "summary": "Create a source",
                "tags": [
                    "Sources"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Source"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sources/{id}/": {
            "get": {
                "operationId": "streams_sources_retrieve",
                "summary": "Get a source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The source's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Source"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_sources_update",
                "summary": "Replace a source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The source's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Source"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "streams_sources_partial_update",
                "summary": "Update a source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The source's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSourceRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Source"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_sources_destroy",
                "summary": "Delete a source",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The source's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/sources/replace-host/": {
            "post": {
                "operationId": "streams_sources_replace_host_create",
                "description": "Rewrites the scheme, host and port of every source on `from_host` to `to_base`, keeping each path. With `dry_run` (the default) nothing is written: the answer says what would change. Running streams that are always on restart on the new address; on-demand streams use it from their next start. Movies played from that host move too for accounts that see the whole catalogue.",
                "summary": "Move sources to a provider's new address",
                "tags": [
                    "Sources"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceHostReplaceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceHostReplaceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SourceHostReplaceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SourceHostMove"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/sources/summary/": {
            "get": {
                "operationId": "streams_sources_summary_retrieve",
                "description": "Counters over every source the filters select, not just one page. Takes the same filters as the list; `page` and `page_size` are ignored.",
                "summary": "Count sources by health",
                "parameters": [
                    {
                        "in": "query",
                        "name": "health",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "down",
                                "online",
                                "unknown"
                            ]
                        },
                        "description": "How the servers last found it."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only turned-on (true) or turned-off (false) sources."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name or the address."
                    },
                    {
                        "in": "query",
                        "name": "unused",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only sources no stream reads from."
                    }
                ],
                "tags": [
                    "Sources"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SourceCounters"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/stats/": {
            "get": {
                "operationId": "streams_stats_retrieve",
                "description": "What the dashboard's top bar shows: connections and lines watching now and, for accounts that see the whole panel, streams online, server traffic and whether \"Under attack\" mode is on. A reseller gets only its own lines' connections.",
                "summary": "Get viewer and traffic totals",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PanelTotals"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/streams/{id}/provider-link/": {
            "get": {
                "operationId": "streams_streams_provider_link_retrieve",
                "description": "Which provider channel the stream follows, and what it takes from it. 404 when it follows none. Panel operators only.",
                "summary": "Get a stream's provider channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamProviderLink"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_streams_provider_link_update",
                "description": "The stream follows `item_id` of `provider` (a channel it lists now), in place of any channel it followed. The `sync_*` switches say what it takes from the channel; following the name may rename it at once. Panel operators who may change streams.",
                "summary": "Make a stream follow a provider channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamProviderLinkRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamProviderLinkRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StreamProviderLinkRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamProviderLinkSaved"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_streams_provider_link_destroy",
                "description": "The stream keeps its name and plays as before. Panel operators who may change streams.",
                "summary": "Stop a stream following a provider channel",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/streams/streams/{id}/provider-link/suggest/": {
            "get": {
                "operationId": "streams_streams_provider_link_suggest_retrieve",
                "description": "The channels a saved stream most likely is: the channel its sources play, then channels of the same or a similar name. Panel operators only.",
                "summary": "Suggest provider channels for a stream",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "required": true
                    }
                ],
                "tags": [
                    "Providers"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProviderLinkSuggestions"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/summary/": {
            "get": {
                "operationId": "streams_summary_retrieve",
                "description": "Counters over every stream the filters select, not just one page, and how many people watch them now. Takes the same filters as the list; `page` and `page_size` are ignored.",
                "summary": "Count streams by status",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams filed under this category, as their main one or not."
                    },
                    {
                        "in": "query",
                        "name": "current_server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The server playing it: the server's id or its name from the install."
                    },
                    {
                        "in": "query",
                        "name": "epg",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "manual",
                                "mapped",
                                "unmapped"
                            ]
                        },
                        "description": "With a guide channel, without one, picked by the panel, or picked by hand."
                    },
                    {
                        "in": "query",
                        "name": "has_clients",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Watched by someone now (true), or by nobody (false)."
                    },
                    {
                        "in": "query",
                        "name": "import_job",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Streams one playlist import added."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Turned on (true) or off (false)."
                    },
                    {
                        "in": "query",
                        "name": "is_on_demand",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Started only when someone watches (true), or always running (false)."
                    },
                    {
                        "in": "query",
                        "name": "provider",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Streams that follow this provider or play from one of its addresses."
                    },
                    {
                        "in": "query",
                        "name": "provider_link",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "gone",
                                "linked",
                                "none"
                            ]
                        },
                        "description": "Streams that follow a provider channel, one the provider no longer lists, or none (with `provider`: that play from it without following it)."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Part of the name, or the stream id."
                    },
                    {
                        "in": "query",
                        "name": "source_line",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Streams with a source on this provider line, written `server|username`, e.g. `line.example.com:8080|user1`."
                    },
                    {
                        "in": "query",
                        "name": "source_problem",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "any",
                                "error",
                                "full",
                                "login",
                                "missing",
                                "no_host",
                                "no_media",
                                "other",
                                "refused",
                                "unreachable"
                            ]
                        },
                        "description": "Streams with a source the servers last found down, for this reason."
                    },
                    {
                        "in": "query",
                        "name": "status",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "error",
                                "offline",
                                "online",
                                "starting"
                            ]
                        },
                        "description": "What the stream is doing now."
                    },
                    {
                        "in": "query",
                        "name": "streaming_engine",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "ffmpeg",
                                "gstreamer"
                            ]
                        }
                    },
                    {
                        "in": "query",
                        "name": "tidy",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "disabled",
                                "ended",
                                "failing",
                                "unlisted",
                                "unwatched"
                            ]
                        },
                        "description": "One group of `GET /streams/tidy/`."
                    }
                ],
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamCounters"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/tidy/": {
            "get": {
                "operationId": "streams_tidy_retrieve",
                "description": "Groups of streams worth a decision (not watched for days, failing for days, turned off for days, in no bouquet, or events whose date has passed), each with its count, a few names and the days it is about. Act on one with a bulk edit or delete whose filters hold `tidy`.",
                "summary": "List streams worth tidying up",
                "tags": [
                    "Streams"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StreamTidyGroups"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/streams/transcoding-profiles/": {
            "get": {
                "operationId": "streams_transcoding_profiles_list",
                "description": "How a stream's picture and sound are converted when it is not sent as it is. Built-in profiles (`is_system`) can be edited but not deleted.",
                "summary": "List transcoding profiles",
                "parameters": [
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "tags": [
                    "Transcoding profiles"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedTranscodingProfileList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "streams_transcoding_profiles_create",
                "description": "Give it to a stream (`transcoding_profile`) to convert the stream this way.",
                "summary": "Create a transcoding profile",
                "tags": [
                    "Transcoding profiles"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TranscodingProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/streams/transcoding-profiles/{id}/": {
            "get": {
                "operationId": "streams_transcoding_profiles_retrieve",
                "description": "Built-in profiles (`is_system`) can be edited but not deleted.",
                "summary": "Get a transcoding profile",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Transcoding Profile.",
                        "required": true
                    }
                ],
                "tags": [
                    "Transcoding profiles"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TranscodingProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "streams_transcoding_profiles_update",
                "description": "Built-in profiles (`is_system`) can be edited but not deleted.",
                "summary": "Replace a transcoding profile",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Transcoding Profile.",
                        "required": true
                    }
                ],
                "tags": [
                    "Transcoding profiles"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/TranscodingProfileRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TranscodingProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "streams_transcoding_profiles_partial_update",
                "description": "Built-in profiles (`is_system`) can be edited but not deleted.",
                "summary": "Update a transcoding profile",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Transcoding Profile.",
                        "required": true
                    }
                ],
                "tags": [
                    "Transcoding profiles"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedTranscodingProfileRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedTranscodingProfileRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedTranscodingProfileRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TranscodingProfile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "streams_transcoding_profiles_destroy",
                "description": "Built-in profiles cannot be deleted (400): copy one instead.",
                "summary": "Delete a transcoding profile",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A UUID string identifying this Transcoding Profile.",
                        "required": true
                    }
                ],
                "tags": [
                    "Transcoding profiles"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ErrorResponseDoc"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/episodes/": {
            "get": {
                "operationId": "tv_episodes_list",
                "description": "Episodes of the TV shows you may manage, a page at a time.",
                "summary": "List episodes",
                "parameters": [
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    },
                    {
                        "in": "query",
                        "name": "season",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this season's episodes."
                    },
                    {
                        "in": "query",
                        "name": "series",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this TV show's episodes."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "failed",
                                "ingesting",
                                "no_media",
                                "ready"
                            ]
                        },
                        "description": "The file's state; `no_media`: no file yet."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedEpisodeList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "tv_episodes_create",
                "description": "Adds an episode to a season. Give it a file afterwards, as for a movie.",
                "summary": "Create an episode",
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/": {
            "get": {
                "operationId": "tv_episodes_retrieve",
                "description": "One episode, with its file and the servers that hold a copy.",
                "summary": "Get an episode",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "tv_episodes_update",
                "description": "Saves every field of an episode.",
                "summary": "Replace an episode",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "tv_episodes_partial_update",
                "description": "Saves only the fields sent.",
                "summary": "Update an episode",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpisodeRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpisodeRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedEpisodeRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "tv_episodes_destroy",
                "description": "Deletes the episode, and its file from every server in the background.",
                "summary": "Delete an episode",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/episodes/{id}/adopt-file/": {
            "post": {
                "operationId": "tv_episodes_adopt_file_create",
                "description": "Uses a file already in a server's incoming folder as the episode's file: nothing is copied. `path` is relative to that folder (GET /vod/browse/ lists it). The server checks the file and reports its size and tracks.",
                "summary": "Give an episode a file already on a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/AdoptFileRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/ingest/": {
            "post": {
                "operationId": "tv_episodes_ingest_create",
                "description": "Copies the episode's file from a link (`method: url`) or a bucket object (`method: s3`, `s3_key`, and `storage` for another bucket than the VOD one) onto a server that keeps movies and episodes. It runs in the background: the answer (202) is the transfer, listed on GET /vod/jobs/.",
                "summary": "Download an episode's file to a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/StartIngestRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/IngestJob"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/jobs/": {
            "get": {
                "operationId": "tv_episodes_jobs_retrieve",
                "description": "The episode's latest 20 file transfers, newest first. Not paged.",
                "summary": "List an episode's file transfers",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/IngestJob"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/tv/episodes/{id}/media/": {
            "delete": {
                "operationId": "tv_episodes_media_destroy",
                "description": "Removes the episode's file from every server. The episode stays, ready for another file.",
                "summary": "Remove an episode's file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/episodes/{id}/preview/": {
            "post": {
                "operationId": "tv_episodes_preview_create",
                "description": "A short-lived link to play the episode yourself. It opens a viewing session, closed with DELETE on the same address (opening another title closes it too). A title played by redirect answers its source link and no session.",
                "summary": "Watch an episode from the dashboard",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TitlePreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "409": {
                        "description": "No file is ready yet."
                    },
                    "503": {
                        "description": "No server can play it now."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "tv_episodes_preview_destroy",
                "description": "Ends the viewing session a preview opened. Answers 204 even when there is nothing to close.",
                "summary": "Close an episode preview",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "session_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The session the preview answered (or in the body)."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/proxy-source/": {
            "post": {
                "operationId": "tv_episodes_proxy_source_create",
                "description": "The episode plays from a link (`url`) or a bucket object (`s3_key`) and nothing is stored. `delivery: proxy`: `server` relays it and viewers never see the source. `delivery: redirect`: viewers are sent to the source itself; `server` only checks it first. Answers 201 with the new file.",
                "summary": "Play an episode from a link without storing it",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ProxySourceRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProxySourceResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "description": "The server could not read the source."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/replicas/": {
            "post": {
                "operationId": "tv_episodes_replicas_create",
                "description": "Copies the episode's file to `server` from a server that holds it, in the background. Answers 202 with the episode: its file's copies show how far it has got.",
                "summary": "Copy an episode to another server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ReplicaServerRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "tv_episodes_replicas_destroy",
                "description": "Deletes the copy of the episode's file that `server` holds.",
                "summary": "Remove an episode's copy from a server",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server (or in the body)."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/episodes/{id}/tmdb-refresh/": {
            "post": {
                "operationId": "tv_episodes_tmdb_refresh_create",
                "description": "Fills the episode's details again from TMDB, by the show's TMDB id and the season and episode numbers. 400 when the show has no TMDB id.",
                "summary": "Refresh an episode's details from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Episode"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/{id}/upload-ticket/": {
            "post": {
                "operationId": "tv_episodes_upload_ticket_create",
                "description": "Prepares an upload from your computer straight to a server that keeps movies and episodes, from the same address that asked. Send the file to `upload_url` in PUT requests of at most `chunk_size` bytes, each with a `Content-Range` header; a HEAD answers how much has arrived (`X-Vod-Offset`).",
                "summary": "Start uploading an episode's file",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The episode's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/TitleUploadRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UploadTicket"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/episodes/bulk/": {
            "post": {
                "operationId": "tv_episodes_bulk_create",
                "description": "One action over the episodes picked by `ids`, or every episode of a `season` or `series`. `activate`, `deactivate` and `delete` are done at once. `detach` (remove their files), `replicate` (copy them to `server`) and `remove_replica` (remove `server`'s copies) run in the background: 202.",
                "summary": "Change many episodes at once",
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeBulkRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeBulkRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/EpisodeBulkRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpisodeBulkResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EpisodeBulkQueued"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/imports/{id}/": {
            "get": {
                "operationId": "tv_imports_retrieve",
                "description": "One import into a TV show (from TMDB or from files) and how far it has got. Background tasks lists, cancels and resumes them.",
                "summary": "Get a TV show import",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The import's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SeriesImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/tv/seasons/": {
            "get": {
                "operationId": "tv_seasons_list",
                "description": "Seasons of the TV shows you may manage, by number. Not paged.",
                "summary": "List seasons",
                "parameters": [
                    {
                        "in": "query",
                        "name": "series",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only this TV show's seasons."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Season"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "tv_seasons_create",
                "description": "Adds a season to a TV show you may manage.",
                "summary": "Create a season",
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Season"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/seasons/{id}/": {
            "get": {
                "operationId": "tv_seasons_retrieve",
                "description": "One season.",
                "summary": "Get a season",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The season's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Season"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "tv_seasons_update",
                "description": "Saves every field of a season.",
                "summary": "Replace a season",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The season's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SeasonRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Season"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "tv_seasons_partial_update",
                "description": "Saves only the fields sent.",
                "summary": "Update a season",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The season's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeasonRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeasonRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeasonRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Season"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "tv_seasons_destroy",
                "description": "Deletes the season with its episodes, and their files from every server in the background.",
                "summary": "Delete a season",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The season's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/series/": {
            "get": {
                "operationId": "tv_series_list",
                "description": "The TV shows you may manage, a page at a time, with how many seasons, episodes and playable episodes each has. Resellers see only the TV shows they added.",
                "summary": "List TV shows",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only TV shows in this category."
                    },
                    {
                        "in": "query",
                        "name": "has_tmdb",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only TV shows matched on TMDB."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only active, or only inactive, TV shows."
                    },
                    {
                        "name": "ordering",
                        "required": false,
                        "in": "query",
                        "description": "Which field to use when ordering the results.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedSeriesList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "tv_series_create",
                "description": "Adds a TV show. Fill its seasons and episodes from TMDB (…/tmdb-sync/) or from files (…/import/plan/, then …/import/).",
                "summary": "Create a TV show",
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Series"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/series/{id}/": {
            "get": {
                "operationId": "tv_series_retrieve",
                "description": "One TV show, with its counts.",
                "summary": "Get a TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Series"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "tv_series_update",
                "description": "Saves every field of a TV show.",
                "summary": "Replace a TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/SeriesRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Series"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "tv_series_partial_update",
                "description": "Saves only the fields sent.",
                "summary": "Update a TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeriesRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeriesRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedSeriesRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Series"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "tv_series_destroy",
                "description": "Deletes the TV show with its seasons and episodes, and their files from every server in the background.",
                "summary": "Delete a TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No response body"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/tv/series/{id}/import/": {
            "post": {
                "operationId": "tv_series_import_create",
                "description": "Creates the episodes of a reviewed list (`items`) and gives each its file, in the background. `delivery` is how the files reach viewers: `adopt` for a `node` source; `download`, `proxy` or `redirect` for `s3` and `url`; `upload` for `upload`. Answers 202 with the import, to follow on GET /tv/imports/{id}/.",
                "summary": "Import files into a TV show",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportApplyRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportApplyRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportApplyRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SeriesImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/series/{id}/import/plan/": {
            "post": {
                "operationId": "tv_series_import_plan_create",
                "description": "Lists the files at a source and says which season and episode each looks like; nothing is created. `source`: `node` (`server` and a `path` in its incoming folder), `s3` (`storage` and a `path` prefix), `url` (`urls`, one link per line) or `upload` (`files`: `[{name, size}]`). Send the reviewed list to …/import/.",
                "summary": "Match files to a TV show's episodes",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportPlanRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportPlanRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/ImportPlanRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ImportPlan"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "description": "The server or the bucket could not be read."
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/series/{id}/imports/": {
            "get": {
                "operationId": "tv_series_imports_retrieve",
                "description": "The TV show's latest 20 imports, newest first, without their lists of files. Not paged.",
                "summary": "List a TV show's imports",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/SeriesImport"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/tv/series/{id}/tmdb-sync/": {
            "post": {
                "operationId": "tv_series_tmdb_sync_create",
                "description": "Creates or updates every season and episode of the show from TMDB, each with its own details, in the background. `seasons` limits it to some season numbers; `include_specials` adds season 0. Answers 202 with the import, to follow on GET /tv/imports/{id}/. 400 when the show has no TMDB id or no TMDB key is set.",
                "summary": "Fill a TV show from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The TV show's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TmdbSyncRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/TmdbSyncRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/TmdbSyncRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SeriesImport"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/tv/series/summary/": {
            "get": {
                "operationId": "tv_series_summary_retrieve",
                "description": "Counters over every TV show the list's filters select, and their episodes.",
                "summary": "Count TV shows",
                "parameters": [
                    {
                        "in": "query",
                        "name": "category",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Only TV shows in this category."
                    },
                    {
                        "in": "query",
                        "name": "has_tmdb",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only TV shows matched on TMDB."
                    },
                    {
                        "in": "query",
                        "name": "is_active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only active, or only inactive, TV shows."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TvShowCounts"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/tv/series/tmdb/detail/{tmdb_id}/": {
            "get": {
                "operationId": "tv_series_tmdb_detail_retrieve",
                "description": "Everything the TV show form can fill in from one TMDB show, with an outline of its seasons.",
                "summary": "Get a TV show's details from TMDB",
                "parameters": [
                    {
                        "in": "path",
                        "name": "tmdb_id",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The TMDB id, e.g. 603.",
                        "required": true
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbTvShow"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/tv/series/tmdb/search/": {
            "get": {
                "operationId": "tv_series_tmdb_search_retrieve",
                "description": "TV shows on TMDB whose title matches `query` (and `year`, if given), best first. Answers 400 with `configured: false` when no TMDB key is set (Settings → VOD).",
                "summary": "Search TMDB for a TV show",
                "parameters": [
                    {
                        "in": "query",
                        "name": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "The title to look for.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "year",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Only titles of this year."
                    }
                ],
                "tags": [
                    "TV shows"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbSearch"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbProblem"
                                }
                            }
                        },
                        "description": "No `query`, no TMDB key set, or TMDB did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/browse/": {
            "get": {
                "operationId": "vod_browse_retrieve",
                "description": "One folder of a server's incoming folder, to pick a file a movie or an episode uses as it is (…/adopt-file/). Panel operators only.",
                "summary": "Browse a server's incoming folder",
                "parameters": [
                    {
                        "in": "query",
                        "name": "path",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Relative to the incoming folder; empty for its top."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Video files"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "description": "The server could not be reached."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/jobs/": {
            "get": {
                "operationId": "vod_jobs_list",
                "description": "Every file transfer of movies and episodes (downloads, uploads, copies between servers), newest first, a page at a time. Panel operators only.",
                "summary": "List file transfers",
                "parameters": [
                    {
                        "in": "query",
                        "name": "active",
                        "schema": {
                            "type": "boolean"
                        },
                        "description": "Only transfers queued or running."
                    },
                    {
                        "in": "query",
                        "name": "ordering",
                        "schema": {
                            "type": "string"
                        },
                        "description": "`title_name`, `method`, `server_name`, `state`, `progress_pct` or `started_at`; `-` in front for descending."
                    },
                    {
                        "name": "page",
                        "required": false,
                        "in": "query",
                        "description": "A page number within the paginated result set.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page_size",
                        "required": false,
                        "in": "query",
                        "description": "Number of results to return per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the title or the file name."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A server's instance id."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "cancelled",
                                "failed",
                                "queued",
                                "running",
                                "succeeded"
                            ]
                        }
                    }
                ],
                "tags": [
                    "Video files"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedIngestJobList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/jobs/{job_id}/cancel/": {
            "post": {
                "operationId": "vod_jobs_cancel_create",
                "description": "Stops waiting on a transfer that is not going to finish.",
                "summary": "Cancel a file transfer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "job_id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The transfer's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Video files"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/IngestJob"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/jobs/{job_id}/retry/": {
            "post": {
                "operationId": "vod_jobs_retry_create",
                "description": "Starts a failed transfer over. Answers 202 with the new transfer.",
                "summary": "Retry a file transfer",
                "parameters": [
                    {
                        "in": "path",
                        "name": "job_id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The transfer's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Video files"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/IngestJob"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/scan/": {
            "get": {
                "operationId": "vod_scan_retrieve",
                "description": "Every file waiting in a server's incoming folder, ready to be given to a movie or an episode. Panel operators only.",
                "summary": "List files in a server's incoming folder",
                "parameters": [
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The server.",
                        "required": true
                    }
                ],
                "tags": [
                    "Video files"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerFiles"
                                }
                            }
                        },
                        "description": ""
                    },
                    "502": {
                        "description": "The server could not be reached."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/": {
            "get": {
                "operationId": "vod_watch_folders_list",
                "description": "Every watch folder, with its files counted by state, its last scan and why that scan failed, if it did. Not paged. Panel operators only.",
                "summary": "List watch folders",
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/WatchFolder"
                                    }
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            },
            "post": {
                "operationId": "vod_watch_folders_create",
                "description": "Saves a folder whose new files are added on their own; a folder that is on starts its first scan at once. The folder must exist and must not overlap another watch folder. Panel operators only.",
                "summary": "Create a watch folder",
                "tags": [
                    "Watch folders"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "201": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/{id}/": {
            "get": {
                "operationId": "vod_watch_folders_retrieve",
                "description": "One watch folder. Panel operators only.",
                "summary": "Get a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            },
            "put": {
                "operationId": "vod_watch_folders_update",
                "description": "Saves every setting of a watch folder. A new place, or a change to what it takes, reads the folder again. Panel operators only.",
                "summary": "Replace a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/WatchFolderRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "patch": {
                "operationId": "vod_watch_folders_partial_update",
                "description": "Saves only the settings sent. A new place, or a change to what it takes, reads the folder again. Panel operators only.",
                "summary": "Update a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedWatchFolderRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedWatchFolderRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/PatchedWatchFolderRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            },
            "delete": {
                "operationId": "vod_watch_folders_destroy",
                "description": "Stops watching the folder. The movies and TV shows it brought in stay, and its files stay where they are. Panel operators only.",
                "summary": "Delete a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderStopped"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "manage"
            }
        },
        "/vod/watch-folders/{id}/categories/": {
            "get": {
                "operationId": "vod_watch_folders_categories_retrieve",
                "description": "What \"My own mapping\" maps for a `kind`: the folder names the watch folder has seen, with their file counts, and TMDB's genres.",
                "summary": "Get a watch folder's names to map",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "movie",
                                "series"
                            ]
                        },
                        "description": "`movie` by default."
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderMappingChoices"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/{id}/files/": {
            "get": {
                "operationId": "vod_watch_folders_files_retrieve",
                "description": "What the folder found, newest first, 50 a page.",
                "summary": "List a watch folder's files",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "episode",
                                "movie"
                            ]
                        }
                    },
                    {
                        "in": "query",
                        "name": "page",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "in": "query",
                        "name": "page_size",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "At most 200."
                    },
                    {
                        "in": "query",
                        "name": "search",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Matches the name or the path."
                    },
                    {
                        "in": "query",
                        "name": "state",
                        "schema": {
                            "type": "string"
                        },
                        "description": "A file state, `needs_you` (not found on TMDB, or failed), `in_panel`, `no_details` or `missing`; several with commas."
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaginatedWatchFileList"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/{id}/files/{file_id}/match/": {
            "post": {
                "operationId": "vod_watch_folders_files_match_create",
                "description": "`tmdb_id`: as that TMDB movie, or an episode of that TMDB show. `as_is: true`: under its file name. `kind` (`movie` or `episode`) when it is not what it looks like. For a file already in the panel without TMDB details, `tmdb_id` fills them in. A file not read yet, or already in the panel, is refused.",
                "summary": "Import a file of a watch folder now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "file_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The file's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MatchRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/MatchRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/MatchRequest"
                            }
                        }
                    }
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "Refused, with the reason in `detail`."
                    },
                    "502": {
                        "description": "TMDB or the server did not answer."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/{id}/files/{file_id}/retry/": {
            "post": {
                "operationId": "vod_watch_folders_files_retry_create",
                "description": "A file that failed goes back to new, and a scan starts.",
                "summary": "Retry a file of a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "file_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The file's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "Refused, with the reason in `detail`."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/{id}/files/{file_id}/skip/": {
            "post": {
                "operationId": "vod_watch_folders_files_skip_create",
                "description": "The file is never imported, at this scan or any later one.",
                "summary": "Leave a file of a watch folder out",
                "parameters": [
                    {
                        "in": "path",
                        "name": "file_id",
                        "schema": {
                            "type": "integer"
                        },
                        "description": "The file's id.",
                        "required": true
                    },
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFile"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "Refused, with the reason in `detail`."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/{id}/files/bulk/": {
            "post": {
                "operationId": "vod_watch_folders_files_bulk_create",
                "description": "`action` (`as_is`, `retry` or `skip`) on the files picked by `ids`, or on every file in a `state`.",
                "summary": "Act on many files of a watch folder",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BulkRequest"
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "$ref": "#/components/schemas/BulkRequest"
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/BulkRequest"
                            }
                        }
                    },
                    "required": true
                },
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderBulkResult"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/{id}/scan/": {
            "post": {
                "operationId": "vod_watch_folders_scan_create",
                "description": "Starts a scan, or answers the one already queued or running (202).",
                "summary": "Scan a watch folder now",
                "parameters": [
                    {
                        "in": "path",
                        "name": "id",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The watch folder's id.",
                        "required": true
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "202": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderScanStarted"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "$ref": "#/components/responses/Invalid"
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    },
                    "404": {
                        "$ref": "#/components/responses/Notfound"
                    }
                },
                "x-scope": "write"
            }
        },
        "/vod/watch-folders/browse/": {
            "get": {
                "operationId": "vod_watch_folders_browse_retrieve",
                "description": "One folder of a server: in its incoming folder (`root: incoming`, `path` relative to it) or its media folders (`root: media`; `path` empty lists them). Buckets are browsed under Settings → Storage.",
                "summary": "Browse a server's folders",
                "parameters": [
                    {
                        "in": "query",
                        "name": "path",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "in": "query",
                        "name": "root",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "incoming",
                                "media"
                            ]
                        },
                        "description": "`incoming` by default."
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "A server that keeps movies and episodes.",
                        "required": true
                    },
                    {
                        "in": "query",
                        "name": "source",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "node"
                            ]
                        },
                        "description": "Only `node` (a server)."
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ServerFolder"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "description": "Refused, with the reason in `detail`."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/defaults/": {
            "get": {
                "operationId": "vod_watch_folders_defaults_retrieve",
                "description": "The bouquets suggested for its movies and its TV shows: the biggest ones, never one for adults.",
                "summary": "Get what a new watch folder starts with",
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderDefaults"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/genres/": {
            "get": {
                "operationId": "vod_watch_folders_genres_retrieve",
                "description": "The genres a new folder's \"My own mapping\" maps, for movies and TV shows.",
                "summary": "List TMDB's genres",
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TmdbGenres"
                                }
                            }
                        },
                        "description": ""
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        },
        "/vod/watch-folders/preview/": {
            "get": {
                "operationId": "vod_watch_folders_preview_retrieve",
                "description": "What a scan would find in a folder: counts, and up to 8 files and how they are read. It stops at 20,000 files or about 15 seconds. A problem comes back on the field it is about, e.g. `{\"path\": \"…\"}`.",
                "summary": "Preview a folder before saving it",
                "parameters": [
                    {
                        "in": "query",
                        "name": "extensions",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    },
                    {
                        "in": "query",
                        "name": "folder",
                        "schema": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true
                        }
                    },
                    {
                        "in": "query",
                        "name": "kind",
                        "schema": {
                            "enum": [
                                "movies",
                                "series",
                                "both",
                                ""
                            ],
                            "type": "string"
                        },
                        "description": "* `movies` - Movies\n* `series` - TV shows\n* `both` - Movies and TV shows"
                    },
                    {
                        "in": "query",
                        "name": "path",
                        "schema": {
                            "type": "string",
                            "maxLength": 1000
                        }
                    },
                    {
                        "in": "query",
                        "name": "root",
                        "schema": {
                            "enum": [
                                "incoming",
                                "media",
                                ""
                            ],
                            "type": "string"
                        },
                        "description": "* `incoming` - Incoming folder\n* `media` - Media folder"
                    },
                    {
                        "in": "query",
                        "name": "server",
                        "schema": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true
                        }
                    },
                    {
                        "in": "query",
                        "name": "source",
                        "schema": {
                            "enum": [
                                "node",
                                "s3"
                            ],
                            "type": "string",
                            "default": "node",
                            "minLength": 1
                        },
                        "description": "* `node` - A server\n* `s3` - A bucket"
                    },
                    {
                        "in": "query",
                        "name": "storage",
                        "schema": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true
                        }
                    }
                ],
                "tags": [
                    "Watch folders"
                ],
                "security": [
                    {
                        "apiKey": []
                    }
                ],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WatchFolderPreview"
                                }
                            }
                        },
                        "description": ""
                    },
                    "400": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {}
                                }
                            }
                        },
                        "description": "`{field: problem}`."
                    },
                    "401": {
                        "$ref": "#/components/responses/Notsignedin"
                    },
                    "403": {
                        "$ref": "#/components/responses/Notallowed"
                    },
                    "429": {
                        "$ref": "#/components/responses/Toomanyrequests"
                    }
                },
                "x-scope": "read"
            }
        }
    },
    "components": {
        "schemas": {
            "Account": {
                "type": "object",
                "description": "A reseller's credits: balance, spending this month and cheapest package price.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "username": {
                        "type": "string"
                    },
                    "group": {
                        "type": "string",
                        "nullable": true
                    },
                    "parent": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditAccountRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "unlimited": {
                        "type": "boolean"
                    },
                    "spent_this_month": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "last_entry_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "cheapest_price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true
                    },
                    "low": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "is_active": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "balance",
                    "cheapest_price",
                    "group",
                    "id",
                    "is_active",
                    "last_entry_at",
                    "low",
                    "parent",
                    "spent_this_month",
                    "unlimited",
                    "username"
                ]
            },
            "ActionsEnum": {
                "enum": [
                    "cancel",
                    "resume",
                    "retry",
                    "undo"
                ],
                "type": "string",
                "description": "* `cancel` - cancel\n* `resume` - resume\n* `retry` - retry\n* `undo` - undo"
            },
            "ActivityClearRequest": {
                "type": "object",
                "properties": {
                    "older_than_days": {
                        "type": "integer",
                        "minimum": 0,
                        "default": 0
                    }
                }
            },
            "ActivityCleared": {
                "type": "object",
                "properties": {
                    "deleted": {
                        "type": "integer"
                    }
                },
                "required": [
                    "deleted"
                ]
            },
            "ActivityLog": {
                "type": "object",
                "description": "One connection that ended: as a live connection, with when it ended\nand how long it lasted.",
                "properties": {
                    "session_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "line": {
                        "type": "string",
                        "readOnly": true
                    },
                    "line_id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "owner": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Username of the account that created the line; empty when none did."
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true,
                        "description": "That account's groups, e.g. Reseller."
                    },
                    "stream_name": {
                        "type": "string",
                        "title": "Stream Name",
                        "readOnly": true
                    },
                    "kind": {
                        "type": "string",
                        "readOnly": true
                    },
                    "title": {
                        "type": "string",
                        "readOnly": true
                    },
                    "server": {
                        "type": "string",
                        "readOnly": true,
                        "nullable": true,
                        "description": "The server the viewer was sent to."
                    },
                    "ip": {
                        "type": "string",
                        "readOnly": true
                    },
                    "player": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "country_code": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "isp": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "city": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "output": {
                        "type": "string",
                        "readOnly": true
                    },
                    "restreamer": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "restreamer_reasons": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "datacenter": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "vpn": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "tor": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "last_heartbeat": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "ended_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "duration_seconds": {
                        "type": "integer",
                        "nullable": true,
                        "readOnly": true
                    }
                },
                "required": [
                    "city",
                    "country_code",
                    "datacenter",
                    "duration_seconds",
                    "groups",
                    "ip",
                    "isp",
                    "kind",
                    "last_heartbeat",
                    "line",
                    "line_id",
                    "output",
                    "owner",
                    "player",
                    "restreamer",
                    "restreamer_reasons",
                    "server",
                    "session_id",
                    "started_at",
                    "stream_name",
                    "title",
                    "tor",
                    "vpn"
                ]
            },
            "ActivityRetention": {
                "type": "object",
                "properties": {
                    "retention_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "description": "0: kept for good."
                    }
                },
                "required": [
                    "retention_days"
                ]
            },
            "ActivityRetentionRequest": {
                "type": "object",
                "properties": {
                    "retention_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "description": "0: kept for good."
                    }
                },
                "required": [
                    "retention_days"
                ]
            },
            "AddressRuleEnum": {
                "enum": [
                    "turns",
                    "least_busy",
                    "same_viewer",
                    "random"
                ],
                "type": "string",
                "description": "* `turns` - Take turns\n* `least_busy` - Least busy\n* `same_viewer` - Same address per viewer\n* `random` - At random"
            },
            "AdoptFileRequest": {
                "type": "object",
                "description": "Attach a file already sitting on a node to a title.\n\nThe cheapest of the ingest paths and the one that needs no transfer\nat all: an operator who has already copied a file onto the node\n(scp/rsync, or a mounted library) points the catalogue at it. The\nnode confirms the file exists and reports its real size and tracks;\nthe panel never takes the client's word for any of that.",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Node that holds the file."
                    },
                    "path": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Path relative to the node's VOD_DIR scan directory.",
                        "maxLength": 512
                    }
                },
                "required": [
                    "path",
                    "server"
                ]
            },
            "AssignGroupsRequestDocRequest": {
                "type": "object",
                "properties": {
                    "group_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "group_ids"
                ]
            },
            "AssignPackageRequestDocRequest": {
                "type": "object",
                "properties": {
                    "line_user_id": {
                        "type": "string",
                        "format": "uuid"
                    }
                },
                "required": [
                    "line_user_id"
                ]
            },
            "AssignPermissionsRequestDocRequest": {
                "type": "object",
                "properties": {
                    "permission_codenames": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    }
                },
                "required": [
                    "permission_codenames"
                ]
            },
            "AssignPermissionsToGroupResponseDoc": {
                "type": "object",
                "properties": {
                    "message": {
                        "type": "string"
                    },
                    "group": {
                        "$ref": "#/components/schemas/Group"
                    },
                    "assigned_permissions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "not_assigned": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "assigned_permissions",
                    "group",
                    "message",
                    "not_assigned"
                ]
            },
            "AssignUserToGroupsResponseDoc": {
                "type": "object",
                "properties": {
                    "message": {
                        "type": "string"
                    },
                    "user": {
                        "$ref": "#/components/schemas/User"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "groups",
                    "message",
                    "user"
                ]
            },
            "AssignableGroup": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "is_reseller": {
                        "type": "boolean"
                    },
                    "required": {
                        "type": "boolean",
                        "description": "The account must be in it: leave it ticked."
                    }
                },
                "required": [
                    "id",
                    "is_reseller",
                    "name",
                    "required"
                ]
            },
            "AttributesEnum": {
                "enum": [
                    "category",
                    "logo",
                    "epg_id",
                    "epg_shift",
                    "number"
                ],
                "type": "string",
                "description": "* `category` - category\n* `logo` - logo\n* `epg_id` - epg_id\n* `epg_shift` - epg_shift\n* `number` - number"
            },
            "AudioCodecEnum": {
                "enum": [
                    "aac",
                    "mp3",
                    "copy"
                ],
                "type": "string",
                "description": "* `aac` - AAC\n* `mp3` - MP3\n* `copy` - Copy (no re-encode)"
            },
            "AudioTrack": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "index": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Track Index",
                        "description": "Position within the stored container, 0-based."
                    },
                    "language": {
                        "type": "string",
                        "readOnly": true,
                        "description": "ISO 639-2 code as tagged in the container (eng, fra, ara). Empty when the source carried no tag."
                    },
                    "title": {
                        "type": "string",
                        "readOnly": true
                    },
                    "codec": {
                        "type": "string",
                        "readOnly": true
                    },
                    "channels": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "is_default": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Default Track"
                    }
                },
                "required": [
                    "channels",
                    "codec",
                    "id",
                    "index",
                    "is_default",
                    "language",
                    "title"
                ]
            },
            "AutoOrClearEnum": {
                "enum": [
                    "auto",
                    "clear"
                ],
                "type": "string",
                "description": "* `auto` - auto\n* `clear` - clear"
            },
            "AvailablePermissionsResponseDoc": {
                "type": "object",
                "properties": {
                    "permissions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Permission"
                        }
                    },
                    "total_count": {
                        "type": "integer"
                    }
                },
                "required": [
                    "permissions",
                    "total_count"
                ]
            },
            "BackgroundTask": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackgroundTaskKindEnum"
                    },
                    "kind_label": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "subtitle": {
                        "type": "string"
                    },
                    "state": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackgroundTaskStateEnum"
                            }
                        ],
                        "description": "Where the task is, in the same words for every kind.\n\n* `queued` - Queued\n* `running` - Running\n* `waiting` - Waiting for you\n* `stalled` - Stalled\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
                    },
                    "state_label": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "description": "The task's own status, in its kind's words."
                    },
                    "status_label": {
                        "type": "string"
                    },
                    "progress": {
                        "$ref": "#/components/schemas/BackgroundTaskProgress"
                    },
                    "message": {
                        "type": "string"
                    },
                    "details": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackgroundTaskDetail"
                        }
                    },
                    "errors": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        },
                        "description": "What went wrong for single items, when the kind records it."
                    },
                    "link": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackgroundTaskLink"
                            }
                        ],
                        "nullable": true
                    },
                    "actions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ActionsEnum"
                        },
                        "description": "What the signed-in account may do to it now."
                    },
                    "created_by_username": {
                        "type": "string",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "actions",
                    "created_at",
                    "created_by_username",
                    "details",
                    "errors",
                    "finished_at",
                    "id",
                    "kind",
                    "kind_label",
                    "link",
                    "message",
                    "progress",
                    "started_at",
                    "state",
                    "state_label",
                    "status",
                    "status_label",
                    "subtitle",
                    "title",
                    "updated_at"
                ]
            },
            "BackgroundTaskChoice": {
                "type": "object",
                "properties": {
                    "value": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    }
                },
                "required": [
                    "label",
                    "value"
                ]
            },
            "BackgroundTaskDetail": {
                "type": "object",
                "properties": {
                    "label": {
                        "type": "string"
                    },
                    "value": {}
                },
                "required": [
                    "label",
                    "value"
                ]
            },
            "BackgroundTaskKindEnum": {
                "enum": [
                    "import",
                    "bulk_delete",
                    "bulk_edit",
                    "ingest",
                    "series_import",
                    "provider_import",
                    "watch_scan",
                    "backup",
                    "panel_import",
                    "editor"
                ],
                "type": "string",
                "description": "* `import` - Playlist import\n* `bulk_delete` - Mass delete\n* `bulk_edit` - Mass edit\n* `ingest` - VOD ingest\n* `series_import` - TV show import\n* `provider_import` - Film and show import\n* `watch_scan` - Watch folder scan\n* `backup` - Backup\n* `panel_import` - Move from another panel\n* `editor` - Playlist editor"
            },
            "BackgroundTaskLink": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "The dashboard page that shows this task."
                    },
                    "query": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "label": {
                        "type": "string"
                    }
                },
                "required": [
                    "label",
                    "path",
                    "query"
                ]
            },
            "BackgroundTaskOptions": {
                "type": "object",
                "properties": {
                    "kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackgroundTaskChoice"
                        }
                    },
                    "states": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackgroundTaskChoice"
                        }
                    },
                    "active_states": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "active_states",
                    "kinds",
                    "states"
                ]
            },
            "BackgroundTaskProgress": {
                "type": "object",
                "properties": {
                    "done": {
                        "type": "integer",
                        "nullable": true
                    },
                    "total": {
                        "type": "integer",
                        "nullable": true
                    },
                    "percent": {
                        "type": "integer",
                        "nullable": true
                    },
                    "phase": {
                        "type": "string"
                    }
                },
                "required": [
                    "done",
                    "percent",
                    "phase",
                    "total"
                ]
            },
            "BackgroundTaskStateEnum": {
                "enum": [
                    "queued",
                    "running",
                    "waiting",
                    "stalled",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `queued` - Queued\n* `running` - Running\n* `waiting` - Waiting for you\n* `stalled` - Stalled\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "BackgroundTaskSummary": {
                "type": "object",
                "properties": {
                    "active": {
                        "type": "integer",
                        "description": "Queued and running tasks."
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        },
                        "description": "Tasks per state."
                    },
                    "active_by_kind": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        },
                        "description": "Active tasks per kind."
                    },
                    "failed_24h": {
                        "type": "integer"
                    }
                },
                "required": [
                    "active",
                    "active_by_kind",
                    "counts",
                    "failed_24h"
                ]
            },
            "Backup": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "plan": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "plan_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "trigger": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupTriggerEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "trigger_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "scope": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScopeEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "components": {
                        "readOnly": true,
                        "description": "The component keys this backup holds."
                    },
                    "component_labels": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "contents_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "encrypted": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "compression": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "status_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "phase": {
                        "type": "string",
                        "readOnly": true
                    },
                    "bytes_done": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "message": {
                        "type": "string",
                        "readOnly": true
                    },
                    "filename": {
                        "type": "string",
                        "readOnly": true
                    },
                    "size_bytes": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "sha256": {
                        "type": "string",
                        "readOnly": true
                    },
                    "copies": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupCopy"
                        },
                        "readOnly": true
                    },
                    "deleted_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "deleted_reason": {
                        "type": "string",
                        "readOnly": true
                    },
                    "can_download": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    }
                },
                "required": [
                    "bytes_done",
                    "can_download",
                    "component_labels",
                    "components",
                    "compression",
                    "contents_label",
                    "copies",
                    "created_at",
                    "created_by_username",
                    "deleted_at",
                    "deleted_reason",
                    "encrypted",
                    "filename",
                    "finished_at",
                    "id",
                    "message",
                    "phase",
                    "plan",
                    "plan_name",
                    "scope",
                    "sha256",
                    "size_bytes",
                    "started_at",
                    "status",
                    "status_label",
                    "trigger",
                    "trigger_label",
                    "updated_at"
                ]
            },
            "BackupChoice": {
                "type": "object",
                "properties": {
                    "value": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    }
                },
                "required": [
                    "label",
                    "value"
                ]
            },
            "BackupCopy": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "destination": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "destination_name": {
                        "type": "string",
                        "maxLength": 100
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackupStorageKindEnum"
                    },
                    "kind_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "location": {
                        "type": "string",
                        "description": "File path on this server, or object key.",
                        "maxLength": 1024
                    },
                    "status": {
                        "$ref": "#/components/schemas/BackupCopyStatusEnum"
                    },
                    "status_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "message": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "stored_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "required": [
                    "destination_name",
                    "id",
                    "kind",
                    "kind_label",
                    "status_label"
                ]
            },
            "BackupCopyStatusEnum": {
                "enum": [
                    "pending",
                    "storing",
                    "stored",
                    "failed",
                    "deleted"
                ],
                "type": "string",
                "description": "* `pending` - Waiting\n* `storing` - Copying\n* `stored` - Stored\n* `failed` - Failed\n* `deleted` - Deleted"
            },
            "BackupDestination": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 100
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackupStorageKindEnum"
                    },
                    "folder": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Bucket"
                    },
                    "storage_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "is_default": {
                        "type": "boolean",
                        "title": "Preselected",
                        "description": "Ticked when a backup is started by hand."
                    },
                    "location": {
                        "type": "string",
                        "readOnly": true
                    },
                    "schedules": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "last_checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_check_ok": {
                        "type": "boolean",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_check_message": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "id",
                    "kind",
                    "last_check_message",
                    "last_check_ok",
                    "last_checked_at",
                    "location",
                    "name",
                    "schedules",
                    "storage_name",
                    "updated_at"
                ]
            },
            "BackupDestinationRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackupStorageKindEnum"
                    },
                    "folder": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Bucket"
                    },
                    "is_default": {
                        "type": "boolean",
                        "title": "Preselected",
                        "description": "Ticked when a backup is started by hand."
                    }
                },
                "required": [
                    "kind",
                    "name"
                ]
            },
            "BackupDownloadLink": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "expires_in": {
                        "type": "integer",
                        "description": "Seconds the link stays valid."
                    }
                },
                "required": [
                    "expires_in",
                    "url"
                ]
            },
            "BackupHealth": {
                "type": "object",
                "properties": {
                    "last_success_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "last_success_size": {
                        "type": "integer",
                        "nullable": true
                    },
                    "last_failure_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "next_run_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "next_plan": {
                        "type": "string",
                        "nullable": true,
                        "description": "The schedule that runs next."
                    },
                    "running": {
                        "type": "boolean"
                    },
                    "warning": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "required": [
                    "last_failure_at",
                    "last_success_at",
                    "last_success_size",
                    "next_plan",
                    "next_run_at",
                    "running",
                    "warning"
                ]
            },
            "BackupImport": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "filename": {
                        "type": "string"
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "received": {
                        "type": "integer",
                        "description": "Bytes uploaded so far."
                    },
                    "status": {
                        "$ref": "#/components/schemas/BackupImportStatusEnum"
                    },
                    "phase": {
                        "type": "string"
                    },
                    "message": {
                        "type": "string"
                    },
                    "created_by": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string"
                    },
                    "updated_at": {
                        "type": "string"
                    },
                    "encrypted": {
                        "type": "boolean"
                    },
                    "archive": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupImportArchive"
                            }
                        ],
                        "description": "What the file holds; empty until it is checked."
                    },
                    "options": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "What the restore was asked to do."
                    },
                    "outcome": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "What the restore did, once it has finished."
                    },
                    "chunk_bytes": {
                        "type": "integer",
                        "description": "Only when the upload starts: send the file in pieces of at most this size."
                    },
                    "expected_offset": {
                        "type": "integer",
                        "description": "Only when a piece was not written: send again from this byte."
                    },
                    "admins": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupImportAdmins"
                            }
                        ],
                        "description": "Only after a check: the file's administrators against this panel's."
                    }
                },
                "required": [
                    "archive",
                    "created_at",
                    "created_by",
                    "filename",
                    "id",
                    "message",
                    "options",
                    "outcome",
                    "phase",
                    "received",
                    "size_bytes",
                    "status",
                    "updated_at"
                ]
            },
            "BackupImportAdmins": {
                "type": "object",
                "properties": {
                    "known": {
                        "type": "boolean",
                        "description": "False for older backups that do not record their administrators."
                    },
                    "theirs": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "mine": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "only_theirs": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "only_mine": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "differ": {
                        "type": "boolean"
                    },
                    "none_in_backup": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "differ",
                    "known",
                    "mine",
                    "none_in_backup",
                    "only_mine",
                    "only_theirs",
                    "theirs"
                ]
            },
            "BackupImportArchive": {
                "type": "object",
                "properties": {
                    "created_at": {
                        "type": "string"
                    },
                    "scope": {
                        "type": "string"
                    },
                    "contents_label": {
                        "type": "string"
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        },
                        "description": "`{key, label, kind}` for each part the file holds."
                    },
                    "files": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "database": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "panel_image": {
                        "type": "string"
                    },
                    "admins": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        },
                        "description": "`{username, is_active}` of the administrators in the file."
                    },
                    "admins_known": {
                        "type": "boolean"
                    },
                    "accounts": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "problem": {
                        "type": "string",
                        "nullable": true,
                        "description": "Why this file cannot be restored here, if it cannot."
                    }
                }
            },
            "BackupImportCheckRequest": {
                "type": "object",
                "properties": {
                    "passphrase": {
                        "type": "string",
                        "writeOnly": true
                    }
                }
            },
            "BackupImportRestoreRequest": {
                "type": "object",
                "description": "What to put back, and what to do about the administrators.",
                "properties": {
                    "whole": {
                        "type": "boolean",
                        "default": false
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ComponentsEnum"
                        }
                    },
                    "keys": {
                        "type": "boolean",
                        "default": false
                    },
                    "keep_admins": {
                        "type": "boolean",
                        "default": true
                    },
                    "passphrase": {
                        "type": "string",
                        "writeOnly": true
                    }
                }
            },
            "BackupImportStartRequest": {
                "type": "object",
                "description": "The backup file about to be uploaded.",
                "properties": {
                    "filename": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "size_bytes": {
                        "type": "integer",
                        "maximum": 17592186044416,
                        "minimum": 0,
                        "format": "int64"
                    }
                },
                "required": [
                    "filename",
                    "size_bytes"
                ]
            },
            "BackupImportStatusEnum": {
                "enum": [
                    "uploading",
                    "ready",
                    "restoring",
                    "completed",
                    "failed"
                ],
                "type": "string",
                "description": "* `uploading` - uploading\n* `ready` - ready\n* `restoring` - restoring\n* `completed` - completed\n* `failed` - failed"
            },
            "BackupOverview": {
                "type": "object",
                "properties": {
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupOverviewComponent"
                        }
                    },
                    "scopes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupChoice"
                        }
                    },
                    "frequencies": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupChoice"
                        }
                    },
                    "compressions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupChoice"
                        }
                    },
                    "destination_kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackupChoice"
                        }
                    },
                    "disk": {
                        "$ref": "#/components/schemas/BackupOverviewDisk"
                    },
                    "pg_dump": {
                        "type": "string",
                        "nullable": true,
                        "description": "The database dump tool's version, if installed."
                    },
                    "stored": {
                        "$ref": "#/components/schemas/BackupOverviewStored"
                    },
                    "health": {
                        "$ref": "#/components/schemas/BackupHealth"
                    },
                    "can": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupPermissions"
                            }
                        ],
                        "description": "What the signed-in account may do here."
                    }
                },
                "required": [
                    "can",
                    "components",
                    "compressions",
                    "destination_kinds",
                    "disk",
                    "frequencies",
                    "health",
                    "pg_dump",
                    "scopes",
                    "stored"
                ]
            },
            "BackupOverviewComponent": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "What `components` lists when you choose what to back up."
                    },
                    "label": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackupOverviewComponentKindEnum"
                    },
                    "kind_label": {
                        "type": "string"
                    },
                    "requires": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Other parts always backed up with this one."
                    },
                    "available": {
                        "type": "boolean"
                    },
                    "unavailable_reason": {
                        "type": "string"
                    },
                    "sensitive": {
                        "type": "boolean",
                        "description": "Holds passwords or keys."
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "rows": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Null when unknown, and for files."
                    }
                },
                "required": [
                    "available",
                    "description",
                    "key",
                    "kind",
                    "kind_label",
                    "label",
                    "requires",
                    "rows",
                    "sensitive",
                    "size_bytes",
                    "unavailable_reason"
                ]
            },
            "BackupOverviewComponentKindEnum": {
                "enum": [
                    "data",
                    "logs",
                    "files"
                ],
                "type": "string",
                "description": "* `data` - data\n* `logs` - logs\n* `files` - files"
            },
            "BackupOverviewDisk": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string"
                    },
                    "total_bytes": {
                        "type": "integer"
                    },
                    "free_bytes": {
                        "type": "integer"
                    },
                    "error": {
                        "type": "string",
                        "description": "Only when the folder cannot be read."
                    }
                },
                "required": [
                    "path"
                ]
            },
            "BackupOverviewStored": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "size_bytes": {
                        "type": "integer"
                    }
                },
                "required": [
                    "count",
                    "size_bytes"
                ]
            },
            "BackupPermissions": {
                "type": "object",
                "properties": {
                    "run": {
                        "type": "boolean"
                    },
                    "download": {
                        "type": "boolean"
                    },
                    "delete": {
                        "type": "boolean"
                    },
                    "manage_schedules": {
                        "type": "boolean"
                    },
                    "manage_storage": {
                        "type": "boolean"
                    },
                    "restore": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "delete",
                    "download",
                    "manage_schedules",
                    "manage_storage",
                    "restore",
                    "run"
                ]
            },
            "BackupPlan": {
                "type": "object",
                "description": "A backup schedule: what to back up, when, where, and how many backups to keep.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 100
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "scope": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScopeEnum"
                            }
                        ],
                        "title": "What to back up"
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ComponentsEnum"
                        }
                    },
                    "destinations": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "destination_names": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "frequency": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/FrequencyEnum"
                            }
                        ],
                        "title": "Runs"
                    },
                    "time_of_day": {
                        "type": "string",
                        "format": "time",
                        "title": "At",
                        "description": "Daily, weekly and monthly runs; for \"every few hours\" only the minute is used."
                    },
                    "every_hours": {
                        "type": "integer",
                        "maximum": 23,
                        "minimum": 1,
                        "title": "Every … hours"
                    },
                    "weekday": {
                        "type": "integer",
                        "maximum": 6,
                        "minimum": 0,
                        "title": "Day of the week",
                        "description": "0 is Monday."
                    },
                    "day_of_month": {
                        "type": "integer",
                        "maximum": 28,
                        "minimum": 1,
                        "title": "Day of the month",
                        "description": "1 to 28, so it exists in every month."
                    },
                    "timezone": {
                        "type": "string",
                        "title": "Time zone",
                        "maxLength": 64
                    },
                    "keep_last": {
                        "type": "integer",
                        "maximum": 10000,
                        "minimum": 0,
                        "title": "Keep the last",
                        "description": "Older backups of this schedule are deleted. 0 keeps all."
                    },
                    "keep_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "title": "Keep for (days)",
                        "description": "Backups older than this are deleted. 0 keeps them regardless of age."
                    },
                    "compression": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CompressionEnum"
                            }
                        ],
                        "minimum": 0,
                        "maximum": 32767
                    },
                    "encrypt": {
                        "type": "boolean"
                    },
                    "has_passphrase": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "next_run_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_run_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "schedule_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "contents_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "last_backup": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BackupScheduleLastBackup"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "contents_label",
                    "created_at",
                    "destination_names",
                    "destinations",
                    "has_passphrase",
                    "id",
                    "last_backup",
                    "last_run_at",
                    "name",
                    "next_run_at",
                    "schedule_label",
                    "updated_at"
                ]
            },
            "BackupPlanRequest": {
                "type": "object",
                "description": "A backup schedule: what to back up, when, where, and how many backups to keep.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "scope": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScopeEnum"
                            }
                        ],
                        "title": "What to back up"
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ComponentsEnum"
                        }
                    },
                    "destinations": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "frequency": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/FrequencyEnum"
                            }
                        ],
                        "title": "Runs"
                    },
                    "time_of_day": {
                        "type": "string",
                        "format": "time",
                        "title": "At",
                        "description": "Daily, weekly and monthly runs; for \"every few hours\" only the minute is used."
                    },
                    "every_hours": {
                        "type": "integer",
                        "maximum": 23,
                        "minimum": 1,
                        "title": "Every … hours"
                    },
                    "weekday": {
                        "type": "integer",
                        "maximum": 6,
                        "minimum": 0,
                        "title": "Day of the week",
                        "description": "0 is Monday."
                    },
                    "day_of_month": {
                        "type": "integer",
                        "maximum": 28,
                        "minimum": 1,
                        "title": "Day of the month",
                        "description": "1 to 28, so it exists in every month."
                    },
                    "timezone": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Time zone",
                        "maxLength": 64
                    },
                    "keep_last": {
                        "type": "integer",
                        "maximum": 10000,
                        "minimum": 0,
                        "title": "Keep the last",
                        "description": "Older backups of this schedule are deleted. 0 keeps all."
                    },
                    "keep_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "title": "Keep for (days)",
                        "description": "Backups older than this are deleted. 0 keeps them regardless of age."
                    },
                    "compression": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CompressionEnum"
                            }
                        ],
                        "minimum": 0,
                        "maximum": 32767
                    },
                    "encrypt": {
                        "type": "boolean"
                    },
                    "passphrase": {
                        "type": "string",
                        "writeOnly": true
                    }
                },
                "required": [
                    "destinations",
                    "name"
                ]
            },
            "BackupScheduleLastBackup": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string"
                    },
                    "status_label": {
                        "type": "string"
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "finished_at",
                    "id",
                    "message",
                    "size_bytes",
                    "status",
                    "status_label"
                ]
            },
            "BackupSchedulePreview": {
                "type": "object",
                "properties": {
                    "runs": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "description": "The next run times, at most three."
                    }
                },
                "required": [
                    "runs"
                ]
            },
            "BackupScheduleTimingRequest": {
                "type": "object",
                "description": "Only the fields that decide when a schedule runs.",
                "properties": {
                    "frequency": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/FrequencyEnum"
                            }
                        ],
                        "title": "Runs"
                    },
                    "time_of_day": {
                        "type": "string",
                        "format": "time",
                        "title": "At",
                        "description": "Daily, weekly and monthly runs; for \"every few hours\" only the minute is used."
                    },
                    "every_hours": {
                        "type": "integer",
                        "maximum": 23,
                        "minimum": 1,
                        "title": "Every … hours"
                    },
                    "weekday": {
                        "type": "integer",
                        "maximum": 6,
                        "minimum": 0,
                        "title": "Day of the week",
                        "description": "0 is Monday."
                    },
                    "day_of_month": {
                        "type": "integer",
                        "maximum": 28,
                        "minimum": 1,
                        "title": "Day of the month",
                        "description": "1 to 28, so it exists in every month."
                    },
                    "timezone": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Time zone",
                        "maxLength": 64
                    }
                }
            },
            "BackupStatusEnum": {
                "enum": [
                    "pending",
                    "running",
                    "uploading",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `pending` - Queued\n* `running` - Backing up\n* `uploading` - Copying to storage\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "BackupStorageCheck": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean"
                    },
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail",
                    "ok"
                ]
            },
            "BackupStorageKindEnum": {
                "enum": [
                    "local",
                    "s3"
                ],
                "type": "string",
                "description": "* `local` - This server\n* `s3` - Object storage"
            },
            "BackupTriggerEnum": {
                "enum": [
                    "manual",
                    "scheduled"
                ],
                "type": "string",
                "description": "* `manual` - Started by hand\n* `scheduled` - Scheduled"
            },
            "BlankEnum": {
                "enum": [
                    ""
                ]
            },
            "BlockAddressRequest": {
                "type": "object",
                "description": "An address to block: one address, a CIDR block or a range `a-b`.\nFor how long: `duration`, or `expires_at` (\"until a date\"), which wins.\n`replace`: change the block this very entry has already.",
                "properties": {
                    "address": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "reason": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "duration": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/DurationEnum"
                            }
                        ],
                        "default": "forever"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "replace": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "address"
                ]
            },
            "BlockedAddressAlready": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    },
                    "code": {
                        "type": "string"
                    },
                    "existing": {
                        "$ref": "#/components/schemas/BlockedIP"
                    }
                },
                "required": [
                    "code",
                    "detail",
                    "existing"
                ]
            },
            "BlockedAddressesAdded": {
                "type": "object",
                "properties": {
                    "blocks": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BlockedIP"
                        }
                    },
                    "sessions_ended": {
                        "type": "integer",
                        "description": "Connections ended from inside it."
                    }
                },
                "required": [
                    "blocks",
                    "sessions_ended"
                ]
            },
            "BlockedEnum": {
                "enum": [
                    "limit",
                    "min_balance"
                ],
                "type": "string",
                "description": "* `limit` - limit\n* `min_balance` - min_balance"
            },
            "BlockedIP": {
                "type": "object",
                "description": "A blocked address or block. `address` is how it is shown (a lone\naddress without /32 or /128, a block in CIDR form); `expires_at` null:\nfor good. `trigger` is what made the panel block it by itself (empty:\nblocked by hand) and `times` how often in a row; `ended`: it ran out\n(automatic blocks stay listed a week); `lifted_at` and\n`lifted_by_username`: someone removed it early.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "network": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Address, block or range",
                        "description": "One address (203.0.113.7/32), a block of them in CIDR form (198.51.100.0/24, 2001:db8::/48) or a range (198.51.100.10-198.51.100.20), as the panel normalised it."
                    },
                    "address": {
                        "type": "string",
                        "description": "How the panel shows it: a lone address without its /32 or /128,\na range with a dash.",
                        "readOnly": true
                    },
                    "reason": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Optional note shown in the admin / panel (e.g. \"abusive restreamer\")."
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Until",
                        "description": "Empty: blocked until removed. Past this moment the block no longer applies."
                    },
                    "trigger": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/BlockedIPTriggerEnum"
                            }
                        ],
                        "readOnly": true,
                        "title": "Blocked automatically for",
                        "description": "Empty: blocked by hand. Otherwise what the panel saw from this address (Settings → Security → Attack protection).\n\n* `signin` - Failed sign-ins\n* `guess` - Wrong passwords\n* `flood` - Too many requests"
                    },
                    "times": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Times blocked automatically",
                        "description": "How many times in a row it was blocked automatically. Each time it comes back within a day of its last block, the block lasts twice as long."
                    },
                    "ended": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "lifted_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "description": "An automatic block someone removed before its end: when. It stays listed a week, and the address is not blocked again for a short while."
                    },
                    "lifted_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "address",
                    "created_at",
                    "created_by_username",
                    "ended",
                    "expires_at",
                    "id",
                    "lifted_at",
                    "lifted_by_username",
                    "network",
                    "reason",
                    "times",
                    "trigger"
                ]
            },
            "BlockedIPTriggerEnum": {
                "enum": [
                    "signin",
                    "guess",
                    "flood"
                ],
                "type": "string",
                "description": "* `signin` - Failed sign-ins\n* `guess` - Wrong passwords\n* `flood` - Too many requests"
            },
            "Bouquet": {
                "type": "object",
                "description": "A bouquet's own fields, plus how much it holds.\n\nIts contents are not listed here: a bouquet can hold tens of thousands\nof streams, and this shape is also nested into every package. They are\nread and changed a page at a time through `bouquets/<id>/content/`.\n`streams` is still accepted on create and update, as a full replacement,\nfor API clients that build a bouquet in one call.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order (lowest first). Ties fall back to name."
                    },
                    "streams_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "movies_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "series_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "id",
                    "movies_count",
                    "name",
                    "series_count",
                    "streams_count",
                    "updated_at"
                ]
            },
            "BouquetContentChangeKindEnum": {
                "enum": [
                    "streams",
                    "movies",
                    "series"
                ],
                "type": "string",
                "description": "* `streams` - streams\n* `movies` - movies\n* `series` - series"
            },
            "BouquetContentChangeRequest": {
                "type": "object",
                "description": "Either `add` / `remove` (up to 1,000 ids each), or `match`: everything the same filters select.",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/BouquetContentChangeKindEnum"
                    },
                    "add": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000
                    },
                    "remove": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000
                    },
                    "match": {
                        "$ref": "#/components/schemas/BouquetContentMatchRequest"
                    }
                },
                "required": [
                    "kind"
                ]
            },
            "BouquetContentChanged": {
                "type": "object",
                "properties": {
                    "added": {
                        "type": "integer"
                    },
                    "removed": {
                        "type": "integer"
                    },
                    "streams_count": {
                        "type": "integer"
                    },
                    "movies_count": {
                        "type": "integer"
                    },
                    "series_count": {
                        "type": "integer"
                    }
                },
                "required": [
                    "added",
                    "movies_count",
                    "removed",
                    "series_count",
                    "streams_count"
                ]
            },
            "BouquetContentMatchActionEnum": {
                "enum": [
                    "add",
                    "remove"
                ],
                "type": "string",
                "description": "* `add` - add\n* `remove` - remove"
            },
            "BouquetContentMatchRequest": {
                "type": "object",
                "properties": {
                    "action": {
                        "$ref": "#/components/schemas/BouquetContentMatchActionEnum"
                    },
                    "search": {
                        "type": "string",
                        "description": "The same search as the list."
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Only this category."
                    }
                },
                "required": [
                    "action"
                ]
            },
            "BouquetContentRow": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "category_name": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "in_bouquet": {
                        "type": "boolean",
                        "description": "Whether the bouquet holds it."
                    },
                    "status": {
                        "type": "string",
                        "description": "Streams only."
                    },
                    "is_on_demand": {
                        "type": "boolean",
                        "description": "Streams only: starts when someone watches."
                    },
                    "year": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Movies and TV shows only."
                    }
                },
                "required": [
                    "category_name",
                    "id",
                    "in_bouquet",
                    "is_active",
                    "name"
                ]
            },
            "BouquetList": {
                "type": "object",
                "description": "A bouquet as the list shows it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "description": {
                        "type": "string",
                        "readOnly": true,
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "order": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Display order (lowest first). Ties fall back to name."
                    },
                    "streams_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "movies_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "series_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "description",
                    "id",
                    "is_active",
                    "movies_count",
                    "name",
                    "order",
                    "series_count",
                    "streams_count",
                    "updated_at"
                ]
            },
            "BouquetReorderRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "One page's bouquet ids, in their new order."
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "BouquetReordered": {
                "type": "object",
                "properties": {
                    "updated": {
                        "type": "integer",
                        "description": "How many bouquets moved."
                    }
                },
                "required": [
                    "updated"
                ]
            },
            "BouquetRequest": {
                "type": "object",
                "description": "A bouquet's own fields, plus how much it holds.\n\nIts contents are not listed here: a bouquet can hold tens of thousands\nof streams, and this shape is also nested into every package. They are\nread and changed a page at a time through `bouquets/<id>/content/`.\n`streams` is still accepted on create and update, as a full replacement,\nfor API clients that build a bouquet in one call.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order (lowest first). Ties fall back to name."
                    },
                    "streams": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid",
                            "writeOnly": true
                        },
                        "writeOnly": true
                    }
                },
                "required": [
                    "name"
                ]
            },
            "BulkActionEnum": {
                "enum": [
                    "as_is",
                    "retry",
                    "skip"
                ],
                "type": "string",
                "description": "* `as_is` - as_is\n* `retry` - retry\n* `skip` - skip"
            },
            "BulkEditChangesRequest": {
                "type": "object",
                "description": "What a bulk edit changes. A key left out leaves that field alone.\n`categories_remove` never takes a stream out of its main category (that\nis `category`). `pinned_servers` is in order: the first plays the\nstreams, the others take over.",
                "properties": {
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "categories_add": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "categories_remove": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "bouquets_add": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "bouquets_remove": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "is_on_demand": {
                        "type": "boolean"
                    },
                    "is_direct": {
                        "type": "boolean"
                    },
                    "streaming_engine": {
                        "$ref": "#/components/schemas/StreamingEngineEnum"
                    },
                    "transcoding_profile": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "allow_passthrough": {
                        "type": "boolean"
                    },
                    "routing_mode": {
                        "$ref": "#/components/schemas/RoutingModeEnum"
                    },
                    "pinned_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "auto_eligible_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "epg": {
                        "$ref": "#/components/schemas/AutoOrClearEnum"
                    },
                    "epg_mode": {
                        "$ref": "#/components/schemas/EpgModeEnum"
                    },
                    "logo": {
                        "$ref": "#/components/schemas/AutoOrClearEnum"
                    },
                    "logo_mode": {
                        "$ref": "#/components/schemas/LogoModeEnum"
                    },
                    "sources": {
                        "$ref": "#/components/schemas/SourcesChangeRequest"
                    },
                    "rename": {
                        "$ref": "#/components/schemas/StreamRenameRuleRequest"
                    },
                    "sort": {
                        "$ref": "#/components/schemas/StreamSortSavedRequest"
                    }
                }
            },
            "BulkRequest": {
                "type": "object",
                "description": "`{action, ids}` or `{action, state}`: files picked, or every file\nin a state (`needs_you`: not found on TMDB, or failed).",
                "properties": {
                    "action": {
                        "$ref": "#/components/schemas/BulkActionEnum"
                    },
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 10000
                    },
                    "state": {
                        "$ref": "#/components/schemas/BulkStateEnum"
                    }
                },
                "required": [
                    "action"
                ]
            },
            "BulkStateEnum": {
                "enum": [
                    "needs_you",
                    "no_match",
                    "failed",
                    "skipped",
                    "no_details"
                ],
                "type": "string",
                "description": "* `needs_you` - needs_you\n* `no_match` - no_match\n* `failed` - failed\n* `skipped` - skipped\n* `no_details` - no_details"
            },
            "CaseEnum": {
                "enum": [
                    "keep",
                    "title",
                    "upper",
                    "lower"
                ],
                "type": "string",
                "description": "* `keep` - keep\n* `title` - title\n* `upper` - upper\n* `lower` - lower"
            },
            "CategoriesEnum": {
                "enum": [
                    "folder",
                    "tmdb",
                    "fixed",
                    "custom"
                ],
                "type": "string",
                "description": "* `folder` - Folder names\n* `tmdb` - TMDB genres\n* `fixed` - One category\n* `custom` - My own mapping"
            },
            "Category": {
                "type": "object",
                "description": "A category: groups and orders streams, movies or TV shows in players and the dashboard. `primary_count` counts what has it as its main category: a category with any can't be deleted.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "xtream_id": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "The number players know it by, in player links and the player API. Given when it is created, never changed or reused, because players save favourites against it."
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "type": {
                        "$ref": "#/components/schemas/CategoryTypeEnum"
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order within its type (lowest first)."
                    },
                    "streams_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "movies_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "series_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "primary_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "id",
                    "movies_count",
                    "name",
                    "primary_count",
                    "series_count",
                    "streams_count",
                    "type",
                    "updated_at",
                    "xtream_id"
                ]
            },
            "CategoryModeEnum": {
                "enum": [
                    "auto",
                    "existing"
                ],
                "type": "string",
                "description": "* `auto` - auto\n* `existing` - existing"
            },
            "CategoryReorderRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Categories of one type, in their new display order."
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "CategoryReorderResult": {
                "type": "object",
                "properties": {
                    "updated": {
                        "type": "integer",
                        "description": "Categories whose place changed."
                    }
                },
                "required": [
                    "updated"
                ]
            },
            "CategoryRequest": {
                "type": "object",
                "description": "A category: groups and orders streams, movies or TV shows in players and the dashboard. `primary_count` counts what has it as its main category: a category with any can't be deleted.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "type": {
                        "$ref": "#/components/schemas/CategoryTypeEnum"
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order within its type (lowest first)."
                    }
                },
                "required": [
                    "name",
                    "type"
                ]
            },
            "CategorySummary": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer",
                        "description": "Categories."
                    },
                    "hidden": {
                        "type": "integer",
                        "description": "Of which hidden."
                    },
                    "streams": {
                        "type": "integer",
                        "description": "Streams filed under any of them, each counted once."
                    },
                    "movies": {
                        "type": "integer",
                        "description": "Movies filed under any of them, each counted once."
                    },
                    "series": {
                        "type": "integer",
                        "description": "TV shows filed under any of them, each counted once."
                    }
                },
                "required": [
                    "hidden",
                    "movies",
                    "series",
                    "streams",
                    "total"
                ]
            },
            "CategoryTypeEnum": {
                "enum": [
                    "movies",
                    "tv_shows",
                    "streams",
                    "custom"
                ],
                "type": "string",
                "description": "* `movies` - Movies\n* `tv_shows` - TV Shows\n* `streams` - Streams\n* `custom` - Custom"
            },
            "CollisionsEnum": {
                "enum": [
                    "skip",
                    "renumber"
                ],
                "type": "string",
                "description": "* `skip` - skip\n* `renumber` - renumber"
            },
            "ComponentsEnum": {
                "enum": [
                    "accounts",
                    "lines",
                    "credits",
                    "categories",
                    "bouquets",
                    "streams",
                    "media",
                    "movies",
                    "tv_series",
                    "servers",
                    "access_control",
                    "settings",
                    "viewing_history",
                    "api_calls",
                    "server_metrics",
                    "task_history",
                    "panel_imports",
                    "playlist_editor",
                    "playlist_editor_history",
                    "providers",
                    "watch_folders",
                    "provider_history",
                    "admin_log",
                    "key_files"
                ],
                "type": "string",
                "description": "* `accounts` - accounts\n* `lines` - lines\n* `credits` - credits\n* `categories` - categories\n* `bouquets` - bouquets\n* `streams` - streams\n* `media` - media\n* `movies` - movies\n* `tv_series` - tv_series\n* `servers` - servers\n* `access_control` - access_control\n* `settings` - settings\n* `viewing_history` - viewing_history\n* `api_calls` - api_calls\n* `server_metrics` - server_metrics\n* `task_history` - task_history\n* `panel_imports` - panel_imports\n* `playlist_editor` - playlist_editor\n* `playlist_editor_history` - playlist_editor_history\n* `providers` - providers\n* `watch_folders` - watch_folders\n* `provider_history` - provider_history\n* `admin_log` - admin_log\n* `key_files` - key_files"
            },
            "CompressionEnum": {
                "enum": [
                    1,
                    6,
                    9
                ],
                "type": "integer",
                "description": "* `1` - Fast (larger files)\n* `6` - Balanced\n* `9` - Smallest (slower)"
            },
            "ConflictModeEnum": {
                "enum": [
                    "skip",
                    "update",
                    "suffix"
                ],
                "type": "string",
                "description": "* `skip` - Skip existing\n* `update` - Update existing\n* `suffix` - Create with a numbered suffix"
            },
            "ConnectionDisconnected": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "ContentKindEnum": {
                "enum": [
                    "live",
                    "movie",
                    "series"
                ],
                "type": "string",
                "description": "* `live` - live\n* `movie` - movie\n* `series` - series"
            },
            "ConvertEnum": {
                "enum": [
                    "audio",
                    "video"
                ],
                "type": "string",
                "description": "* `audio` - audio\n* `video` - video"
            },
            "CountriesRequest": {
                "type": "object",
                "properties": {
                    "codes": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 8
                        },
                        "maxItems": 300
                    }
                },
                "required": [
                    "codes"
                ]
            },
            "CreatedChannelContentKindEnum": {
                "enum": [
                    "movie",
                    "episode",
                    "series",
                    "season",
                    "movie_category",
                    "series_category",
                    "all_movies",
                    "all_episodes",
                    "everything"
                ],
                "type": "string",
                "description": "* `movie` - A film\n* `episode` - An episode\n* `series` - A whole show\n* `season` - A season\n* `movie_category` - The films of a category\n* `series_category` - The shows of a category\n* `all_movies` - Every film\n* `all_episodes` - Every episode\n* `everything` - Every film and episode"
            },
            "CreatedChannelDay": {
                "type": "object",
                "properties": {
                    "day": {
                        "type": "string",
                        "format": "date"
                    },
                    "timezone": {
                        "type": "string"
                    },
                    "entries": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CreatedChannelEntry"
                        }
                    },
                    "waiting": {
                        "type": "boolean"
                    },
                    "ends_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "required": [
                    "day",
                    "ends_at",
                    "entries",
                    "timezone",
                    "waiting"
                ]
            },
            "CreatedChannelEntry": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "title": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/MovieOrEpisodeEnum"
                    },
                    "fixed_time": {
                        "type": "boolean"
                    },
                    "converted": {
                        "type": "boolean"
                    },
                    "on_now": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "converted",
                    "fixed_time",
                    "kind",
                    "on_now",
                    "start",
                    "stop",
                    "title"
                ]
            },
            "CreatedChannelGuideEditRequest": {
                "type": "object",
                "description": "The operator's words for one title of the guide; all empty: the\ntitle's own words again.",
                "properties": {
                    "key": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 48
                    },
                    "title": {
                        "type": "string",
                        "default": "",
                        "maxLength": 300
                    },
                    "sub_title": {
                        "type": "string",
                        "default": "",
                        "maxLength": 300
                    },
                    "description": {
                        "type": "string",
                        "default": "",
                        "maxLength": 4000
                    }
                },
                "required": [
                    "key"
                ]
            },
            "CreatedChannelGuideEditsRequest": {
                "type": "object",
                "properties": {
                    "edits": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CreatedChannelGuideEditRequest"
                        }
                    }
                },
                "required": [
                    "edits"
                ]
            },
            "CreatedChannelGuideKept": {
                "type": "object",
                "properties": {
                    "kept": {
                        "type": "integer"
                    }
                },
                "required": [
                    "kept"
                ]
            },
            "CreatedChannelGuidePage": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CreatedChannelGuideTitle"
                        }
                    }
                },
                "required": [
                    "count",
                    "results"
                ]
            },
            "CreatedChannelGuideTitle": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/MovieOrEpisodeEnum"
                    },
                    "name": {
                        "type": "string"
                    },
                    "made": {
                        "$ref": "#/components/schemas/CreatedChannelGuideWords"
                    },
                    "edit": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreatedChannelGuideWords"
                            }
                        ],
                        "nullable": true
                    }
                },
                "required": [
                    "edit",
                    "key",
                    "kind",
                    "made",
                    "name"
                ]
            },
            "CreatedChannelGuideWords": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string"
                    },
                    "sub_title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    }
                },
                "required": [
                    "description",
                    "sub_title",
                    "title"
                ]
            },
            "CreatedChannelItem": {
                "type": "object",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/CreatedChannelContentKindEnum"
                    },
                    "movie": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "episode": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "season": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "label": {
                        "type": "string",
                        "readOnly": true
                    }
                },
                "required": [
                    "kind",
                    "label"
                ]
            },
            "CreatedChannelPlan": {
                "type": "object",
                "properties": {
                    "order": {
                        "$ref": "#/components/schemas/OrderEnum"
                    },
                    "ending": {
                        "$ref": "#/components/schemas/EndingEnum"
                    },
                    "format": {
                        "$ref": "#/components/schemas/CreatedChannelPlanFormatEnum"
                    },
                    "logo": {
                        "type": "boolean",
                        "description": "Draw the channel logo on the picture. Every title is then converted."
                    },
                    "logo_corner": {
                        "$ref": "#/components/schemas/LogoCornerEnum"
                    },
                    "banner_minutes": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "description": "Show \"Next: <title>\" during the last this many minutes of each title (0 = never). Every title is then converted."
                    },
                    "timezone": {
                        "type": "string",
                        "description": "The time zone the fixed times are written in.",
                        "maxLength": 64
                    },
                    "guide": {
                        "$ref": "#/components/schemas/GuideEnum"
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CreatedChannelItem"
                        }
                    },
                    "slots": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CreatedChannelSlot"
                        }
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "ends_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "waiting": {
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "ends_at",
                    "started_at",
                    "updated_at",
                    "waiting"
                ]
            },
            "CreatedChannelPlanFormatEnum": {
                "enum": [
                    "auto",
                    "copy",
                    "convert"
                ],
                "type": "string",
                "description": "* `auto` - Convert only the titles in another format\n* `copy` - Never convert (cheapest)\n* `convert` - Convert every title (needed for the logo and the banner)"
            },
            "CreatedChannelSlot": {
                "type": "object",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/CreatedChannelContentKindEnum"
                    },
                    "movie": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "episode": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "season": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "starts": {
                        "type": "string",
                        "format": "time"
                    },
                    "date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "length_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "nullable": true
                    },
                    "count": {
                        "type": "integer",
                        "maximum": 50,
                        "minimum": 1,
                        "default": 1
                    }
                },
                "required": [
                    "kind",
                    "label",
                    "starts"
                ]
            },
            "CreditAccountRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "username": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "username"
                ]
            },
            "CreditAdjusted": {
                "type": "object",
                "properties": {
                    "entry": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Entry"
                            }
                        ],
                        "description": "The history row written."
                    },
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Their balance now."
                    }
                },
                "required": [
                    "balance",
                    "entry"
                ]
            },
            "CreditAdjustmentRequest": {
                "type": "object",
                "description": "Credits to add, or to remove with a negative amount, and why.",
                "properties": {
                    "amount": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "reason": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditAdjustmentTypeEnum"
                            }
                        ],
                        "default": "other",
                        "description": "Why, for the history.\n\n* `payment` - They paid\n* `refund` - You refunded them\n* `correction` - A correction\n* `promo` - A promotion\n* `other` - Anything else"
                    },
                    "reference": {
                        "type": "string",
                        "default": "",
                        "maxLength": 200
                    }
                },
                "required": [
                    "amount",
                    "reason"
                ]
            },
            "CreditAdjustmentTypeEnum": {
                "enum": [
                    "payment",
                    "refund",
                    "correction",
                    "promo",
                    "other"
                ],
                "type": "string",
                "description": "* `payment` - They paid\n* `refund` - You refunded them\n* `correction` - A correction\n* `promo` - A promotion\n* `other` - Anything else"
            },
            "CreditBalance": {
                "type": "object",
                "properties": {
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "unlimited": {
                        "type": "boolean",
                        "description": "Lines cost this account nothing, whatever its balance."
                    },
                    "is_reseller": {
                        "type": "boolean",
                        "description": "The account pays for its lines with credits."
                    },
                    "can_adjust": {
                        "type": "boolean",
                        "description": "May add or remove resellers' credits."
                    },
                    "can_give": {
                        "type": "boolean",
                        "description": "May give credits to the resellers below it."
                    },
                    "can_view_all": {
                        "type": "boolean",
                        "description": "Sees every reseller's credits."
                    },
                    "can_manage_prices": {
                        "type": "boolean",
                        "description": "May set resellers' own package prices."
                    },
                    "spent_this_month": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Spent on lines this calendar month, net of refunds."
                    },
                    "held_by_subresellers": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true,
                        "description": "What the resellers below it hold. Null for an operator."
                    },
                    "cheapest_price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true,
                        "description": "The lowest price it pays for a package it sells. Null when none."
                    },
                    "low": {
                        "type": "boolean",
                        "description": "The balance is below the cheapest price."
                    },
                    "trials": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditTrials"
                            }
                        ],
                        "nullable": true,
                        "description": "Trial lines; null for an operator."
                    }
                },
                "required": [
                    "balance",
                    "can_adjust",
                    "can_give",
                    "can_manage_prices",
                    "can_view_all",
                    "cheapest_price",
                    "held_by_subresellers",
                    "is_reseller",
                    "low",
                    "spent_this_month",
                    "trials",
                    "unlimited"
                ]
            },
            "CreditDeleteQuote": {
                "type": "object",
                "properties": {
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Their balance (negative when they owe credits)."
                    },
                    "kind": {
                        "nullable": true,
                        "description": "What happens to it: `returned` to the reseller above them, or `written_off`. Null: no credits.\n\n* `returned` - returned\n* `written_off` - written_off",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/CreditDeleteQuoteKindEnum"
                            },
                            {
                                "$ref": "#/components/schemas/NullEnum"
                            }
                        ]
                    },
                    "goes_to": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditReturnedTo"
                            }
                        ],
                        "nullable": true,
                        "description": "Who gets the balance back; null when nobody does."
                    },
                    "why": {
                        "type": "string",
                        "description": "The same, in one sentence."
                    }
                },
                "required": [
                    "balance",
                    "goes_to",
                    "kind",
                    "why"
                ]
            },
            "CreditDeleteQuoteKindEnum": {
                "enum": [
                    "returned",
                    "written_off"
                ],
                "type": "string",
                "description": "* `returned` - returned\n* `written_off` - written_off"
            },
            "CreditGiven": {
                "type": "object",
                "properties": {
                    "entries": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Entry"
                        },
                        "description": "The two history rows written: yours, then theirs."
                    },
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Their balance now."
                    },
                    "my_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Your balance now."
                    }
                },
                "required": [
                    "balance",
                    "entries",
                    "my_balance"
                ]
            },
            "CreditPricePackage": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "The package's own price."
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "is_enabled": {
                        "type": "boolean"
                    },
                    "duration": {
                        "type": "string",
                        "description": "In words: \"1 month\", \"7 days\"."
                    }
                },
                "required": [
                    "credit_cost",
                    "duration",
                    "id",
                    "is_enabled",
                    "is_trial",
                    "name"
                ]
            },
            "CreditPriceRow": {
                "type": "object",
                "properties": {
                    "package": {
                        "$ref": "#/components/schemas/CreditPricePackage"
                    },
                    "price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true,
                        "description": "Their own price; null when none is set."
                    },
                    "effective_price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "What they pay for it."
                    },
                    "source": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditPriceRowSourceEnum"
                            }
                        ],
                        "description": "Where `effective_price` comes from.\n\n* `own` - Their own price\n* `parent` - A price set by a reseller above them\n* `list` - The package's price"
                    }
                },
                "required": [
                    "effective_price",
                    "package",
                    "price",
                    "source"
                ]
            },
            "CreditPriceRowSourceEnum": {
                "enum": [
                    "own",
                    "parent",
                    "list"
                ],
                "type": "string",
                "description": "* `own` - Their own price\n* `parent` - A price set by a reseller above them\n* `list` - The package's price"
            },
            "CreditPriceSetRequest": {
                "type": "object",
                "properties": {
                    "package": {
                        "type": "string",
                        "format": "uuid",
                        "description": "A package they may sell."
                    },
                    "price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true,
                        "description": "Their price; null clears it (they pay the package's), \"0.00\" is free."
                    }
                },
                "required": [
                    "package",
                    "price"
                ]
            },
            "CreditQuote": {
                "type": "object",
                "properties": {
                    "price": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "What the package costs this account."
                    },
                    "own_price": {
                        "type": "boolean",
                        "description": "The price is one set for this account."
                    },
                    "source": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditQuoteSourceEnum"
                            }
                        ],
                        "description": "Where the price comes from.\n\n* `own` - Your own price\n* `parent` - A price the reseller above you set\n* `list` - The package's price"
                    },
                    "balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "balance_after": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "unlimited": {
                        "type": "boolean"
                    },
                    "operator": {
                        "type": "boolean",
                        "description": "A panel operator: pays nothing."
                    },
                    "enough": {
                        "type": "boolean",
                        "description": "The balance covers the price."
                    },
                    "missing": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "What the balance lacks; \"0.00\" when it is enough."
                    },
                    "trial": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditQuoteTrial"
                            }
                        ],
                        "nullable": true,
                        "description": "For a trial package on a new line; null otherwise."
                    },
                    "refused": {
                        "type": "string",
                        "nullable": true,
                        "description": "Why it would be refused, in words; null: it would not."
                    },
                    "refused_field": {
                        "nullable": true,
                        "description": "What the refusal is about.\n\n* `package` - package\n* `credits` - credits",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/RefusedFieldEnum"
                            },
                            {
                                "$ref": "#/components/schemas/NullEnum"
                            }
                        ]
                    },
                    "next_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When a trial limit refusal lifts."
                    }
                },
                "required": [
                    "balance",
                    "balance_after",
                    "enough",
                    "missing",
                    "next_at",
                    "operator",
                    "own_price",
                    "price",
                    "refused",
                    "refused_field",
                    "source",
                    "trial",
                    "unlimited"
                ]
            },
            "CreditQuoteSourceEnum": {
                "enum": [
                    "own",
                    "parent",
                    "list"
                ],
                "type": "string",
                "description": "* `own` - Your own price\n* `parent` - A price the reseller above you set\n* `list` - The package's price"
            },
            "CreditQuoteTrial": {
                "type": "object",
                "properties": {
                    "left": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Trial lines left in the period; null: no limit."
                    }
                },
                "required": [
                    "left"
                ]
            },
            "CreditReturnedTo": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "username": {
                        "type": "string"
                    },
                    "is_me": {
                        "type": "boolean",
                        "description": "True when it is the signed-in account."
                    }
                },
                "required": [
                    "id",
                    "is_me",
                    "username"
                ]
            },
            "CreditTotals": {
                "type": "object",
                "properties": {
                    "added": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Added by operators, and balances brought from another panel."
                    },
                    "spent": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Spent on lines."
                    },
                    "refunded": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Given back for deleted lines."
                    },
                    "given": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Given to other resellers."
                    },
                    "received": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Received from other resellers."
                    },
                    "returned": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Returned from deleted resellers' balances."
                    },
                    "written_off": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Written off with deleted resellers' balances."
                    },
                    "held_by_resellers": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "What the accounts covered hold right now."
                    }
                },
                "required": [
                    "added",
                    "given",
                    "held_by_resellers",
                    "received",
                    "refunded",
                    "returned",
                    "spent",
                    "written_off"
                ]
            },
            "CreditTrials": {
                "type": "object",
                "properties": {
                    "limit": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Trial lines allowed per period; null: no limit."
                    },
                    "period": {
                        "$ref": "#/components/schemas/PeriodEnum"
                    },
                    "used": {
                        "type": "integer",
                        "description": "Trial lines made in the current period."
                    },
                    "left": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Null: no limit."
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Whether this account may make trial lines at all."
                    },
                    "min_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "The balance a trial line needs."
                    },
                    "blocked": {
                        "nullable": true,
                        "description": "Why the next trial line would be refused: none left, or the balance is too low. Null: it would not.\n\n* `limit` - limit\n* `min_balance` - min_balance",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/BlockedEnum"
                            },
                            {
                                "$ref": "#/components/schemas/NullEnum"
                            }
                        ]
                    },
                    "next_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When the next trial line opens, once none are left."
                    }
                },
                "required": [
                    "blocked",
                    "enabled",
                    "left",
                    "limit",
                    "min_balance",
                    "next_at",
                    "period",
                    "used"
                ]
            },
            "CurrentSource": {
                "type": "object",
                "description": "The source the stream is playing from now, with what the servers\nlast read from it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Source Name"
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true,
                        "title": "Source URL"
                    },
                    "health": {
                        "type": "string",
                        "readOnly": true,
                        "description": "How the servers last found it: `online` while a server plays from it, `down` after one failed to, `unknown` until a server has tried."
                    },
                    "health_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Health Reported At",
                        "description": "When a server last said how it found it."
                    },
                    "probed_video_codec": {
                        "type": "string",
                        "readOnly": true,
                        "description": "e.g. h264, hevc. Empty until a server has read the source."
                    },
                    "probed_audio_codec": {
                        "type": "string",
                        "readOnly": true
                    },
                    "probed_fps": {
                        "type": "number",
                        "format": "double",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Null when the source declares a variable or unknown rate."
                    },
                    "probed_width": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "probed_height": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "probed_audio_tracks": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Number of audio streams — language alternatives."
                    },
                    "probed_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "description": "When a server last read these, as a stream started on it."
                    }
                },
                "required": [
                    "health",
                    "health_at",
                    "id",
                    "name",
                    "probed_at",
                    "probed_audio_codec",
                    "probed_audio_tracks",
                    "probed_fps",
                    "probed_height",
                    "probed_video_codec",
                    "probed_width",
                    "url"
                ]
            },
            "CurrentUserPermissionsResponseDoc": {
                "type": "object",
                "properties": {
                    "username": {
                        "type": "string"
                    },
                    "is_staff": {
                        "type": "boolean"
                    },
                    "is_superuser": {
                        "type": "boolean"
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "groups",
                    "is_staff",
                    "is_superuser",
                    "permissions",
                    "username"
                ]
            },
            "DatabaseHealth": {
                "type": "object",
                "description": "The panel database's health. When `status` is `down`, only\n`checked_at`, `error` and `warnings` come.",
                "properties": {
                    "status": {
                        "type": "string",
                        "description": "`ok`, `warn` (see `warnings`) or `down`."
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "error": {
                        "type": "string",
                        "description": "Why the database cannot be reached (`down` only)."
                    },
                    "ping_ms": {
                        "type": "number",
                        "format": "double",
                        "description": "How long a trivial query took."
                    },
                    "version": {
                        "type": "string",
                        "description": "The database server's version."
                    },
                    "uptime_seconds": {
                        "type": "integer"
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "connections": {
                        "$ref": "#/components/schemas/DatabaseHealthConnections"
                    },
                    "cache_hit_ratio": {
                        "type": "number",
                        "format": "double",
                        "nullable": true,
                        "description": "Share of reads served from memory (0–1)."
                    },
                    "deadlocks": {
                        "type": "integer"
                    },
                    "commits": {
                        "type": "integer"
                    },
                    "rollbacks": {
                        "type": "integer"
                    },
                    "temp_bytes": {
                        "type": "integer"
                    },
                    "stats_since": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Since when the counters above count."
                    },
                    "longest_transaction_seconds": {
                        "type": "integer"
                    },
                    "long_running_queries": {
                        "type": "integer",
                        "description": "Queries running for over a minute."
                    },
                    "lock_waiters": {
                        "type": "integer"
                    },
                    "pending_migrations": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Database changes not applied yet (restart the panel)."
                    },
                    "largest_tables": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DatabaseHealthTable"
                        }
                    },
                    "backup": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/DatabaseHealthBackup"
                            }
                        ],
                        "nullable": true
                    },
                    "warnings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DatabaseHealthWarning"
                        }
                    }
                },
                "required": [
                    "checked_at",
                    "status",
                    "warnings"
                ]
            },
            "DatabaseHealthBackup": {
                "type": "object",
                "properties": {
                    "last_success_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "last_success_size": {
                        "type": "integer",
                        "nullable": true
                    },
                    "last_failure_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "next_run_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "next_plan": {
                        "type": "string",
                        "nullable": true,
                        "description": "The backup schedule that runs next."
                    },
                    "running": {
                        "type": "boolean"
                    },
                    "warning": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "required": [
                    "last_failure_at",
                    "last_success_at",
                    "last_success_size",
                    "next_plan",
                    "next_run_at",
                    "running",
                    "warning"
                ]
            },
            "DatabaseHealthConnections": {
                "type": "object",
                "properties": {
                    "active": {
                        "type": "integer"
                    },
                    "idle": {
                        "type": "integer"
                    },
                    "idle_in_transaction": {
                        "type": "integer"
                    },
                    "panel_total": {
                        "type": "integer",
                        "description": "Connections to the panel's database."
                    },
                    "server_total": {
                        "type": "integer",
                        "description": "Connections to the whole database server."
                    },
                    "max": {
                        "type": "integer",
                        "description": "The most the database server accepts."
                    }
                },
                "required": [
                    "active",
                    "idle",
                    "idle_in_transaction",
                    "max",
                    "panel_total",
                    "server_total"
                ]
            },
            "DatabaseHealthTable": {
                "type": "object",
                "properties": {
                    "table": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string",
                        "description": "What the table holds, in plain words."
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "rows": {
                        "type": "integer",
                        "nullable": true
                    },
                    "dead_rows": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Old rows waiting to be cleaned up."
                    },
                    "last_vacuum": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "required": [
                    "dead_rows",
                    "label",
                    "last_vacuum",
                    "rows",
                    "size_bytes",
                    "table"
                ]
            },
            "DatabaseHealthWarning": {
                "type": "object",
                "properties": {
                    "level": {
                        "type": "string",
                        "description": "`warn`, or `down` when the database cannot be reached."
                    },
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "level",
                    "message"
                ]
            },
            "DownVideoChunk": {
                "type": "object",
                "properties": {
                    "received": {
                        "type": "integer",
                        "description": "Bytes of the video the panel holds."
                    },
                    "expected_offset": {
                        "type": "integer",
                        "description": "The chunk was not where the file ends: send from here."
                    }
                },
                "required": [
                    "received"
                ]
            },
            "DurationEnum": {
                "enum": [
                    "forever",
                    "1h",
                    "1d",
                    "7d",
                    "30d"
                ],
                "type": "string",
                "description": "* `forever` - forever\n* `1h` - 1h\n* `1d` - 1d\n* `7d` - 7d\n* `30d` - 30d"
            },
            "DurationTypeEnum": {
                "enum": [
                    "hours",
                    "days",
                    "weeks",
                    "months"
                ],
                "type": "string",
                "description": "* `hours` - Hours\n* `days` - Days\n* `weeks` - Weeks\n* `months` - Months"
            },
            "EditorAddSourceRequest": {
                "type": "object",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/EditorSourceRequest"
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ContentKindEnum"
                        },
                        "default": [
                            "live"
                        ]
                    },
                    "attributes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/AttributesEnum"
                        },
                        "default": [
                            "category",
                            "logo"
                        ]
                    },
                    "categories": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string",
                                "minLength": 1
                            },
                            "maxItems": 100000
                        }
                    }
                },
                "required": [
                    "source"
                ]
            },
            "EditorAffixOptionsRequest": {
                "type": "object",
                "properties": {
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "where": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorAffixOptionsWhereEnum"
                            }
                        ],
                        "default": "prefix"
                    },
                    "remove": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "text"
                ]
            },
            "EditorAffixOptionsWhereEnum": {
                "enum": [
                    "prefix",
                    "suffix"
                ],
                "type": "string",
                "description": "* `prefix` - prefix\n* `suffix` - suffix"
            },
            "EditorApiCategory": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "source_name": {
                        "type": "string",
                        "description": "The provider's name for it."
                    },
                    "position": {
                        "type": "integer"
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "deleted_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Set while it is in the bin."
                    }
                },
                "required": [
                    "deleted_at",
                    "hidden",
                    "id",
                    "name",
                    "position",
                    "source_name",
                    "sync_name"
                ]
            },
            "EditorApiCategoryList": {
                "type": "object",
                "properties": {
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorApiCategory"
                        }
                    }
                },
                "required": [
                    "results"
                ]
            },
            "EditorApiEntryChangeRequest": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "maxLength": 2000
                    },
                    "logo": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "epg_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "epg_shift": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,3}(?:\\.\\d{0,2})?$"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -1
                    },
                    "catchup_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 0
                    },
                    "tmdb_id": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 1,
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,2})?$",
                        "nullable": true
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "category": {
                        "type": "integer"
                    }
                },
                "required": [
                    "id"
                ]
            },
            "EditorApiEntryPage": {
                "type": "object",
                "properties": {
                    "columns": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The order of the values in each row."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        }
                    },
                    "next": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Pass it as `after` for the next page; null at the end."
                    }
                },
                "required": [
                    "columns",
                    "next",
                    "results"
                ]
            },
            "EditorApiPlaylist": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "username": {
                        "type": "string",
                        "description": "The playlist's own login."
                    },
                    "password": {
                        "type": "string"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "message": {
                        "type": "string"
                    },
                    "counts": {
                        "$ref": "#/components/schemas/EditorApiPlaylistCounts"
                    },
                    "version": {
                        "type": "integer",
                        "description": "Goes up with every change."
                    },
                    "last_synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "counts",
                    "expiry",
                    "id",
                    "last_synced_at",
                    "message",
                    "name",
                    "password",
                    "updated_at",
                    "username",
                    "version"
                ]
            },
            "EditorApiPlaylistCounts": {
                "type": "object",
                "properties": {
                    "live": {
                        "type": "integer"
                    },
                    "movie": {
                        "type": "integer"
                    },
                    "series": {
                        "type": "integer"
                    },
                    "episodes": {
                        "type": "integer"
                    },
                    "users": {
                        "type": "integer",
                        "description": "Customers."
                    }
                },
                "required": [
                    "episodes",
                    "live",
                    "movie",
                    "series",
                    "users"
                ]
            },
            "EditorApiPlaylistList": {
                "type": "object",
                "properties": {
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorApiPlaylist"
                        }
                    }
                },
                "required": [
                    "results"
                ]
            },
            "EditorAutoBackup": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "weekly": {
                        "type": "boolean",
                        "description": "Kept 35 days; the others 7."
                    },
                    "size": {
                        "type": "integer",
                        "description": "Bytes."
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        },
                        "description": "What it holds, by section."
                    }
                },
                "required": [
                    "counts",
                    "created_at",
                    "id",
                    "size",
                    "weekly"
                ]
            },
            "EditorAutoRestoreRequest": {
                "type": "object",
                "properties": {
                    "sections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SectionsEnum"
                        },
                        "description": "What to restore (default: all). In a form, also one comma-separated value."
                    }
                }
            },
            "EditorBackupRequest": {
                "type": "object",
                "properties": {
                    "type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorBackupTypeEnum"
                            }
                        ],
                        "default": "private"
                    },
                    "sections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SectionsEnum"
                        },
                        "default": [
                            "live",
                            "movie",
                            "series",
                            "updaters",
                            "users"
                        ]
                    }
                }
            },
            "EditorBackupTypeEnum": {
                "enum": [
                    "private",
                    "shareable"
                ],
                "type": "string",
                "description": "* `private` - private\n* `shareable` - shareable"
            },
            "EditorCandidate": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The new provider's id for it."
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string"
                    },
                    "category": {
                        "type": "string"
                    }
                },
                "required": [
                    "category",
                    "key",
                    "name",
                    "url"
                ]
            },
            "EditorCaseOptionsModeEnum": {
                "enum": [
                    "upper",
                    "lower",
                    "title",
                    "capitalize"
                ],
                "type": "string",
                "description": "* `upper` - upper\n* `lower` - lower\n* `title` - title\n* `capitalize` - capitalize"
            },
            "EditorCaseOptionsRequest": {
                "type": "object",
                "properties": {
                    "mode": {
                        "$ref": "#/components/schemas/EditorCaseOptionsModeEnum"
                    }
                },
                "required": [
                    "mode"
                ]
            },
            "EditorCategory": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "source_name": {
                        "type": "string",
                        "description": "Its name at the provider ('' for one made in the editor)."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Categories are listed by position."
                    },
                    "hidden": {
                        "type": "boolean",
                        "description": "Hidden from the playlist players get."
                    },
                    "sync_name": {
                        "type": "boolean",
                        "description": "Takes the provider's name again at each sync."
                    },
                    "deleted_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it went to the recycle bin; null when it is not there."
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many rows it shows."
                    }
                },
                "required": [
                    "count",
                    "deleted_at",
                    "hidden",
                    "id",
                    "name",
                    "position",
                    "source_name",
                    "sync_name"
                ]
            },
            "EditorCategoryCloneRequest": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "into": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    }
                },
                "required": [
                    "id"
                ]
            },
            "EditorCategoryCreateRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "hidden": {
                        "type": "boolean",
                        "default": false
                    },
                    "sync_name": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "name"
                ]
            },
            "EditorCategoryIdsRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 50000
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorCategoryItemRequest": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "id"
                ]
            },
            "EditorCategoryMergeRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 10000
                    },
                    "into": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "ids",
                    "into"
                ]
            },
            "EditorCategoryReorderRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "before": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "after": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorCategorySaveRequest": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategoryItemRequest"
                        },
                        "maxItems": 50000
                    }
                },
                "required": [
                    "items"
                ]
            },
            "EditorCategorySortRequest": {
                "type": "object",
                "properties": {
                    "desc": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "EditorChange": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "seq": {
                        "type": "integer",
                        "description": "Its place in the playlist's history."
                    },
                    "label": {
                        "type": "string",
                        "description": "What it did, in words, e.g. \"Renamed 12 channels\"."
                    },
                    "operation": {
                        "type": "string",
                        "description": "The kind of edit, e.g. `save`, `rename`, `move`, `delete`, `purge`, `sort`, `tool:replace`, `undo`."
                    },
                    "kind": {
                        "type": "string",
                        "description": "The list it changed: `live`, `movie` or `series`; empty when it was not one list."
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many rows it changed."
                    },
                    "undoable": {
                        "type": "boolean",
                        "description": "Whether it can still be undone or reverted."
                    },
                    "undone": {
                        "type": "boolean",
                        "description": "Whether it is undone (redo brings it back)."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "count",
                    "created_at",
                    "id",
                    "kind",
                    "label",
                    "operation",
                    "seq",
                    "undoable",
                    "undone"
                ]
            },
            "EditorChangeDetail": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "seq": {
                        "type": "integer",
                        "description": "Its place in the playlist's history."
                    },
                    "label": {
                        "type": "string",
                        "description": "What it did, in words, e.g. \"Renamed 12 channels\"."
                    },
                    "operation": {
                        "type": "string",
                        "description": "The kind of edit, e.g. `save`, `rename`, `move`, `delete`, `purge`, `sort`, `tool:replace`, `undo`."
                    },
                    "kind": {
                        "type": "string",
                        "description": "The list it changed: `live`, `movie` or `series`; empty when it was not one list."
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many rows it changed."
                    },
                    "undoable": {
                        "type": "boolean",
                        "description": "Whether it can still be undone or reverted."
                    },
                    "undone": {
                        "type": "boolean",
                        "description": "Whether it is undone (redo brings it back)."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorChangeRow"
                        }
                    },
                    "more": {
                        "type": "integer",
                        "description": "Rows of the change left out of `rows`."
                    }
                },
                "required": [
                    "count",
                    "created_at",
                    "id",
                    "kind",
                    "label",
                    "more",
                    "operation",
                    "rows",
                    "seq",
                    "undoable",
                    "undone"
                ]
            },
            "EditorChangeRow": {
                "type": "object",
                "properties": {
                    "t": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/TEnum"
                            }
                        ],
                        "description": "What the row is: a channel, movie or TV show (`entry`), a category or an episode.\n\n* `entry` - entry\n* `category` - category\n* `episode` - episode"
                    },
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "b": {
                        "nullable": true,
                        "description": "The fields it changed, before; null: the change added the row."
                    },
                    "a": {
                        "nullable": true,
                        "description": "The same fields after; null: the change removed the row."
                    }
                },
                "required": [
                    "a",
                    "b",
                    "id",
                    "name",
                    "t"
                ]
            },
            "EditorChangeTypeRequest": {
                "type": "object",
                "description": "The rows to turn into another kind, and where their copies go.",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "new_category": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "to": {
                        "$ref": "#/components/schemas/ContentKindEnum"
                    },
                    "series": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "new_series": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "season": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": -1,
                        "default": 1
                    },
                    "episode": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "keep": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "ids",
                    "to"
                ]
            },
            "EditorConnection": {
                "type": "object",
                "properties": {
                    "ip": {
                        "type": "string"
                    },
                    "user_agent": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "country": {
                        "type": "string",
                        "description": "Two-letter country code."
                    },
                    "what": {
                        "type": "string",
                        "description": "What they watched last."
                    },
                    "first_seen": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "last_seen": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "requests": {
                        "type": "integer"
                    },
                    "online": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "city",
                    "country",
                    "first_seen",
                    "ip",
                    "last_seen",
                    "online",
                    "requests",
                    "user_agent",
                    "what"
                ]
            },
            "EditorCopyEditsRequest": {
                "type": "object",
                "properties": {
                    "scope": {
                        "$ref": "#/components/schemas/EditorScopeRequest"
                    },
                    "match_by": {
                        "$ref": "#/components/schemas/MatchByEnum"
                    },
                    "values": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ValuesEnum"
                        }
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid"
                    }
                },
                "required": [
                    "match_by",
                    "playlist",
                    "scope",
                    "values"
                ]
            },
            "EditorCopyEditsResult": {
                "type": "object",
                "properties": {
                    "matched": {
                        "type": "integer",
                        "description": "Rows of the other playlist that matched."
                    },
                    "updated": {
                        "type": "integer",
                        "description": "Of those, rows that changed."
                    },
                    "change": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The change made in the other playlist's history."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The other playlist's version after it."
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The other playlist's id."
                    }
                },
                "required": [
                    "change",
                    "matched",
                    "playlist",
                    "updated",
                    "version"
                ]
            },
            "EditorCopyResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "nullable": true,
                        "description": "The rows it changed, as the grid lists them; null when there are too many to send: load the list again. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "created": {
                        "type": "integer",
                        "description": "Copies made."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Rows left out: already there."
                    },
                    "message": {
                        "type": "string",
                        "description": "What it did, in a sentence to show."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "created",
                    "message",
                    "removed",
                    "rows",
                    "skipped",
                    "version"
                ]
            },
            "EditorCopyTarget": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The other playlist's id."
                    },
                    "version": {
                        "type": "integer",
                        "description": "Its version after the copy."
                    },
                    "change": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The change made in its history."
                    }
                },
                "required": [
                    "change",
                    "id",
                    "version"
                ]
            },
            "EditorCover": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "year": {
                        "type": "string"
                    },
                    "tmdb_id": {
                        "type": "string"
                    }
                },
                "required": [
                    "name",
                    "tmdb_id",
                    "url",
                    "year"
                ]
            },
            "EditorCustomer": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "username": {
                        "type": "string"
                    },
                    "password": {
                        "type": "string"
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Null: never."
                    },
                    "sync_expiry": {
                        "type": "boolean",
                        "description": "The end date is read from the provider when it nears."
                    },
                    "max_connections": {
                        "type": "integer",
                        "description": "-1: no limit."
                    },
                    "message": {
                        "type": "string"
                    },
                    "notes": {
                        "type": "string"
                    },
                    "language": {
                        "type": "string"
                    },
                    "all_live": {
                        "type": "boolean",
                        "description": "Every channel category, new ones too."
                    },
                    "live_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "all_movie": {
                        "type": "boolean"
                    },
                    "movie_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "all_series": {
                        "type": "boolean"
                    },
                    "series_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "providers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorProviderLine"
                        },
                        "description": "Their own provider lines."
                    },
                    "copy_login": {
                        "type": "boolean",
                        "description": "Their provider lines use their own username and password."
                    },
                    "online": {
                        "type": "boolean"
                    },
                    "last_seen_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "connections": {
                        "type": "integer",
                        "description": "Connections now."
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "all_live",
                    "all_movie",
                    "all_series",
                    "connections",
                    "copy_login",
                    "created_at",
                    "enabled",
                    "expiry",
                    "id",
                    "language",
                    "last_seen_at",
                    "live_categories",
                    "max_connections",
                    "message",
                    "movie_categories",
                    "name",
                    "notes",
                    "online",
                    "password",
                    "providers",
                    "series_categories",
                    "sync_expiry",
                    "synced_at",
                    "username"
                ]
            },
            "EditorCustomerMoveRequest": {
                "type": "object",
                "properties": {
                    "playlist": {
                        "type": "string",
                        "format": "uuid"
                    }
                },
                "required": [
                    "playlist"
                ]
            },
            "EditorCustomerRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "password": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "sync_expiry": {
                        "type": "boolean"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "message": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "notes": {
                        "type": "string",
                        "maxLength": 5000
                    },
                    "language": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "all_live": {
                        "type": "boolean"
                    },
                    "live_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "all_movie": {
                        "type": "boolean"
                    },
                    "movie_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "all_series": {
                        "type": "boolean"
                    },
                    "series_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "providers": {},
                    "copy_login": {
                        "type": "boolean"
                    }
                }
            },
            "EditorCustomersCategoriesModeEnum": {
                "enum": [
                    "add",
                    "remove",
                    "overwrite"
                ],
                "type": "string",
                "description": "* `add` - add\n* `remove` - remove\n* `overwrite` - overwrite"
            },
            "EditorCustomersCategoriesRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "mode": {
                        "$ref": "#/components/schemas/EditorCustomersCategoriesModeEnum"
                    },
                    "live": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true
                    },
                    "movie": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true
                    },
                    "series": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "nullable": true
                    }
                },
                "required": [
                    "ids",
                    "mode"
                ]
            },
            "EditorCustomersChanged": {
                "type": "object",
                "properties": {
                    "changed": {
                        "type": "integer"
                    }
                },
                "required": [
                    "changed"
                ]
            },
            "EditorDedupeOptionsByEnum": {
                "enum": [
                    "url",
                    "name",
                    "stream_id",
                    "epg_id"
                ],
                "type": "string",
                "description": "* `url` - url\n* `name` - name\n* `stream_id` - stream_id\n* `epg_id` - epg_id"
            },
            "EditorDedupeOptionsRequest": {
                "type": "object",
                "properties": {
                    "by": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorDedupeOptionsByEnum"
                            }
                        ],
                        "default": "name"
                    }
                }
            },
            "EditorDetail": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "EditorDomainCheck": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean"
                    },
                    "detail": {
                        "type": "string",
                        "description": "What was found, in a sentence."
                    }
                },
                "required": [
                    "detail",
                    "ok"
                ]
            },
            "EditorDuplicates": {
                "type": "object",
                "properties": {
                    "by": {
                        "type": "string",
                        "description": "What the rows were compared by."
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {
                                "type": "integer"
                            }
                        },
                        "description": "The ids of each group of duplicates, in grid order."
                    },
                    "count": {
                        "type": "integer",
                        "description": "Rows in all the groups."
                    }
                },
                "required": [
                    "by",
                    "count",
                    "groups"
                ]
            },
            "EditorEditRecord": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "seq": {
                        "type": "integer",
                        "description": "Its place in the playlist's history."
                    },
                    "label": {
                        "type": "string",
                        "description": "What was done, in words."
                    },
                    "operation": {
                        "type": "string"
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many entries it changed."
                    },
                    "undoable": {
                        "type": "boolean"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "count",
                    "created_at",
                    "id",
                    "label",
                    "operation",
                    "seq",
                    "undoable"
                ]
            },
            "EditorEditResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorEditRecord"
                            }
                        ],
                        "nullable": true,
                        "description": "The history record this edit made; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "The changed entries, each a list of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    }
                },
                "required": [
                    "change",
                    "rows",
                    "version"
                ]
            },
            "EditorEntry": {
                "type": "object",
                "description": "One channel, movie or TV show, everything about it.",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "kind": {
                        "type": "string",
                        "description": "`live`, `movie` or `series`."
                    },
                    "category": {
                        "type": "integer",
                        "description": "Its category's id."
                    },
                    "category_name": {
                        "type": "string"
                    },
                    "provider": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The provider it comes from; null for a row added by hand."
                    },
                    "provider_key": {
                        "type": "string",
                        "description": "Its id at the provider."
                    },
                    "source_name": {
                        "type": "string",
                        "description": "Its name at the provider."
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string",
                        "description": "The stream address players open."
                    },
                    "logo": {
                        "type": "string"
                    },
                    "epg_id": {
                        "type": "string",
                        "description": "The guide channel it shows the programmes of."
                    },
                    "epg_shift": {
                        "type": "number",
                        "format": "double",
                        "description": "Hours added to its guide times."
                    },
                    "number": {
                        "type": "integer",
                        "description": "Channel number; -1: none."
                    },
                    "catchup_days": {
                        "type": "integer",
                        "description": "Days of catch-up players are told about."
                    },
                    "tmdb_id": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Its TMDB id (movies and TV shows)."
                    },
                    "rating": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "info": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Plot, cast, genre, poster… of a movie or TV show."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Rows are listed by position in their category."
                    },
                    "hidden": {
                        "type": "boolean",
                        "description": "Hidden from the playlist players get."
                    },
                    "sync_name": {
                        "type": "boolean",
                        "description": "Takes the provider's name again at each sync."
                    },
                    "deleted_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it went to the recycle bin; null when it is not there."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "episodes": {
                        "type": "integer",
                        "nullable": true,
                        "description": "A TV show's episodes; null for channels and movies, and while they are not fetched yet."
                    }
                },
                "required": [
                    "catchup_days",
                    "category",
                    "category_name",
                    "created_at",
                    "deleted_at",
                    "epg_id",
                    "epg_shift",
                    "episodes",
                    "hidden",
                    "id",
                    "info",
                    "kind",
                    "logo",
                    "name",
                    "number",
                    "position",
                    "provider",
                    "provider_key",
                    "rating",
                    "source_name",
                    "sync_name",
                    "tmdb_id",
                    "updated_at",
                    "url"
                ]
            },
            "EditorEntryCreateRequest": {
                "type": "object",
                "description": "A new row: its category and name, and any other field.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "maxLength": 2000
                    },
                    "logo": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "epg_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "epg_shift": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,3}(?:\\.\\d{0,2})?$"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 9999999,
                        "minimum": -1
                    },
                    "catchup_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 0
                    },
                    "tmdb_id": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 1,
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,2})?$",
                        "nullable": true
                    },
                    "info": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "top": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "category",
                    "name"
                ]
            },
            "EditorEntryFieldsRequest": {
                "type": "object",
                "description": "What a row's inspector edits. Every field optional.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "maxLength": 2000
                    },
                    "logo": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "epg_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "epg_shift": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,3}(?:\\.\\d{0,2})?$"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 9999999,
                        "minimum": -1
                    },
                    "catchup_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 0
                    },
                    "tmdb_id": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 1,
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,2})?$",
                        "nullable": true
                    },
                    "info": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    }
                }
            },
            "EditorEntryIdsRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorEntryMovePlaceEnum": {
                "enum": [
                    "top",
                    "bottom"
                ],
                "type": "string",
                "description": "* `top` - top\n* `bottom` - bottom"
            },
            "EditorEntryMoveRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "place": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorEntryMovePlaceEnum"
                            }
                        ],
                        "default": "bottom"
                    },
                    "copy": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorEntryReorderRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "before": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "after": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "category",
                    "ids"
                ]
            },
            "EditorEntryRestoreRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorEntrySaveItemRequest": {
                "type": "object",
                "description": "One row: its id and the fields to change.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "maxLength": 2000
                    },
                    "logo": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "epg_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "epg_shift": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,3}(?:\\.\\d{0,2})?$"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 9999999,
                        "minimum": -1
                    },
                    "catchup_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 0
                    },
                    "tmdb_id": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 1,
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,2})?$",
                        "nullable": true
                    },
                    "info": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "hidden": {
                        "type": "boolean"
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "id": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "id"
                ]
            },
            "EditorEntrySaveRequest": {
                "type": "object",
                "description": "`items`, or `ids` with `set`.",
                "properties": {
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEntrySaveItemRequest"
                        },
                        "description": "Each row with its own values."
                    },
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "description": "Rows that all take the values of `set`.",
                        "maxItems": 300000
                    },
                    "set": {
                        "$ref": "#/components/schemas/EditorEntryFieldsRequest"
                    }
                }
            },
            "EditorEntrySortByEnum": {
                "enum": [
                    "name",
                    "number",
                    "epg_id",
                    "url",
                    "created_at",
                    "updated_at",
                    "rating",
                    "tmdb_id",
                    "last_episode",
                    "provider"
                ],
                "type": "string",
                "description": "* `name` - name\n* `number` - number\n* `epg_id` - epg_id\n* `url` - url\n* `created_at` - created_at\n* `updated_at` - updated_at\n* `rating` - rating\n* `tmdb_id` - tmdb_id\n* `last_episode` - last_episode\n* `provider` - provider"
            },
            "EditorEntrySortRequest": {
                "type": "object",
                "properties": {
                    "target": {
                        "$ref": "#/components/schemas/EditorEntrySortTargetEnum"
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "by": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorEntrySortByEnum"
                            }
                        ],
                        "default": "name"
                    },
                    "desc": {
                        "type": "boolean",
                        "default": false
                    },
                    "provider": {
                        "type": "integer",
                        "minimum": 1,
                        "nullable": true
                    }
                },
                "required": [
                    "target"
                ]
            },
            "EditorEntrySortTargetEnum": {
                "enum": [
                    "categories",
                    "all",
                    "category",
                    "selection"
                ],
                "type": "string",
                "description": "* `categories` - categories\n* `all` - all\n* `category` - category\n* `selection` - selection"
            },
            "EditorEpisode": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "season": {
                        "type": "integer",
                        "description": "-1: none."
                    },
                    "number": {
                        "type": "integer",
                        "description": "-1: none."
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string",
                        "description": "The stream address players open."
                    },
                    "info": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "deleted_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it went to the recycle bin; null when it is not there."
                    }
                },
                "required": [
                    "deleted_at",
                    "id",
                    "info",
                    "name",
                    "number",
                    "season",
                    "url"
                ]
            },
            "EditorEpisodeCreateRequest": {
                "type": "object",
                "properties": {
                    "season": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": -1
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "name": {
                        "type": "string",
                        "default": "",
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    }
                },
                "required": [
                    "season",
                    "url"
                ]
            },
            "EditorEpisodeIdsRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 50000
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorEpisodeItemRequest": {
                "type": "object",
                "properties": {
                    "season": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": -1
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    },
                    "id": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                "required": [
                    "id"
                ]
            },
            "EditorEpisodeList": {
                "type": "object",
                "properties": {
                    "series": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorEntry"
                            }
                        ],
                        "description": "The TV show."
                    },
                    "episodes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEpisode"
                        },
                        "description": "By season and number."
                    },
                    "error": {
                        "type": "string",
                        "description": "Why the provider's episodes could not be fetched; '' when they were."
                    }
                },
                "required": [
                    "episodes",
                    "error",
                    "series"
                ]
            },
            "EditorEpisodeMoveRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 50000
                    },
                    "series": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "collisions": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CollisionsEnum"
                            }
                        ],
                        "default": "skip"
                    }
                },
                "required": [
                    "ids",
                    "series"
                ]
            },
            "EditorEpisodeMoveResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "The TV shows' rows (their episode counts change). Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "episodes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEpisode"
                        },
                        "nullable": true,
                        "description": "The episodes it changed; null when there are too many to send: load them again."
                    },
                    "moved": {
                        "type": "integer"
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Episodes whose season and number the other TV show already had."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "episodes",
                    "moved",
                    "removed",
                    "rows",
                    "skipped",
                    "version"
                ]
            },
            "EditorEpisodeSaveRequest": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEpisodeItemRequest"
                        },
                        "maxItems": 10000
                    }
                },
                "required": [
                    "items"
                ]
            },
            "EditorEpisodesResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "The TV shows' rows (their episode counts change). Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "episodes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEpisode"
                        },
                        "nullable": true,
                        "description": "The episodes it changed; null when there are too many to send: load them again."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "episodes",
                    "removed",
                    "rows",
                    "version"
                ]
            },
            "EditorEpisodesToChannelsRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 50000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "kind": {
                        "$ref": "#/components/schemas/LiveOrMovieEnum"
                    },
                    "keep": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "category",
                    "ids"
                ]
            },
            "EditorEpisodesToChannelsResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "The TV shows' rows (their episode counts change). Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "episodes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorEpisode"
                        },
                        "nullable": true,
                        "description": "The episodes it changed; null when there are too many to send: load them again."
                    },
                    "created": {
                        "type": "integer",
                        "description": "Rows made."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Episodes left out: already there."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "created",
                    "episodes",
                    "removed",
                    "rows",
                    "skipped",
                    "version"
                ]
            },
            "EditorExportText": {
                "type": "object",
                "properties": {
                    "m3u": {
                        "type": "string"
                    },
                    "xtream": {
                        "type": "string"
                    },
                    "web_player": {
                        "type": "string"
                    },
                    "enigma2": {
                        "type": "string"
                    }
                },
                "required": [
                    "enigma2",
                    "m3u",
                    "web_player",
                    "xtream"
                ]
            },
            "EditorExternalGuide": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "description": "`checking` while it is first checked, `error` when it failed."
                    },
                    "last_imported_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "last_error": {
                        "type": "string"
                    },
                    "channels": {
                        "type": "integer"
                    },
                    "programmes": {
                        "type": "integer"
                    },
                    "mine": {
                        "type": "boolean",
                        "description": "Added from the playlist editor."
                    }
                },
                "required": [
                    "channels",
                    "id",
                    "last_error",
                    "last_imported_at",
                    "mine",
                    "name",
                    "programmes",
                    "status",
                    "url"
                ]
            },
            "EditorFetchEpisodesRequest": {
                "type": "object",
                "properties": {
                    "scope": {}
                }
            },
            "EditorFormatOptionsFormatEnum": {
                "enum": [
                    "ts",
                    "live_ts",
                    "live_hls"
                ],
                "type": "string",
                "description": "* `ts` - ts\n* `live_ts` - live_ts\n* `live_hls` - live_hls"
            },
            "EditorFormatOptionsRequest": {
                "type": "object",
                "properties": {
                    "format": {
                        "$ref": "#/components/schemas/EditorFormatOptionsFormatEnum"
                    },
                    "provider": {
                        "type": "integer",
                        "minimum": 1,
                        "nullable": true
                    }
                },
                "required": [
                    "format"
                ]
            },
            "EditorGrid": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version: it moves with every change."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        }
                    },
                    "columns": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The names of the values in each row."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "Every row of the list, categories by position and rows by position in their category. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    }
                },
                "required": [
                    "categories",
                    "columns",
                    "rows",
                    "version"
                ]
            },
            "EditorGuideChannel": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The guide id to give a channel."
                    },
                    "name": {
                        "type": "string"
                    },
                    "logo": {
                        "type": "string"
                    },
                    "until": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "The end of its guide."
                    },
                    "days": {
                        "type": "number",
                        "format": "double",
                        "nullable": true,
                        "description": "Days of guide left."
                    }
                },
                "required": [
                    "days",
                    "id",
                    "logo",
                    "name",
                    "until"
                ]
            },
            "EditorGuideChannelPage": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer",
                        "description": "How many match in all."
                    },
                    "offset": {
                        "type": "integer"
                    },
                    "limit": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorGuideChannel"
                        }
                    }
                },
                "required": [
                    "count",
                    "limit",
                    "offset",
                    "results"
                ]
            },
            "EditorGuideCheckStarted": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The background task: follow it with `GET /editor/jobs/{id}/` (`/editor/api/v1/jobs/{id}/` with a token)."
                    },
                    "source": {
                        "$ref": "#/components/schemas/EditorExternalGuide"
                    },
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "job",
                    "message",
                    "source"
                ]
            },
            "EditorGuideCountriesRequest": {
                "type": "object",
                "properties": {
                    "codes": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    }
                },
                "required": [
                    "codes"
                ]
            },
            "EditorGuideCountry": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "channels": {
                        "type": "integer"
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Whether the panel imports it."
                    }
                },
                "required": [
                    "channels",
                    "code",
                    "enabled",
                    "name"
                ]
            },
            "EditorGuideEvent": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "channel": {
                        "type": "integer"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "repeat": {
                        "$ref": "#/components/schemas/RepeatEnum"
                    }
                },
                "required": [
                    "channel",
                    "description",
                    "id",
                    "repeat",
                    "start",
                    "stop",
                    "title"
                ]
            },
            "EditorGuideEventRequest": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 300
                    },
                    "description": {
                        "type": "string",
                        "default": "",
                        "maxLength": 5000
                    },
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "repeat": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RepeatEnum"
                            }
                        ],
                        "default": "none"
                    }
                },
                "required": [
                    "start",
                    "stop",
                    "title"
                ]
            },
            "EditorGuideSource": {
                "type": "object",
                "properties": {
                    "id": {
                        "oneOf": [
                            {
                                "type": "integer"
                            },
                            {
                                "type": "string",
                                "enum": [
                                    "creator"
                                ]
                            }
                        ]
                    },
                    "type": {
                        "$ref": "#/components/schemas/EditorGuideSourceTypeEnum"
                    },
                    "name": {
                        "type": "string"
                    },
                    "channels": {
                        "type": "integer"
                    },
                    "long": {
                        "type": "integer",
                        "description": "Channels with two days of guide or more."
                    },
                    "short": {
                        "type": "integer",
                        "description": "Channels with less."
                    },
                    "status": {
                        "type": "string"
                    },
                    "mine": {
                        "type": "boolean",
                        "description": "Added by this account."
                    }
                },
                "required": [
                    "channels",
                    "id",
                    "long",
                    "mine",
                    "name",
                    "short",
                    "status",
                    "type"
                ]
            },
            "EditorGuideSourceTypeEnum": {
                "enum": [
                    "country",
                    "url",
                    "creator"
                ],
                "type": "string",
                "description": "* `country` - country\n* `url` - url\n* `creator` - creator"
            },
            "EditorHistory": {
                "type": "object",
                "properties": {
                    "changes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorChange"
                        },
                        "description": "Latest first."
                    },
                    "can_undo": {
                        "type": "boolean"
                    },
                    "can_redo": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "can_redo",
                    "can_undo",
                    "changes"
                ]
            },
            "EditorImportRequest": {
                "type": "object",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/EditorSourceRequest"
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ContentKindEnum"
                        },
                        "default": [
                            "live"
                        ]
                    },
                    "attributes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/AttributesEnum"
                        },
                        "default": [
                            "category",
                            "logo"
                        ]
                    },
                    "categories": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string",
                                "minLength": 1
                            },
                            "maxItems": 100000
                        }
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    }
                },
                "required": [
                    "name",
                    "source"
                ]
            },
            "EditorInfoMatchRequest": {
                "type": "object",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/MovieOrSeriesEnum"
                    },
                    "scope": {},
                    "override": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "boolean"
                        }
                    }
                },
                "required": [
                    "kind",
                    "scope"
                ]
            },
            "EditorKindOptions": {
                "type": "object",
                "properties": {
                    "sync_new": {
                        "type": "boolean",
                        "description": "Add new entries and categories."
                    },
                    "import_all": {
                        "type": "boolean",
                        "description": "Also take back from the bin what the provider lists."
                    },
                    "on_top": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Categories (ids) where new entries go at the top."
                    },
                    "provider_epg": {
                        "type": "boolean",
                        "description": "New channels take the provider's guide id."
                    },
                    "sync_names": {
                        "type": "boolean",
                        "description": "Rename channels marked to follow the provider."
                    },
                    "catchup": {
                        "type": "boolean",
                        "description": "Catch-up days and server time, from the provider."
                    },
                    "deletions": {
                        "type": "boolean",
                        "description": "What the provider removed goes to the bin."
                    },
                    "safe_deletions": {
                        "type": "boolean",
                        "description": "Not when it would be more than 1,500 or half of them."
                    },
                    "delete_categories": {
                        "type": "boolean",
                        "description": "Remove categories the provider dropped, once empty."
                    },
                    "any_domain": {
                        "type": "boolean",
                        "description": "Accept streams on another address than the list."
                    }
                }
            },
            "EditorKindOptionsRequest": {
                "type": "object",
                "properties": {
                    "sync_new": {
                        "type": "boolean",
                        "description": "Add new entries and categories."
                    },
                    "import_all": {
                        "type": "boolean",
                        "description": "Also take back from the bin what the provider lists."
                    },
                    "on_top": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Categories (ids) where new entries go at the top."
                    },
                    "provider_epg": {
                        "type": "boolean",
                        "description": "New channels take the provider's guide id."
                    },
                    "sync_names": {
                        "type": "boolean",
                        "description": "Rename channels marked to follow the provider."
                    },
                    "catchup": {
                        "type": "boolean",
                        "description": "Catch-up days and server time, from the provider."
                    },
                    "deletions": {
                        "type": "boolean",
                        "description": "What the provider removed goes to the bin."
                    },
                    "safe_deletions": {
                        "type": "boolean",
                        "description": "Not when it would be more than 1,500 or half of them."
                    },
                    "delete_categories": {
                        "type": "boolean",
                        "description": "Remove categories the provider dropped, once empty."
                    },
                    "any_domain": {
                        "type": "boolean",
                        "description": "Accept streams on another address than the list."
                    }
                }
            },
            "EditorLinks": {
                "type": "object",
                "properties": {
                    "m3u": {
                        "type": "string",
                        "description": "The M3U playlist link."
                    },
                    "epg": {
                        "type": "string",
                        "description": "The TV guide (XMLTV) link."
                    },
                    "xtream": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorPlayerLogin"
                            }
                        ],
                        "description": "The login players sign in with."
                    },
                    "enigma2": {
                        "type": "string",
                        "description": "A command to run on a satellite box."
                    },
                    "web_player": {
                        "type": "string"
                    },
                    "mag": {
                        "type": "string",
                        "nullable": true,
                        "description": "Always null for now."
                    },
                    "export_text": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorExportText"
                            }
                        ],
                        "description": "The same, as text ready to send."
                    }
                },
                "required": [
                    "enigma2",
                    "epg",
                    "export_text",
                    "m3u",
                    "mag",
                    "web_player",
                    "xtream"
                ]
            },
            "EditorLogin": {
                "type": "object",
                "properties": {
                    "username": {
                        "type": "string"
                    },
                    "password": {
                        "type": "string"
                    }
                },
                "required": [
                    "password",
                    "username"
                ]
            },
            "EditorLoginCheck": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "description": "Whether the username can be used."
                    },
                    "detail": {
                        "type": "string",
                        "description": "Why, in a sentence to show."
                    }
                },
                "required": [
                    "detail",
                    "ok"
                ]
            },
            "EditorLogo": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "source": {
                        "$ref": "#/components/schemas/EditorLogoSourceEnum"
                    }
                },
                "required": [
                    "name",
                    "source",
                    "url"
                ]
            },
            "EditorLogoSourceEnum": {
                "enum": [
                    "guide",
                    "wikimedia"
                ],
                "type": "string",
                "description": "* `guide` - guide\n* `wikimedia` - wikimedia"
            },
            "EditorMapping": {
                "type": "object",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "`live`, `movie` or `series`."
                    },
                    "provider_key": {
                        "type": "string",
                        "description": "The provider's category id."
                    },
                    "provider_name": {
                        "type": "string"
                    },
                    "category": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The playlist's category it goes to; null for a new one."
                    },
                    "sync": {
                        "type": "boolean",
                        "description": "Whether this category is kept in step."
                    }
                },
                "required": [
                    "kind",
                    "provider_key"
                ]
            },
            "EditorMappingRequest": {
                "type": "object",
                "properties": {
                    "kind": {
                        "type": "string",
                        "minLength": 1,
                        "description": "`live`, `movie` or `series`."
                    },
                    "provider_key": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The provider's category id."
                    },
                    "provider_name": {
                        "type": "string",
                        "minLength": 1
                    },
                    "category": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The playlist's category it goes to; null for a new one."
                    },
                    "sync": {
                        "type": "boolean",
                        "description": "Whether this category is kept in step."
                    }
                },
                "required": [
                    "kind",
                    "provider_key"
                ]
            },
            "EditorMatchRequest": {
                "type": "object",
                "properties": {
                    "scope": {},
                    "source": {
                        "type": "string",
                        "nullable": true,
                        "minLength": 1,
                        "maxLength": 20
                    },
                    "precision": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 40
                    },
                    "override": {
                        "type": "boolean",
                        "nullable": true
                    }
                },
                "required": [
                    "scope"
                ]
            },
            "EditorNameAsGuideRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "on": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorNewLoginRequest": {
                "type": "object",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1
                    },
                    "password": {
                        "type": "string",
                        "minLength": 1
                    }
                }
            },
            "EditorNewProviderRequest": {
                "type": "object",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/EditorSourceRequest"
                    }
                },
                "required": [
                    "source"
                ]
            },
            "EditorNumbersRequest": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "integer",
                        "maximum": 9000000,
                        "minimum": 0,
                        "default": 1
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "continue": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "EditorOptimizeOptionsRequest": {
                "type": "object",
                "properties": {
                    "country_prefix": {
                        "type": "boolean",
                        "default": true
                    },
                    "quality": {
                        "type": "boolean",
                        "default": false
                    },
                    "symbols": {
                        "type": "boolean",
                        "default": true
                    },
                    "brackets": {
                        "type": "boolean",
                        "default": false
                    },
                    "spaces": {
                        "type": "boolean",
                        "default": true
                    },
                    "years": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "EditorOutsideGuideRequest": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "minLength": 1,
                        "maxLength": 1000
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    }
                },
                "required": [
                    "name",
                    "url"
                ]
            },
            "EditorOwnGuideChannel": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "tvg_id": {
                        "type": "string",
                        "description": "The guide id channels use."
                    },
                    "name": {
                        "type": "string"
                    },
                    "events": {
                        "type": "integer",
                        "description": "Its programmes."
                    }
                },
                "required": [
                    "events",
                    "id",
                    "name",
                    "tvg_id"
                ]
            },
            "EditorOwnGuideChannelRequest": {
                "type": "object",
                "properties": {
                    "tvg_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120,
                        "pattern": "^[^\\s<>\"&]{1,120}$"
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    }
                },
                "required": [
                    "name",
                    "tvg_id"
                ]
            },
            "EditorPair": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The playlist's entry."
                    },
                    "name": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string",
                        "description": "`live` or `movie`."
                    },
                    "candidate": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorPairedEntry"
                            }
                        ],
                        "nullable": true,
                        "description": "The new provider's entry it takes; null for none."
                    },
                    "confidence": {
                        "type": "number",
                        "format": "double",
                        "description": "0 to 1; from 0.9 the pair is sure."
                    },
                    "how": {
                        "type": "string",
                        "nullable": true,
                        "description": "`name`, `id` or `close`."
                    },
                    "variants": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPairedEntry"
                        },
                        "description": "Other close entries to pick instead."
                    }
                },
                "required": [
                    "candidate",
                    "confidence",
                    "how",
                    "id",
                    "kind",
                    "name",
                    "variants"
                ]
            },
            "EditorPairPage": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "offset": {
                        "type": "integer"
                    },
                    "limit": {
                        "type": "integer"
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPair"
                        }
                    }
                },
                "required": [
                    "limit",
                    "offset",
                    "rows",
                    "total"
                ]
            },
            "EditorPairedEntry": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The new provider's id for it."
                    },
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string"
                    }
                },
                "required": [
                    "key",
                    "name",
                    "url"
                ]
            },
            "EditorPickedEntriesRequest": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "keys": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 64
                        },
                        "maxItems": 50000
                    },
                    "all": {
                        "type": "boolean",
                        "default": false
                    },
                    "category": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "job"
                ]
            },
            "EditorPickedImport": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorEditRecord"
                            }
                        ],
                        "nullable": true,
                        "description": "The history record this edit made; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "description": "The changed entries, each a list of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "created": {
                        "type": "integer",
                        "description": "Entries added."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Entries already in the playlist (the bin too)."
                    },
                    "message": {
                        "type": "string",
                        "description": "What was done, in a sentence."
                    }
                },
                "required": [
                    "change",
                    "created",
                    "message",
                    "rows",
                    "skipped",
                    "version"
                ]
            },
            "EditorPlayerLogin": {
                "type": "object",
                "properties": {
                    "server": {
                        "type": "string"
                    },
                    "username": {
                        "type": "string"
                    },
                    "password": {
                        "type": "string"
                    },
                    "m3u": {
                        "type": "string",
                        "description": "The M3U link made from this login."
                    },
                    "epg": {
                        "type": "string",
                        "description": "The guide link made from this login."
                    }
                },
                "required": [
                    "epg",
                    "m3u",
                    "password",
                    "server",
                    "username"
                ]
            },
            "EditorPlaylist": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "position": {
                        "type": "integer",
                        "description": "Playlists are listed by position."
                    },
                    "owner": {
                        "type": "string",
                        "description": "The username of the account that owns it."
                    },
                    "username": {
                        "type": "string",
                        "description": "The login players sign in with to this playlist."
                    },
                    "password": {
                        "type": "string"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "The expiry date players are told; null: none."
                    },
                    "message": {
                        "type": "string",
                        "description": "The message players are told."
                    },
                    "counts": {
                        "$ref": "#/components/schemas/EditorPlaylistCounts"
                    },
                    "providers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPlaylistProvider"
                        }
                    },
                    "last_synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "version": {
                        "type": "integer",
                        "description": "Moves with every change to what its links serve."
                    },
                    "custom_domain": {
                        "type": "string",
                        "description": "The domain its links use; '' for the panel's."
                    }
                },
                "required": [
                    "counts",
                    "custom_domain",
                    "expiry",
                    "id",
                    "last_synced_at",
                    "message",
                    "name",
                    "owner",
                    "password",
                    "position",
                    "providers",
                    "updated_at",
                    "username",
                    "version"
                ]
            },
            "EditorPlaylistCopy": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The background task copying the content."
                    },
                    "playlist": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorPlaylistDetail"
                            }
                        ],
                        "description": "The new playlist."
                    }
                },
                "required": [
                    "job",
                    "playlist"
                ]
            },
            "EditorPlaylistCounts": {
                "type": "object",
                "properties": {
                    "live": {
                        "type": "integer",
                        "description": "Channels."
                    },
                    "movie": {
                        "type": "integer",
                        "description": "Movies."
                    },
                    "series": {
                        "type": "integer",
                        "description": "TV shows."
                    },
                    "episodes": {
                        "type": "integer"
                    },
                    "users": {
                        "type": "integer",
                        "description": "Customers it is handed to."
                    }
                },
                "required": [
                    "episodes",
                    "live",
                    "movie",
                    "series",
                    "users"
                ]
            },
            "EditorPlaylistCreateRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "maxLength": 120
                    }
                }
            },
            "EditorPlaylistDetail": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "position": {
                        "type": "integer",
                        "description": "Playlists are listed by position."
                    },
                    "owner": {
                        "type": "string",
                        "description": "The username of the account that owns it."
                    },
                    "username": {
                        "type": "string",
                        "description": "The login players sign in with to this playlist."
                    },
                    "password": {
                        "type": "string"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "The expiry date players are told; null: none."
                    },
                    "message": {
                        "type": "string",
                        "description": "The message players are told."
                    },
                    "counts": {
                        "$ref": "#/components/schemas/EditorPlaylistCounts"
                    },
                    "providers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPlaylistProvider"
                        }
                    },
                    "last_synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "version": {
                        "type": "integer",
                        "description": "Moves with every change to what its links serve."
                    },
                    "custom_domain": {
                        "type": "string",
                        "description": "The domain its links use; '' for the panel's."
                    },
                    "settings": {
                        "$ref": "#/components/schemas/EditorPlaylistSettings"
                    }
                },
                "required": [
                    "counts",
                    "custom_domain",
                    "expiry",
                    "id",
                    "last_synced_at",
                    "message",
                    "name",
                    "owner",
                    "password",
                    "position",
                    "providers",
                    "settings",
                    "updated_at",
                    "username",
                    "version"
                ]
            },
            "EditorPlaylistList": {
                "type": "object",
                "properties": {
                    "quotas": {
                        "$ref": "#/components/schemas/EditorQuotas"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPlaylist"
                        }
                    }
                },
                "required": [
                    "quotas",
                    "results"
                ]
            },
            "EditorPlaylistLoginRequest": {
                "type": "object",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "password": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    }
                },
                "required": [
                    "password",
                    "username"
                ]
            },
            "EditorPlaylistProvider": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "type": {
                        "type": "string",
                        "description": "How its content is read, e.g. `xtream` (a provider login: server, username and password) or `m3u` (a playlist link)."
                    },
                    "url": {
                        "type": "string",
                        "description": "The address its streams start with."
                    },
                    "label": {
                        "type": "string"
                    },
                    "source": {
                        "type": "string",
                        "description": "An `m3u` provider's playlist link, its password hidden; '' for other types."
                    }
                },
                "required": [
                    "id",
                    "label",
                    "source",
                    "type",
                    "url"
                ]
            },
            "EditorPlaylistReorderRequest": {
                "type": "object",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000
                    }
                },
                "required": [
                    "ids"
                ]
            },
            "EditorPlaylistSettings": {
                "type": "object",
                "description": "Every setting of a playlist.",
                "properties": {
                    "max_connections": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "track_connections": {
                        "type": "boolean"
                    },
                    "limit_connections": {
                        "type": "boolean"
                    },
                    "time_shift": {
                        "type": "number",
                        "format": "double",
                        "description": "Hours added to the server time players are told."
                    },
                    "language": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "provider_vod_info": {
                        "type": "boolean"
                    },
                    "auto_vod_info": {
                        "type": "boolean"
                    },
                    "vod_info_options": {},
                    "epg_gzip": {
                        "type": "boolean"
                    },
                    "use_tvg_id": {
                        "type": "boolean"
                    },
                    "epg_dummy_text": {
                        "type": "string",
                        "maxLength": 200
                    },
                    "epg_days": {
                        "type": "integer",
                        "maximum": 14,
                        "minimum": 1
                    },
                    "epg_fields": {},
                    "epg_precision": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 40
                    },
                    "epg_override": {
                        "type": "boolean"
                    },
                    "epg_hide_short": {
                        "type": "boolean"
                    },
                    "epg_show_ids": {
                        "type": "boolean"
                    },
                    "logo_precision": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 40
                    },
                    "logo_override": {
                        "type": "boolean"
                    },
                    "hidden_provider": {
                        "type": "boolean"
                    },
                    "custom_domain": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "welcome": {},
                    "app_color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "app_logo": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "stream_format": {
                        "$ref": "#/components/schemas/StreamFormatEnum"
                    }
                },
                "required": [
                    "time_shift"
                ]
            },
            "EditorPlaylistTaskStarted": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The background task: follow it with `GET /editor/jobs/{id}/` (`/editor/api/v1/jobs/{id}/` with a token)."
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The playlist the task fills."
                    }
                },
                "required": [
                    "job",
                    "playlist"
                ]
            },
            "EditorPreferences": {
                "type": "object",
                "properties": {
                    "values": {
                        "type": "object",
                        "additionalProperties": {}
                    }
                },
                "required": [
                    "values"
                ]
            },
            "EditorPreferencesRequest": {
                "type": "object",
                "properties": {
                    "values": {
                        "type": "object",
                        "additionalProperties": {}
                    }
                },
                "required": [
                    "values"
                ]
            },
            "EditorPreset": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "icon": {
                        "type": "string",
                        "maxLength": 40
                    },
                    "steps": {},
                    "kinds": {},
                    "position": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "id",
                    "name"
                ]
            },
            "EditorPresetBundle": {
                "type": "object",
                "properties": {
                    "presets": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPresetExport"
                        }
                    }
                },
                "required": [
                    "presets"
                ]
            },
            "EditorPresetBundleRequest": {
                "type": "object",
                "properties": {
                    "presets": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPresetExportRequest"
                        }
                    }
                },
                "required": [
                    "presets"
                ]
            },
            "EditorPresetExport": {
                "type": "object",
                "description": "One preset as an export holds it.",
                "properties": {
                    "name": {
                        "type": "string",
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "icon": {
                        "type": "string",
                        "maxLength": 40
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPresetStep"
                        }
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Where it is offered: some of `live`, `movie`, `series`; empty: everywhere."
                    }
                },
                "required": [
                    "name",
                    "steps"
                ]
            },
            "EditorPresetExportRequest": {
                "type": "object",
                "description": "One preset as an export holds it.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "icon": {
                        "type": "string",
                        "maxLength": 40
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPresetStepRequest"
                        }
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        },
                        "description": "Where it is offered: some of `live`, `movie`, `series`; empty: everywhere."
                    }
                },
                "required": [
                    "name",
                    "steps"
                ]
            },
            "EditorPresetOptionsRequest": {
                "type": "object",
                "description": "The options of the `preset` tool: a saved preset, or steps.",
                "properties": {
                    "preset": {
                        "type": "integer",
                        "description": "A saved preset, by id."
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorPresetStepRequest"
                        },
                        "description": "Or the steps to run."
                    }
                }
            },
            "EditorPresetRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "icon": {
                        "type": "string",
                        "maxLength": 40
                    },
                    "steps": {},
                    "kinds": {},
                    "position": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    }
                },
                "required": [
                    "name"
                ]
            },
            "EditorPresetSample": {
                "type": "object",
                "properties": {
                    "output": {
                        "type": "string",
                        "description": "The sample after every step."
                    },
                    "deleted": {
                        "type": "boolean",
                        "description": "Whether a step would send the row to the recycle bin."
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The sample after each step, in order."
                    }
                },
                "required": [
                    "deleted",
                    "output",
                    "steps"
                ]
            },
            "EditorPresetStep": {
                "type": "object",
                "description": "One step: a bulk tool and its options.",
                "properties": {
                    "tool": {
                        "$ref": "#/components/schemas/ToolEnum"
                    },
                    "options": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "The tool's options, as the tool takes them."
                    }
                },
                "required": [
                    "options",
                    "tool"
                ]
            },
            "EditorPresetStepRequest": {
                "type": "object",
                "description": "One step: a bulk tool and its options.",
                "properties": {
                    "tool": {
                        "$ref": "#/components/schemas/ToolEnum"
                    },
                    "options": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "The tool's options, as the tool takes them."
                    }
                },
                "required": [
                    "options",
                    "tool"
                ]
            },
            "EditorPresetTestKindEnum": {
                "enum": [
                    "live",
                    "movie",
                    "series"
                ],
                "type": "string",
                "description": "* `live` - Live channel\n* `movie` - Film\n* `series` - TV show"
            },
            "EditorPresetTestRequest": {
                "type": "object",
                "properties": {
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "sample": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorPresetTestKindEnum"
                            }
                        ],
                        "default": "live"
                    }
                },
                "required": [
                    "sample",
                    "steps"
                ]
            },
            "EditorProgramme": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "title": {
                        "type": "string"
                    },
                    "sub_title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "category": {
                        "type": "string"
                    }
                },
                "required": [
                    "category",
                    "description",
                    "start",
                    "stop",
                    "sub_title",
                    "title"
                ]
            },
            "EditorProvider": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "type": {
                        "$ref": "#/components/schemas/EditorProviderTypeEnum"
                    },
                    "url": {
                        "type": "string",
                        "description": "The address its streams start with."
                    },
                    "param1": {
                        "type": "string",
                        "description": "Username, key or MAC address, by type."
                    },
                    "has_param2": {
                        "type": "boolean",
                        "description": "Whether a password is set (it is never shown)."
                    },
                    "label": {
                        "type": "string"
                    },
                    "source_url": {
                        "type": "boolean",
                        "description": "Whether an M3U address provider has its own list address."
                    },
                    "source": {
                        "type": "string",
                        "description": "The list address, with its secrets hidden ('' when none)."
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "The provider line's end date, when known."
                    },
                    "max_connections": {
                        "type": "integer",
                        "nullable": true
                    },
                    "streams": {
                        "type": "integer",
                        "description": "Entries that come from it."
                    }
                },
                "required": [
                    "expiry",
                    "has_param2",
                    "id",
                    "label",
                    "max_connections",
                    "param1",
                    "source",
                    "source_url",
                    "streams",
                    "type",
                    "url"
                ]
            },
            "EditorProviderCategories": {
                "type": "object",
                "properties": {
                    "live": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorProviderCategory"
                        }
                    },
                    "movie": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorProviderCategory"
                        }
                    },
                    "series": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorProviderCategory"
                        }
                    }
                }
            },
            "EditorProviderCategory": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The provider's category id."
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "key",
                    "name"
                ]
            },
            "EditorProviderLine": {
                "type": "object",
                "properties": {
                    "provider": {
                        "type": "integer",
                        "description": "One of the playlist's providers."
                    },
                    "username": {
                        "type": "string"
                    },
                    "password": {
                        "type": "string"
                    },
                    "dns": {
                        "type": "string",
                        "description": "Another address for this provider ('' for its own)."
                    }
                },
                "required": [
                    "dns",
                    "password",
                    "provider",
                    "username"
                ]
            },
            "EditorProviderMoveRequest": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "choices": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string",
                            "maxLength": 64
                        }
                    },
                    "missing": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MissingEnum"
                            }
                        ],
                        "default": "delete"
                    },
                    "providers": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProvidersEnum"
                            }
                        ],
                        "default": "replace"
                    },
                    "users": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "job"
                ]
            },
            "EditorProviderRemoved": {
                "type": "object",
                "properties": {
                    "removed": {
                        "type": "integer",
                        "description": "Entries deleted with it."
                    }
                },
                "required": [
                    "removed"
                ]
            },
            "EditorProviderRequest": {
                "type": "object",
                "description": "`ProviderSerializer` with its types in plain words, for the API\nreference only.",
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/EditorProviderTypeEnum"
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "param1": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "param2": {
                        "type": "string",
                        "writeOnly": true,
                        "default": "",
                        "maxLength": 255
                    },
                    "label": {
                        "type": "string",
                        "default": "",
                        "maxLength": 120
                    },
                    "source_url": {
                        "type": "string",
                        "writeOnly": true,
                        "default": "",
                        "maxLength": 2000
                    }
                },
                "required": [
                    "type",
                    "url"
                ]
            },
            "EditorProviderTypeEnum": {
                "enum": [
                    "xtream",
                    "m3u",
                    "file",
                    "auth",
                    "apollo",
                    "watch",
                    "xui_mac",
                    "token"
                ],
                "type": "string",
                "description": "* `xtream` - A provider login: server, username and password\n* `m3u` - An M3U address\n* `file` - An M3U file\n* `auth` - An auth key and a profile\n* `apollo` - A stream API login: username and password\n* `watch` - A watch key\n* `xui_mac` - A MAC address\n* `token` - A token"
            },
            "EditorPurgeResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "nullable": true,
                        "description": "The rows it changed, as the grid lists them; null when there are too many to send: load the list again. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "removed_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of categories removed for good."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "removed",
                    "removed_categories",
                    "rows",
                    "version"
                ]
            },
            "EditorQuota": {
                "type": "object",
                "properties": {
                    "used": {
                        "type": "integer"
                    },
                    "max": {
                        "type": "integer",
                        "nullable": true,
                        "description": "null: no limit."
                    }
                },
                "required": [
                    "max",
                    "used"
                ]
            },
            "EditorQuotas": {
                "type": "object",
                "properties": {
                    "playlists": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorQuota"
                            }
                        ],
                        "description": "Playlists the account keeps, and how many it may."
                    },
                    "users": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorQuota"
                            }
                        ],
                        "description": "Customers its playlists are handed to, and how many it may."
                    },
                    "entries": {
                        "type": "integer",
                        "description": "Channels, movies and TV shows a playlist may hold."
                    },
                    "episodes": {
                        "type": "integer",
                        "description": "Episodes a playlist may hold."
                    }
                },
                "required": [
                    "entries",
                    "episodes",
                    "playlists",
                    "users"
                ]
            },
            "EditorReplaceOptionsActionEnum": {
                "enum": [
                    "remove",
                    "replace",
                    "delete"
                ],
                "type": "string",
                "description": "* `remove` - remove\n* `replace` - replace\n* `delete` - delete"
            },
            "EditorReplaceOptionsFieldEnum": {
                "enum": [
                    "name",
                    "url",
                    "logo"
                ],
                "type": "string",
                "description": "* `name` - name\n* `url` - url\n* `logo` - logo"
            },
            "EditorReplaceOptionsMatchEnum": {
                "enum": [
                    "words",
                    "symbols",
                    "always"
                ],
                "type": "string",
                "description": "* `words` - words\n* `symbols` - symbols\n* `always` - always"
            },
            "EditorReplaceOptionsRequest": {
                "type": "object",
                "properties": {
                    "find": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 300
                    },
                    "action": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorReplaceOptionsActionEnum"
                            }
                        ],
                        "default": "remove"
                    },
                    "regex": {
                        "type": "boolean",
                        "default": false
                    },
                    "match": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorReplaceOptionsMatchEnum"
                            }
                        ],
                        "default": "words"
                    },
                    "where": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorReplaceOptionsWhereEnum"
                            }
                        ],
                        "default": "all"
                    },
                    "length": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "default": 7
                    },
                    "field": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorReplaceOptionsFieldEnum"
                            }
                        ],
                        "default": "name"
                    },
                    "case_sensitive": {
                        "type": "boolean",
                        "default": false
                    },
                    "with": {
                        "type": "string",
                        "default": "",
                        "maxLength": 500
                    }
                },
                "required": [
                    "find"
                ]
            },
            "EditorReplaceOptionsWhereEnum": {
                "enum": [
                    "all",
                    "first",
                    "last"
                ],
                "type": "string",
                "description": "* `all` - all\n* `first` - first\n* `last` - last"
            },
            "EditorResetContentRequest": {
                "type": "object",
                "properties": {
                    "live": {
                        "type": "boolean",
                        "default": false
                    },
                    "movie": {
                        "type": "boolean",
                        "default": false
                    },
                    "series": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "EditorResetLinksRequest": {
                "type": "object",
                "properties": {
                    "m3u": {
                        "type": "boolean",
                        "default": false
                    },
                    "epg": {
                        "type": "boolean",
                        "default": false
                    },
                    "login": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "EditorRestoreRequest": {
                "type": "object",
                "properties": {
                    "sections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SectionsEnum"
                        },
                        "description": "What to restore (default: all). In a form, also one comma-separated value."
                    },
                    "file": {
                        "type": "string",
                        "format": "binary",
                        "description": "Up to 500 MB."
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "required": [
                    "file"
                ]
            },
            "EditorScopeRequest": {
                "type": "object",
                "description": "`{\"ids\": […]}`, `{\"categories\": […]}` or `{\"all\": true}`.",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 50000
                    },
                    "all": {
                        "type": "boolean"
                    }
                }
            },
            "EditorSeason": {
                "type": "object",
                "properties": {
                    "number": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string"
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "episode_count": {
                        "type": "integer"
                    }
                },
                "required": [
                    "air_date",
                    "episode_count",
                    "name",
                    "number",
                    "plot",
                    "poster_url"
                ]
            },
            "EditorSettings": {
                "type": "object",
                "properties": {
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "max_playlists": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Playlists per account",
                        "description": "How many playlists one reseller may keep. Administrators have no limit."
                    },
                    "max_users": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Customers per account",
                        "description": "How many customers one reseller may hand playlists to, all playlists together. Administrators have no limit."
                    },
                    "max_entries": {
                        "type": "integer",
                        "maximum": 2000000,
                        "minimum": 1000,
                        "title": "Channels and titles per playlist",
                        "description": "Imports stop adding past this many channels, films and shows together."
                    },
                    "max_episodes": {
                        "type": "integer",
                        "maximum": 5000000,
                        "minimum": 1000,
                        "title": "Episodes per playlist"
                    },
                    "output_cache_seconds": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 0,
                        "title": "Links cache (seconds)",
                        "description": "How long a built playlist or guide is reused before an edit shows. 0 rebuilds on every download."
                    },
                    "live_sync_hours": {
                        "type": "integer",
                        "maximum": 48,
                        "minimum": 1,
                        "title": "Sync channels every (hours)"
                    },
                    "vod_sync_hours": {
                        "type": "integer",
                        "maximum": 168,
                        "minimum": 6,
                        "title": "Sync films and shows every (hours)"
                    },
                    "history_depth": {
                        "type": "integer",
                        "maximum": 1000,
                        "minimum": 10,
                        "title": "Undo steps kept per playlist"
                    },
                    "auto_backups": {
                        "type": "boolean",
                        "title": "Back up playlists automatically",
                        "description": "A copy of every playlist twice a day, kept for a week, plus one a week kept for a month."
                    },
                    "tracking_minutes": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 2,
                        "title": "A customer counts as watching for (minutes)",
                        "description": "After their last request: what \"online\" and the connection limit go by."
                    }
                },
                "required": [
                    "updated_at"
                ]
            },
            "EditorSourcePanelExport": {
                "type": "object",
                "properties": {
                    "filename": {
                        "type": "string"
                    },
                    "content": {
                        "type": "string",
                        "description": "The SQL statements or the Python script."
                    },
                    "count": {
                        "type": "integer",
                        "description": "Streams it updates."
                    },
                    "notes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "What to do by hand, if anything."
                    }
                },
                "required": [
                    "content",
                    "count",
                    "filename",
                    "notes"
                ]
            },
            "EditorSourcePanelExportModeEnum": {
                "enum": [
                    "sql",
                    "python"
                ],
                "type": "string",
                "description": "* `sql` - sql\n* `python` - python"
            },
            "EditorSourcePanelExportRequest": {
                "type": "object",
                "properties": {
                    "mode": {
                        "$ref": "#/components/schemas/EditorSourcePanelExportModeEnum"
                    },
                    "provider": {
                        "type": "integer"
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/LiveOrMovieEnum"
                        },
                        "default": [
                            "live"
                        ]
                    },
                    "fields": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/FieldsEnum"
                        },
                        "default": [
                            "epg",
                            "logo",
                            "name"
                        ]
                    },
                    "order": {
                        "type": "boolean",
                        "default": false
                    },
                    "bouquets": {
                        "type": "boolean",
                        "default": false
                    },
                    "remove_hidden": {
                        "type": "boolean",
                        "default": false
                    },
                    "db": {
                        "type": "object",
                        "additionalProperties": {}
                    }
                },
                "required": [
                    "mode",
                    "provider"
                ]
            },
            "EditorSourceReadRequest": {
                "type": "object",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/EditorSourceRequest"
                    }
                },
                "required": [
                    "source"
                ]
            },
            "EditorSourceRequest": {
                "type": "object",
                "properties": {
                    "type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorSourceTypeEnum"
                            }
                        ],
                        "description": "Where the list comes from. Leave it out to name a provider instead.\n\n* `xtream` - A provider login: url (the server), username and password\n* `m3u` - An M3U address: url\n* `file` - An M3U file sent with POST /editor/uploads/: upload"
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The server (`xtream`) or the M3U address (`m3u`)."
                    },
                    "username": {
                        "type": "string",
                        "minLength": 1
                    },
                    "password": {
                        "type": "string",
                        "minLength": 1
                    },
                    "format": {
                        "type": "string",
                        "minLength": 1,
                        "description": "How channel links are written (`xtream`): `ts` (the default), `live_ts` or `live_hls`."
                    },
                    "upload": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The id `POST /editor/uploads/` answered (`file`)."
                    },
                    "provider": {
                        "type": "integer",
                        "description": "One of the playlist's providers, by id, instead of the above."
                    }
                }
            },
            "EditorSourceScanRequest": {
                "type": "object",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/EditorSourceRequest"
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ContentKindEnum"
                        },
                        "description": "Default: all."
                    }
                },
                "required": [
                    "source"
                ]
            },
            "EditorSourceTypeEnum": {
                "enum": [
                    "xtream",
                    "m3u",
                    "file"
                ],
                "type": "string",
                "description": "* `xtream` - A provider login: url (the server), username and password\n* `m3u` - An M3U address: url\n* `file` - An M3U file sent with POST /editor/uploads/: upload"
            },
            "EditorSyncNowRequest": {
                "type": "object",
                "properties": {
                    "kinds": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        },
                        "description": "Some of `live`, `movie` and `series` (default: all)."
                    }
                }
            },
            "EditorTask": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "type": {
                        "$ref": "#/components/schemas/EditorTaskTypeEnum"
                    },
                    "status": {
                        "$ref": "#/components/schemas/EditorTaskStatusEnum"
                    },
                    "title": {
                        "type": "string"
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "owner": {
                        "type": "string",
                        "nullable": true,
                        "description": "The account's username."
                    },
                    "progress": {
                        "type": "integer",
                        "description": "0 to 100."
                    },
                    "step": {
                        "type": "string",
                        "description": "What it is doing now."
                    },
                    "error": {
                        "type": "string"
                    },
                    "done": {
                        "type": "integer",
                        "nullable": true
                    },
                    "total": {
                        "type": "integer",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "result": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "What it found or did, by type of task. Not in lists."
                    },
                    "log": {
                        "type": "string",
                        "description": "Not in lists."
                    }
                },
                "required": [
                    "created_at",
                    "done",
                    "error",
                    "finished_at",
                    "id",
                    "owner",
                    "playlist",
                    "progress",
                    "started_at",
                    "status",
                    "step",
                    "title",
                    "total",
                    "type",
                    "updated_at"
                ]
            },
            "EditorTaskStarted": {
                "type": "object",
                "properties": {
                    "job": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The background task: follow it with `GET /editor/jobs/{id}/` (`/editor/api/v1/jobs/{id}/` with a token)."
                    }
                },
                "required": [
                    "job"
                ]
            },
            "EditorTaskStatusEnum": {
                "enum": [
                    "queued",
                    "running",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `queued` - Queued\n* `running` - Running\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "EditorTaskTypeEnum": {
                "enum": [
                    "import",
                    "add",
                    "sync",
                    "provider",
                    "restore",
                    "duplicate",
                    "guide",
                    "logos",
                    "info",
                    "migrate",
                    "episodes"
                ],
                "type": "string",
                "description": "* `import` - Playlist import\n* `add` - Content added from another source\n* `sync` - Playlist sync\n* `provider` - Provider change\n* `restore` - Backup restore\n* `duplicate` - Playlist copy\n* `guide` - Guide matching\n* `logos` - Logo matching\n* `info` - Film and show info\n* `migrate` - Move to a new provider\n* `episodes` - Episodes of every show"
            },
            "EditorTitleDetail": {
                "type": "object",
                "properties": {
                    "tmdb_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "year": {
                        "type": "integer",
                        "nullable": true
                    },
                    "rating": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "genre": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "description": "Directors of a movie, creators of a TV show."
                    },
                    "cast": {
                        "type": "string"
                    },
                    "country": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string"
                    },
                    "backdrop_url": {
                        "type": "string"
                    },
                    "seasons": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorSeason"
                        },
                        "description": "TV shows only."
                    }
                },
                "required": [
                    "backdrop_url",
                    "cast",
                    "country",
                    "director",
                    "genre",
                    "name",
                    "plot",
                    "poster_url",
                    "rating",
                    "release_date",
                    "tmdb_id",
                    "year"
                ]
            },
            "EditorTitleHit": {
                "type": "object",
                "properties": {
                    "tmdb_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "original_name": {
                        "type": "string"
                    },
                    "year": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string"
                    },
                    "backdrop_url": {
                        "type": "string"
                    },
                    "rating": {
                        "type": "number",
                        "format": "double"
                    }
                },
                "required": [
                    "backdrop_url",
                    "name",
                    "original_name",
                    "plot",
                    "poster_url",
                    "rating",
                    "tmdb_id",
                    "year"
                ]
            },
            "EditorToPlaylistRequest": {
                "type": "object",
                "description": "The rows to copy, and where their copies go.",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "maxItems": 300000
                    },
                    "category": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "new_category": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "playlist": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "keep": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "ids",
                    "playlist"
                ]
            },
            "EditorToPlaylistResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "nullable": true,
                        "description": "The rows it changed, as the grid lists them; null when there are too many to send: load the list again. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "created": {
                        "type": "integer",
                        "description": "Copies made."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Rows left out: already there."
                    },
                    "message": {
                        "type": "string",
                        "description": "What it did, in a sentence to show."
                    },
                    "merged": {
                        "type": "integer",
                        "description": "TV shows the other playlist already had, which got the new episodes."
                    },
                    "episodes": {
                        "type": "integer",
                        "description": "Episodes added to those TV shows."
                    },
                    "target": {
                        "$ref": "#/components/schemas/EditorCopyTarget"
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "created",
                    "episodes",
                    "merged",
                    "message",
                    "removed",
                    "rows",
                    "skipped",
                    "target",
                    "version"
                ]
            },
            "EditorToolDiff": {
                "type": "object",
                "properties": {
                    "t": {
                        "$ref": "#/components/schemas/TEnum"
                    },
                    "id": {
                        "type": "integer"
                    },
                    "field": {
                        "type": "string",
                        "description": "The field that changes; `deleted`: the row goes to the recycle bin."
                    },
                    "before": {},
                    "after": {}
                },
                "required": [
                    "after",
                    "before",
                    "field",
                    "id",
                    "t"
                ]
            },
            "EditorToolOptionsRequest": {
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/EditorOptimizeOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorReplaceOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorDedupeOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorAffixOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorCaseOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorUrlOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorFormatOptionsRequest"
                    },
                    {
                        "$ref": "#/components/schemas/EditorPresetOptionsRequest"
                    }
                ]
            },
            "EditorToolOutcome": {
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/EditorToolResult"
                    },
                    {
                        "$ref": "#/components/schemas/EditorToolPreview"
                    }
                ]
            },
            "EditorToolPreview": {
                "type": "object",
                "properties": {
                    "diff": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorToolDiff"
                        },
                        "description": "The first differences, one per field."
                    },
                    "count": {
                        "type": "integer",
                        "description": "Rows that would change."
                    },
                    "binned": {
                        "type": "integer",
                        "description": "Of those, rows that would go to the recycle bin."
                    }
                },
                "required": [
                    "binned",
                    "count",
                    "diff"
                ]
            },
            "EditorToolRequest": {
                "type": "object",
                "description": "The rows to work on, and the tool's options.",
                "properties": {
                    "scope": {
                        "$ref": "#/components/schemas/EditorScopeRequest"
                    },
                    "options": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorToolOptionsRequest"
                            }
                        ],
                        "description": "The options of the tool in the path."
                    },
                    "target": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorToolTargetEnum"
                            }
                        ],
                        "default": "entries"
                    },
                    "preview": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "scope"
                ]
            },
            "EditorToolResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "nullable": true,
                        "description": "The rows it changed, as the grid lists them; null when there are too many to send: load the list again. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    },
                    "changed": {
                        "type": "integer",
                        "description": "Rows changed."
                    },
                    "binned": {
                        "type": "integer",
                        "description": "Of those, rows sent to the recycle bin."
                    }
                },
                "required": [
                    "binned",
                    "categories",
                    "change",
                    "changed",
                    "removed",
                    "rows",
                    "version"
                ]
            },
            "EditorToolTargetEnum": {
                "enum": [
                    "entries",
                    "categories"
                ],
                "type": "string",
                "description": "* `entries` - entries\n* `categories` - categories"
            },
            "EditorUndoResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "description": "The change undone, redone, or made by the revert."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after it."
                    }
                },
                "required": [
                    "change",
                    "version"
                ]
            },
            "EditorUpdater": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "provider": {
                        "type": "integer"
                    },
                    "provider_url": {
                        "type": "string"
                    },
                    "options": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorUpdaterOptions"
                            }
                        ],
                        "description": "Per kind; a kind left out is not synced."
                    },
                    "mappings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorMapping"
                        }
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "last_run_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "last_ok_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "status": {
                        "type": "string"
                    },
                    "last_error": {
                        "type": "string"
                    },
                    "next_live_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When channels sync next."
                    },
                    "next_vod_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When movies and TV shows sync next."
                    }
                },
                "required": [
                    "enabled",
                    "id",
                    "last_error",
                    "last_ok_at",
                    "last_run_at",
                    "mappings",
                    "next_live_at",
                    "next_vod_at",
                    "options",
                    "provider",
                    "provider_url",
                    "status"
                ]
            },
            "EditorUpdaterOptions": {
                "type": "object",
                "properties": {
                    "live": {
                        "$ref": "#/components/schemas/EditorKindOptions"
                    },
                    "movie": {
                        "$ref": "#/components/schemas/EditorKindOptions"
                    },
                    "series": {
                        "$ref": "#/components/schemas/EditorKindOptions"
                    }
                }
            },
            "EditorUpdaterOptionsRequest": {
                "type": "object",
                "properties": {
                    "live": {
                        "$ref": "#/components/schemas/EditorKindOptionsRequest"
                    },
                    "movie": {
                        "$ref": "#/components/schemas/EditorKindOptionsRequest"
                    },
                    "series": {
                        "$ref": "#/components/schemas/EditorKindOptionsRequest"
                    }
                }
            },
            "EditorUpdaterRequest": {
                "type": "object",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "options": {
                        "$ref": "#/components/schemas/EditorUpdaterOptionsRequest"
                    },
                    "mappings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorMappingRequest"
                        }
                    },
                    "enabled": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "provider"
                ]
            },
            "EditorUpdaterRun": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "kinds": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Some of `live`, `movie` and `series`."
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "status": {
                        "type": "string"
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "integer"
                            }
                        },
                        "description": "Per kind: added, renamed, removed…"
                    },
                    "log": {
                        "type": "string"
                    }
                },
                "required": [
                    "counts",
                    "finished_at",
                    "id",
                    "kinds",
                    "log",
                    "started_at",
                    "status"
                ]
            },
            "EditorUploadRequest": {
                "type": "object",
                "properties": {
                    "file": {
                        "type": "string",
                        "format": "binary"
                    }
                },
                "required": [
                    "file"
                ]
            },
            "EditorUploaded": {
                "type": "object",
                "properties": {
                    "upload": {
                        "type": "string"
                    },
                    "size": {
                        "type": "integer",
                        "description": "Bytes."
                    }
                },
                "required": [
                    "size",
                    "upload"
                ]
            },
            "EditorUrlOptionsFieldEnum": {
                "enum": [
                    "url",
                    "logo"
                ],
                "type": "string",
                "description": "* `url` - url\n* `logo` - logo"
            },
            "EditorUrlOptionsRequest": {
                "type": "object",
                "properties": {
                    "find": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "field": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorUrlOptionsFieldEnum"
                            }
                        ],
                        "default": "url"
                    },
                    "with": {
                        "type": "string",
                        "default": "",
                        "maxLength": 500
                    }
                },
                "required": [
                    "find"
                ]
            },
            "EditorWriteResult": {
                "type": "object",
                "properties": {
                    "change": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EditorChange"
                            }
                        ],
                        "nullable": true,
                        "description": "The change it made in the history; null when nothing changed."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The playlist's version after the edit."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "items": {}
                        },
                        "nullable": true,
                        "description": "The rows it changed, as the grid lists them; null when there are too many to send: load the list again. Each row is an array of values in this order: id, category, name, source_name, url, logo, epg_id, epg_shift, number, catchup_days, tmdb_id, rating, hidden, sync_name, deleted_at, created_at, updated_at, provider, episodes."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorCategory"
                        },
                        "description": "The categories it changed."
                    },
                    "removed": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Ids of rows removed for good."
                    }
                },
                "required": [
                    "categories",
                    "change",
                    "removed",
                    "rows",
                    "version"
                ]
            },
            "EndingEnum": {
                "enum": [
                    "loop",
                    "once"
                ],
                "type": "string",
                "description": "* `loop` - Start again from the top\n* `once` - Play once, then turn the channel off"
            },
            "Entry": {
                "type": "object",
                "description": "One change to a balance. The names in it are kept as they were then, so it reads the same once an account, line or package is gone.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "account": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditAccountRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "account_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "amount": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "readOnly": true
                    },
                    "balance_after": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "readOnly": true
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EntryKindEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "kind_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EntryTypeEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "type_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "description": {
                        "type": "string",
                        "readOnly": true
                    },
                    "actor_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "by_me": {
                        "type": "boolean",
                        "nullable": true,
                        "readOnly": true
                    },
                    "counterparty_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "line": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditAccountRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "line_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "package_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "duration": {
                        "type": "string",
                        "readOnly": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "reason": {
                        "type": "string",
                        "readOnly": true
                    },
                    "reference": {
                        "type": "string",
                        "readOnly": true
                    }
                },
                "required": [
                    "account",
                    "account_name",
                    "actor_name",
                    "amount",
                    "balance_after",
                    "by_me",
                    "counterparty_name",
                    "created_at",
                    "description",
                    "duration",
                    "expires_at",
                    "id",
                    "kind",
                    "kind_label",
                    "line",
                    "line_name",
                    "package_name",
                    "reason",
                    "reference",
                    "type",
                    "type_label"
                ]
            },
            "EntryKindEnum": {
                "enum": [
                    "adjust",
                    "line_new",
                    "line_extend",
                    "line_trial",
                    "refund",
                    "transfer_out",
                    "transfer_in",
                    "returned",
                    "written_off",
                    "import"
                ],
                "type": "string",
                "description": "* `adjust` - Added or removed\n* `line_new` - New line\n* `line_extend` - Line extended\n* `line_trial` - Trial line\n* `refund` - Refund\n* `transfer_out` - Given or taken back (out)\n* `transfer_in` - Given or taken back (in)\n* `returned` - Returned\n* `written_off` - Written off\n* `import` - Brought from the old panel"
            },
            "EntryTypeEnum": {
                "enum": [
                    "payment",
                    "refund",
                    "correction",
                    "promo",
                    "other"
                ],
                "type": "string",
                "description": "* `payment` - Payment\n* `refund` - Refund\n* `correction` - Correction\n* `promo` - Promotion\n* `other` - Other"
            },
            "EpgChannelRef": {
                "type": "object",
                "description": "`EpgChannelRef`: a channel as pickers and streams show it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "icon": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true
                    },
                    "countries": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "maxLength": 8
                        },
                        "readOnly": true
                    },
                    "has_guide": {
                        "type": "boolean",
                        "readOnly": true
                    }
                },
                "required": [
                    "countries",
                    "has_guide",
                    "icon",
                    "id",
                    "name"
                ]
            },
            "EpgModeEnum": {
                "enum": [
                    "missing",
                    "auto",
                    "all"
                ],
                "type": "string",
                "description": "* `missing` - missing\n* `auto` - auto\n* `all` - all"
            },
            "EpgSettings": {
                "type": "object",
                "description": "`EpgSettings`: the key is write-only; a blank one keeps the stored\nkey (the page never has it to send back).",
                "properties": {
                    "farm_url": {
                        "type": "string",
                        "format": "uri",
                        "title": "Minimus EPG address",
                        "description": "Where the guide is downloaded from. Leave the default unless Minimus support gives you another address.",
                        "maxLength": 200
                    },
                    "has_key": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "refresh_hours": {
                        "type": "integer",
                        "maximum": 48,
                        "minimum": 1,
                        "title": "Refresh every (hours)",
                        "description": "How often the panel checks for a newer guide. Unchanged files are not downloaded again."
                    },
                    "keep_days": {
                        "type": "integer",
                        "maximum": 14,
                        "minimum": 1,
                        "title": "Days of guide to keep",
                        "description": "Programmes further ahead are not imported, and the past is dropped after a day. More days means a bigger database."
                    },
                    "auto_assign": {
                        "type": "boolean",
                        "title": "Assign EPG automatically",
                        "description": "When a stream is created or imported without an EPG channel, give it the channel its name clearly matches."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "has_key",
                    "updated_at"
                ]
            },
            "EpgSource": {
                "type": "object",
                "description": "`EpgSource`. A Minimus EPG country's address is never shown: it is\nbuilt from the settings, and its key never leaves the server.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EpgSourceKindEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "readOnly": true
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "priority": {
                        "type": "integer",
                        "maximum": 1000,
                        "minimum": 0,
                        "description": "When two sources carry the same channel, the higher priority one supplies its programmes."
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EpgSourceStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "last_checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_imported_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_error": {
                        "type": "string",
                        "readOnly": true
                    },
                    "channels_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "programmes_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "channels_count",
                    "country",
                    "id",
                    "kind",
                    "last_checked_at",
                    "last_error",
                    "last_imported_at",
                    "programmes_count",
                    "status",
                    "updated_at"
                ]
            },
            "EpgSourceKindEnum": {
                "enum": [
                    "minimus",
                    "xmltv"
                ],
                "type": "string",
                "description": "* `minimus` - Minimus EPG country\n* `xmltv` - XMLTV address"
            },
            "EpgSourceRequest": {
                "type": "object",
                "description": "`EpgSource`. A Minimus EPG country's address is never shown: it is\nbuilt from the settings, and its key never leaves the server.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "priority": {
                        "type": "integer",
                        "maximum": 1000,
                        "minimum": 0,
                        "description": "When two sources carry the same channel, the higher priority one supplies its programmes."
                    }
                }
            },
            "EpgSourceStatusEnum": {
                "enum": [
                    "idle",
                    "queued",
                    "importing",
                    "ok",
                    "error"
                ],
                "type": "string",
                "description": "* `idle` - Waiting\n* `queued` - Queued\n* `importing` - Importing\n* `ok` - Up to date\n* `error` - Failed"
            },
            "Episode": {
                "type": "object",
                "description": "An episode, with its file, whether it can play now, and where its copies are.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "xtream_id": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "The number players know it by, in player links and the player API. Given when it is created, never changed or reused, because players save favourites against it."
                    },
                    "season": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "season_number": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "series_id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "series_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Episode Number"
                    },
                    "code": {
                        "type": "string",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "title": "Title",
                        "description": "Empty reads as \"Episode N\" wherever a title is shown.",
                        "maxLength": 255
                    },
                    "title": {
                        "type": "string",
                        "readOnly": true
                    },
                    "plot": {
                        "type": "string"
                    },
                    "still_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "A frame from the episode, shown as its thumbnail. The series poster stands in when empty.",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "runtime_minutes": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true,
                        "title": "Runtime (minutes)"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "writer": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "guest_stars": {
                        "type": "string"
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "The episode's own TMDB record, filled by a sync.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive episode disappears from playlists and refuses playback, without being deleted."
                    },
                    "media_file": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "The file behind this title. Null until a source is attached. One title, one file — selling the same title in two qualities means two entries, which is also how every player's VOD list expects to see it."
                    },
                    "media": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MediaFile"
                            }
                        ],
                        "readOnly": true
                    },
                    "is_playable": {
                        "type": "boolean",
                        "description": "Whether a viewer asking for it now could be served.",
                        "readOnly": true
                    },
                    "ready_node_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "code",
                    "created_at",
                    "id",
                    "is_playable",
                    "media",
                    "media_file",
                    "number",
                    "ready_node_count",
                    "season",
                    "season_number",
                    "series_id",
                    "series_name",
                    "title",
                    "updated_at",
                    "xtream_id"
                ]
            },
            "EpisodeBulkActionEnum": {
                "enum": [
                    "activate",
                    "deactivate",
                    "delete",
                    "detach",
                    "replicate",
                    "remove_replica"
                ],
                "type": "string",
                "description": "* `activate` - activate\n* `deactivate` - deactivate\n* `delete` - delete\n* `detach` - detach\n* `replicate` - replicate\n* `remove_replica` - remove_replica"
            },
            "EpisodeBulkQueued": {
                "type": "object",
                "properties": {
                    "queued": {
                        "type": "integer",
                        "description": "Episodes with a file, queued for the action."
                    }
                },
                "required": [
                    "queued"
                ]
            },
            "EpisodeBulkRequest": {
                "type": "object",
                "description": "One action over many episodes: picked by id, or a whole season/series.",
                "properties": {
                    "action": {
                        "$ref": "#/components/schemas/EpisodeBulkActionEnum"
                    },
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 5000
                    },
                    "series": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "season": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid"
                    }
                },
                "required": [
                    "action"
                ]
            },
            "EpisodeBulkResult": {
                "type": "object",
                "properties": {
                    "updated": {
                        "type": "integer",
                        "description": "Episodes activated or deactivated."
                    },
                    "deleted": {
                        "type": "integer"
                    }
                }
            },
            "EpisodeRequest": {
                "type": "object",
                "description": "An episode, with its file, whether it can play now, and where its copies are.",
                "properties": {
                    "season": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Episode Number"
                    },
                    "name": {
                        "type": "string",
                        "title": "Title",
                        "description": "Empty reads as \"Episode N\" wherever a title is shown.",
                        "maxLength": 255
                    },
                    "plot": {
                        "type": "string"
                    },
                    "still_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "A frame from the episode, shown as its thumbnail. The series poster stands in when empty.",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "runtime_minutes": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true,
                        "title": "Runtime (minutes)"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "writer": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "guest_stars": {
                        "type": "string"
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "The episode's own TMDB record, filled by a sync.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive episode disappears from playlists and refuses playback, without being deleted."
                    }
                },
                "required": [
                    "number",
                    "season"
                ]
            },
            "ErrorResponseDoc": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "ExistingEpisode": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "media": {
                        "type": "string",
                        "nullable": true,
                        "description": "Its file's state, null without one."
                    }
                },
                "required": [
                    "id",
                    "media",
                    "name"
                ]
            },
            "FieldsEnum": {
                "enum": [
                    "name",
                    "logo",
                    "epg",
                    "number"
                ],
                "type": "string",
                "description": "* `name` - name\n* `logo` - logo\n* `epg` - epg\n* `number` - number"
            },
            "FrequencyEnum": {
                "enum": [
                    "manual",
                    "hourly",
                    "daily",
                    "weekly",
                    "monthly"
                ],
                "type": "string",
                "description": "* `manual` - Only when started by hand\n* `hourly` - Every few hours\n* `daily` - Daily\n* `weekly` - Weekly\n* `monthly` - Monthly"
            },
            "GiveRequest": {
                "type": "object",
                "properties": {
                    "amount": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$"
                    },
                    "reason": {
                        "type": "string",
                        "default": "",
                        "maxLength": 500
                    }
                },
                "required": [
                    "amount"
                ]
            },
            "Group": {
                "type": "object",
                "description": "A group: its permissions, members, the group above it, and the rules for its resellers (trial lines and refunds).",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "permissions_display": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "permissions_count": {
                        "type": "integer",
                        "description": "Get count of permissions in this group",
                        "readOnly": true
                    },
                    "users": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GroupUser"
                        },
                        "readOnly": true
                    },
                    "users_count": {
                        "type": "integer",
                        "description": "Get count of users in this group",
                        "readOnly": true
                    },
                    "parent": {
                        "type": "integer",
                        "nullable": true,
                        "readOnly": true
                    },
                    "parent_name": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "is_reseller": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "can_customize_packages": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "can_customize_bouquets": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "trials_limit": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "trials_period": {
                        "type": "string",
                        "readOnly": true,
                        "default": "day"
                    },
                    "trials_min_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "readOnly": true
                    },
                    "refund_window_hours": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    }
                },
                "required": [
                    "can_customize_bouquets",
                    "can_customize_packages",
                    "created_at",
                    "created_by_username",
                    "id",
                    "is_reseller",
                    "name",
                    "parent",
                    "parent_name",
                    "permissions_count",
                    "permissions_display",
                    "refund_window_hours",
                    "trials_limit",
                    "trials_min_balance",
                    "trials_period",
                    "users",
                    "users_count"
                ]
            },
            "GroupList": {
                "type": "object",
                "description": "A group as the list shows it: without its members.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "permissions_count": {
                        "type": "integer",
                        "description": "Get count of permissions in this group",
                        "readOnly": true
                    },
                    "users_count": {
                        "type": "integer",
                        "description": "Get count of users in this group",
                        "readOnly": true
                    },
                    "parent": {
                        "type": "integer",
                        "nullable": true,
                        "readOnly": true
                    },
                    "parent_name": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "is_reseller": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "can_customize_packages": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "can_customize_bouquets": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "trials_limit": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "trials_period": {
                        "type": "string",
                        "readOnly": true,
                        "default": "day"
                    },
                    "trials_min_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "readOnly": true
                    },
                    "refund_window_hours": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    }
                },
                "required": [
                    "can_customize_bouquets",
                    "can_customize_packages",
                    "created_at",
                    "created_by_username",
                    "id",
                    "is_reseller",
                    "name",
                    "parent",
                    "parent_name",
                    "permissions_count",
                    "refund_window_hours",
                    "trials_limit",
                    "trials_min_balance",
                    "trials_period",
                    "users_count"
                ]
            },
            "GroupUser": {
                "type": "object",
                "description": "A member of a group.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Email address"
                    },
                    "first_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "last_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "is_staff": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "readOnly": true
                    }
                },
                "required": [
                    "email",
                    "first_name",
                    "groups",
                    "id",
                    "is_active",
                    "is_staff",
                    "last_name",
                    "username"
                ]
            },
            "GroupWriteRequest": {
                "type": "object",
                "description": "A group as created or changed. The flags and credit rules are kept on\nthe group's profile; the credit rules are changed by panel operators only.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Permission ids. You can give only permissions you hold."
                    },
                    "parent": {
                        "type": "integer",
                        "nullable": true,
                        "description": "On create: the group it goes under, one of yours. Left out: your own group when you have one."
                    },
                    "is_reseller": {
                        "type": "boolean",
                        "description": "Its members are resellers who pay with credits."
                    },
                    "can_customize_packages": {
                        "type": "boolean",
                        "description": "Members may build their own packages (only if you may)."
                    },
                    "can_customize_bouquets": {
                        "type": "boolean",
                        "description": "Members may build their own bouquets (only if you may)."
                    },
                    "trials_limit": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "nullable": true,
                        "description": "Trial lines each member may make per period; null: no limit, 0: none."
                    },
                    "trials_period": {
                        "$ref": "#/components/schemas/TrialsPeriodEnum"
                    },
                    "trials_min_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "The balance a member needs to make a trial line."
                    },
                    "refund_window_hours": {
                        "type": "integer",
                        "maximum": 720,
                        "minimum": 0,
                        "description": "A line deleted within this many hours of its payment is refunded; 0: never."
                    }
                },
                "required": [
                    "name"
                ]
            },
            "GuideChannelProgrammes": {
                "type": "object",
                "properties": {
                    "channel": {
                        "$ref": "#/components/schemas/EpgChannelRef"
                    },
                    "now": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/GuideProgramme"
                            }
                        ],
                        "nullable": true
                    },
                    "next": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/GuideProgramme"
                            }
                        ],
                        "nullable": true
                    },
                    "programmes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GuideProgramme"
                        }
                    }
                },
                "required": [
                    "channel",
                    "next",
                    "now",
                    "programmes"
                ]
            },
            "GuideCountries": {
                "type": "object",
                "properties": {
                    "available": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GuideCountry"
                        },
                        "description": "The countries Minimus EPG offers."
                    },
                    "selected": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The country codes the panel imports."
                    },
                    "error": {
                        "type": "string",
                        "description": "Why the offer could not be read, or empty."
                    }
                },
                "required": [
                    "available",
                    "error",
                    "selected"
                ]
            },
            "GuideCountry": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "channels": {
                        "type": "integer"
                    }
                },
                "required": [
                    "channels",
                    "code",
                    "name"
                ]
            },
            "GuideEnum": {
                "enum": [
                    "made",
                    "edited",
                    "own"
                ],
                "type": "string",
                "description": "* `made` - Made from the schedule\n* `edited` - Made from the schedule, with my changes\n* `own` - A guide I choose"
            },
            "GuideKeyTest": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean"
                    },
                    "detail": {
                        "type": "string",
                        "description": "What Minimus EPG answered, in words."
                    },
                    "countries": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Countries the key gives, when it works."
                    }
                },
                "required": [
                    "countries",
                    "detail",
                    "ok"
                ]
            },
            "GuideProgramme": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    }
                },
                "required": [
                    "description",
                    "start",
                    "stop",
                    "title"
                ]
            },
            "GuideStatus": {
                "type": "object",
                "properties": {
                    "sources": {
                        "type": "integer"
                    },
                    "importing": {
                        "type": "integer",
                        "description": "Sources queued or importing now."
                    },
                    "errors": {
                        "type": "integer",
                        "description": "Sources whose last import failed."
                    },
                    "channels": {
                        "type": "integer"
                    },
                    "programmes": {
                        "type": "integer"
                    },
                    "guide_until": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "How far ahead the guide goes."
                    },
                    "streams": {
                        "$ref": "#/components/schemas/GuideStreamCounts"
                    }
                },
                "required": [
                    "channels",
                    "errors",
                    "guide_until",
                    "importing",
                    "programmes",
                    "sources",
                    "streams"
                ]
            },
            "GuideStreamCounts": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "mapped": {
                        "type": "integer",
                        "description": "Streams with a guide channel."
                    },
                    "auto": {
                        "type": "integer",
                        "description": "Given their channel by the panel."
                    },
                    "manual": {
                        "type": "integer",
                        "description": "Given their channel by hand."
                    },
                    "unmapped": {
                        "type": "integer"
                    },
                    "without_guide": {
                        "type": "integer",
                        "description": "Streams whose guide channel no source carries."
                    }
                },
                "required": [
                    "auto",
                    "manual",
                    "mapped",
                    "total",
                    "unmapped",
                    "without_guide"
                ]
            },
            "GuideSuggestedCountries": {
                "type": "object",
                "properties": {
                    "suggested": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GuideSuggestedCountry"
                        }
                    }
                },
                "required": [
                    "suggested"
                ]
            },
            "GuideSuggestedCountry": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "streams": {
                        "type": "integer",
                        "description": "Streams that name it."
                    }
                },
                "required": [
                    "code",
                    "streams"
                ]
            },
            "GuideSuggestion": {
                "type": "object",
                "properties": {
                    "channel": {
                        "$ref": "#/components/schemas/EpgChannelRef"
                    },
                    "score": {
                        "type": "number",
                        "format": "double",
                        "description": "From 0 to 1."
                    },
                    "reason": {
                        "type": "string",
                        "description": "Why it matches, in words."
                    }
                },
                "required": [
                    "channel",
                    "reason",
                    "score"
                ]
            },
            "GuideSuggestions": {
                "type": "object",
                "properties": {
                    "best": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/GuideSuggestion"
                            }
                        ],
                        "nullable": true,
                        "description": "Set when the panel is sure enough to pick it alone."
                    },
                    "suggestions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GuideSuggestion"
                        }
                    }
                },
                "required": [
                    "best",
                    "suggestions"
                ]
            },
            "ImportApplyDeliveryEnum": {
                "enum": [
                    "adopt",
                    "download",
                    "proxy",
                    "redirect",
                    "upload"
                ],
                "type": "string",
                "description": "* `adopt` - adopt\n* `download` - download\n* `proxy` - proxy\n* `redirect` - redirect\n* `upload` - upload"
            },
            "ImportApplyRequest": {
                "type": "object",
                "description": "The reviewed list, and how its files should reach the viewers.",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/ShowImportSourceEnum"
                    },
                    "delivery": {
                        "$ref": "#/components/schemas/ImportApplyDeliveryEnum"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "skip_existing": {
                        "type": "boolean",
                        "default": true,
                        "description": "Leave episodes that already have a file (or one on its way) alone."
                    },
                    "fill_tmdb": {
                        "type": "boolean",
                        "default": true,
                        "description": "Give new seasons and episodes their TMDB metadata, when the show has a TMDB id."
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImportItemRequest"
                        }
                    }
                },
                "required": [
                    "delivery",
                    "items",
                    "source"
                ]
            },
            "ImportItemRequest": {
                "type": "object",
                "properties": {
                    "ref": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2048
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 512
                    },
                    "size": {
                        "type": "integer",
                        "minimum": 0,
                        "default": 0
                    },
                    "season": {
                        "type": "integer",
                        "maximum": 999,
                        "minimum": 0
                    },
                    "episode": {
                        "type": "integer",
                        "maximum": 9999,
                        "minimum": 0
                    }
                },
                "required": [
                    "episode",
                    "ref",
                    "season"
                ]
            },
            "ImportPlan": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PlannedFile"
                        }
                    },
                    "ignored": {
                        "type": "integer",
                        "description": "Files left out: not video files."
                    },
                    "truncated": {
                        "type": "boolean",
                        "description": "The source holds more than `limit` files."
                    },
                    "limit": {
                        "type": "integer"
                    }
                },
                "required": [
                    "ignored",
                    "items",
                    "limit",
                    "truncated"
                ]
            },
            "ImportPlanRequest": {
                "type": "object",
                "description": "Where the files are, for the matching step.",
                "properties": {
                    "source": {
                        "$ref": "#/components/schemas/ShowImportSourceEnum"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "path": {
                        "type": "string",
                        "maxLength": 1024
                    },
                    "urls": {
                        "type": "string",
                        "maxLength": 2000000
                    },
                    "files": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        },
                        "maxItems": 2000
                    }
                },
                "required": [
                    "source"
                ]
            },
            "ImportRenamingRule": {
                "type": "object",
                "properties": {
                    "rule": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamRenameRule"
                            }
                        ],
                        "nullable": true
                    }
                },
                "required": [
                    "rule"
                ]
            },
            "ImportRenamingRuleRequest": {
                "type": "object",
                "properties": {
                    "rule": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamRenameRuleRequest"
                            }
                        ],
                        "nullable": true
                    }
                },
                "required": [
                    "rule"
                ]
            },
            "ImportSortRule": {
                "type": "object",
                "properties": {
                    "match": {
                        "$ref": "#/components/schemas/SortRuleMatchEnum"
                    },
                    "text": {
                        "type": "string"
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "category_name": {
                        "type": "string",
                        "readOnly": true
                    }
                },
                "required": [
                    "category",
                    "category_name",
                    "match",
                    "text"
                ]
            },
            "ImportSortRuleListRequest": {
                "type": "object",
                "properties": {
                    "rules": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSortRuleRequest"
                        }
                    }
                },
                "required": [
                    "rules"
                ]
            },
            "ImportSortRules": {
                "type": "object",
                "properties": {
                    "rules": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ImportSortRule"
                        }
                    }
                },
                "required": [
                    "rules"
                ]
            },
            "ImportStateEnum": {
                "enum": [
                    "new",
                    "done",
                    "skipped",
                    "failed"
                ],
                "type": "string",
                "description": "* `` - Not imported\n* `new` - Waiting\n* `done` - Imported\n* `skipped` - Left out\n* `failed` - Failed"
            },
            "IngestJob": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "media_file": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "title": {
                        "type": "object",
                        "additionalProperties": {},
                        "nullable": true,
                        "description": "The title behind this job, for an operator-legible queue.\n\n`kind` is the title's model (`movie`, `episode`) and `id` its key,\nso the queue can link to the right page. Null while the file\nexists but no catalogue entry points at it. Reached through the\nmedia file's reverse one-to-one; the list view selects those\nrelations so this costs no query per row.",
                        "readOnly": true
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "title": "Target Server"
                    },
                    "server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "method": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/IngestJobMethodEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "source_ref": {
                        "readOnly": true,
                        "title": "Source Reference",
                        "description": "Method-specific locator: the URL to pull, the watch-folder path, the bucket and key of an object, the peer node for a replication. An object is recorded by its key and signed only when the job is sent to the node — a queued job can wait longer than any signed URL lives — and the node receives an ordinary HTTPS URL, so it needs no cloud SDK and object storage is just a URL pull."
                    },
                    "state": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/IngestJobStateEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "phase": {
                        "type": "string",
                        "readOnly": true,
                        "description": "What the node is doing right now: waiting for a free slot, downloading, uploading, probing, publishing."
                    },
                    "progress_pct": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Progress %"
                    },
                    "bytes_done": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "bytes_total": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "error": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Last Error"
                    },
                    "attempts": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    }
                },
                "required": [
                    "attempts",
                    "bytes_done",
                    "bytes_total",
                    "created_at",
                    "error",
                    "finished_at",
                    "id",
                    "media_file",
                    "method",
                    "phase",
                    "progress_pct",
                    "server",
                    "server_name",
                    "source_ref",
                    "started_at",
                    "state",
                    "title"
                ]
            },
            "IngestJobMethodEnum": {
                "enum": [
                    "url",
                    "upload",
                    "scan",
                    "s3",
                    "replicate",
                    "link"
                ],
                "type": "string",
                "description": "* `url` - Download from URL\n* `upload` - Upload from panel\n* `scan` - Watch folder on node\n* `s3` - Object storage\n* `replicate` - Copy from another node\n* `link` - Serve in place on the node"
            },
            "IngestJobStateEnum": {
                "enum": [
                    "queued",
                    "running",
                    "succeeded",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `queued` - Queued\n* `running` - Running\n* `succeeded` - Succeeded\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "KeyEnum": {
                "enum": [
                    "unwatched",
                    "failing",
                    "disabled",
                    "unlisted",
                    "ended"
                ],
                "type": "string",
                "description": "* `unwatched` - unwatched\n* `failing` - failing\n* `disabled` - disabled\n* `unlisted` - unlisted\n* `ended` - ended"
            },
            "KeyTestRequest": {
                "type": "object",
                "properties": {
                    "api_key": {
                        "type": "string",
                        "writeOnly": true
                    }
                }
            },
            "LicenseInstalled": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string",
                        "description": "The holder, plan and server limit accepted."
                    },
                    "license": {
                        "$ref": "#/components/schemas/LicenseStatus"
                    }
                },
                "required": [
                    "detail",
                    "license"
                ]
            },
            "LicenseRemoved": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "LicenseServerCheck": {
                "type": "object",
                "description": "When the license server last confirmed the license.",
                "properties": {
                    "confirmed_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "lease_expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When streaming stops unless the panel reaches the license server again.",
                        "readOnly": true
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "error": {
                        "type": "string"
                    }
                },
                "required": [
                    "checked_at",
                    "confirmed_at",
                    "error",
                    "lease_expires_at"
                ]
            },
            "LicenseStatus": {
                "type": "object",
                "description": "The panel's license, as the License page shows it. The license itself is never returned.",
                "properties": {
                    "needs_setup": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "customer_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "plan": {
                        "type": "string",
                        "readOnly": true
                    },
                    "max_servers": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "features": {
                        "readOnly": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "is_expired": {
                        "type": "boolean",
                        "description": "Whether the license's expiry date has passed.",
                        "readOnly": true
                    },
                    "days_remaining": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Whole days left; negative once expired, null when there is no expiry.",
                        "readOnly": true
                    },
                    "jti": {
                        "type": "string",
                        "readOnly": true
                    },
                    "last_status_ok": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "last_status_reason": {
                        "type": "string",
                        "readOnly": true
                    },
                    "last_verified_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "activated_by": {
                        "type": "string",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "streaming_allowed": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "problem": {
                        "type": "string",
                        "readOnly": true
                    },
                    "server_check": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LicenseServerCheck"
                            }
                        ],
                        "readOnly": true
                    }
                },
                "required": [
                    "activated_by",
                    "customer_name",
                    "days_remaining",
                    "expires_at",
                    "features",
                    "is_expired",
                    "jti",
                    "last_status_ok",
                    "last_status_reason",
                    "last_verified_at",
                    "max_servers",
                    "needs_setup",
                    "plan",
                    "problem",
                    "server_check",
                    "streaming_allowed",
                    "updated_at"
                ]
            },
            "LicenseUploadRequest": {
                "type": "object",
                "description": "The license: its text as `token`, or its file as `file`.",
                "properties": {
                    "token": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The license text you received."
                    },
                    "file": {
                        "type": "string",
                        "format": "binary",
                        "description": "The license file, instead of `token`."
                    }
                }
            },
            "LineBouquetRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "LineCharge": {
                "type": "object",
                "properties": {
                    "amount": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Credits taken from your balance."
                    },
                    "balance_after": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Your balance now."
                    }
                },
                "required": [
                    "amount",
                    "balance_after"
                ]
            },
            "LineCreated": {
                "type": "object",
                "description": "The line as created. Its other settings are read with a GET.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "username": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "first_name": {
                        "type": "string"
                    },
                    "last_name": {
                        "type": "string"
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Null: never expires."
                    },
                    "max_connections": {
                        "type": "integer"
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "charge": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineCharge"
                            }
                        ],
                        "nullable": true,
                        "description": "What you paid; null when nothing was taken."
                    }
                },
                "required": [
                    "charge",
                    "email",
                    "expire_date",
                    "first_name",
                    "forced_server",
                    "id",
                    "is_active",
                    "is_trial",
                    "last_name",
                    "max_connections",
                    "username"
                ]
            },
            "LineCurrentPackage": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "assigned_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "required": [
                    "assigned_at",
                    "expires_at",
                    "id",
                    "is_trial",
                    "name"
                ]
            },
            "LineDeleted": {
                "type": "object",
                "properties": {
                    "refunded": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "Credits given back for the line's last payment; \"0.00\" when none."
                    },
                    "to": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditReturnedTo"
                            }
                        ],
                        "nullable": true,
                        "description": "Whose balance the refund went to; null with no refund."
                    }
                },
                "required": [
                    "refunded",
                    "to"
                ]
            },
            "LineExtendRequest": {
                "type": "object",
                "description": "The package to extend the line with: its length is added to the line's time left, and its connections, restrictions and formats are applied as on a new line.",
                "properties": {
                    "package": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "reset_bouquets": {
                        "type": "boolean",
                        "default": false
                    },
                    "reset_settings": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "package"
                ]
            },
            "LineExtended": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    },
                    "previous_expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "package": {
                        "$ref": "#/components/schemas/LinePackageRef"
                    },
                    "assignment_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The package's entry in the line's package history."
                    },
                    "line": {
                        "$ref": "#/components/schemas/LineUserWithProfile"
                    },
                    "charge": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineCharge"
                            }
                        ],
                        "nullable": true,
                        "description": "What you paid; null when nothing was taken."
                    }
                },
                "required": [
                    "assignment_id",
                    "charge",
                    "detail",
                    "expire_date",
                    "line",
                    "package",
                    "previous_expire_date"
                ]
            },
            "LineLinks": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The domain the links use, if any."
                    },
                    "origin": {
                        "type": "string",
                        "description": "The start of the line's links; empty for the panel's own address."
                    },
                    "from": {
                        "type": "string",
                        "nullable": true,
                        "description": "The reseller whose domain it is, when not the line's own reseller."
                    }
                },
                "required": [
                    "from",
                    "name",
                    "origin"
                ]
            },
            "LinePackageRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "LineRefundQuote": {
                "type": "object",
                "properties": {
                    "refund": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "What deleting the line now would give back; \"0.00\" when nothing."
                    },
                    "why": {
                        "type": "string",
                        "description": "The reason, in one sentence."
                    },
                    "to": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CreditReturnedTo"
                            }
                        ],
                        "nullable": true,
                        "description": "Whose balance it would go back to; null with no refund."
                    }
                },
                "required": [
                    "refund",
                    "to",
                    "why"
                ]
            },
            "LineSummary": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer",
                        "description": "Lines you can see."
                    },
                    "active": {
                        "type": "integer",
                        "description": "Of those, the ones that can watch now: active, enabled, not expired."
                    }
                },
                "required": [
                    "active",
                    "total"
                ]
            },
            "LineUpdateRequest": {
                "type": "object",
                "description": "A line's details and settings. A field left out is left as it is.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 10,
                        "minimum": 1
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "allowed_ips": {
                        "type": "string"
                    },
                    "blocked_ips": {
                        "type": "string"
                    },
                    "allowed_user_agent": {
                        "type": "string"
                    },
                    "notes": {
                        "type": "string"
                    },
                    "reseller_notes": {
                        "type": "string"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineUpdateStatusEnum"
                            }
                        ],
                        "description": "Only `active` can watch.\n\n* `active` - Can watch\n* `inactive` - Not in service yet\n* `suspended` - On hold, e.g. a payment pending\n* `banned` - Kept out for abuse\n* `expired` - Past its expiry date"
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "is_restreamer": {
                        "type": "boolean"
                    },
                    "forced_countries": {
                        "type": "string"
                    },
                    "lock_to_isp": {
                        "type": "boolean"
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "output_formats": {
                        "type": "string"
                    }
                }
            },
            "LineUpdateStatusEnum": {
                "enum": [
                    "active",
                    "inactive",
                    "suspended",
                    "banned",
                    "expired"
                ],
                "type": "string",
                "description": "* `active` - Can watch\n* `inactive` - Not in service yet\n* `suspended` - On hold, e.g. a payment pending\n* `banned` - Kept out for abuse\n* `expired` - Past its expiry date"
            },
            "LineUserCreateRequest": {
                "type": "object",
                "description": "A new line. With `package`, the package sets what you leave out.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "password_confirm": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 10,
                        "minimum": 1
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "allowed_ips": {
                        "type": "string"
                    },
                    "blocked_ips": {
                        "type": "string"
                    },
                    "allowed_user_agent": {
                        "type": "string"
                    },
                    "notes": {
                        "type": "string"
                    },
                    "reseller_notes": {
                        "type": "string"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "package": {
                        "type": "string",
                        "format": "uuid",
                        "writeOnly": true,
                        "nullable": true
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "is_restreamer": {
                        "type": "boolean"
                    },
                    "forced_countries": {
                        "type": "string"
                    },
                    "lock_to_isp": {
                        "type": "boolean"
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "output_formats": {
                        "type": "string"
                    }
                },
                "required": [
                    "password",
                    "password_confirm",
                    "username"
                ]
            },
            "LineUserProfile": {
                "type": "object",
                "description": "A line's settings: status, expiry, connections, restrictions, bouquets and current package. `notes` is shown only to those above the line's owner.",
                "properties": {
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineUserProfileStatusEnum"
                            }
                        ],
                        "description": "Only \"Active\" can watch. The rest differ in intent, not in effect: \"Inactive\" is not yet in service, \"Suspended\" is a reversible hold (payment pending) an automated process may lift, \"Banned\" is applied for abuse and must never be reversed automatically, \"Expired\" is driven by the expiry date. Pick the one you would defend to the customer — reporting and any future auto-reactivation read this field.\n\n* `active` - Active\n* `inactive` - Inactive\n* `suspended` - Suspended\n* `banned` - Banned\n* `expired` - Expired"
                    },
                    "status_display": {
                        "type": "string",
                        "readOnly": true
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Maximum simultaneous connections allowed"
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "Account expiration date"
                    },
                    "allowed_user_agent": {
                        "type": "string",
                        "description": "Allowed user agents (one per line)"
                    },
                    "allowed_ips": {
                        "type": "string",
                        "description": "Allowed IP addresses (one per line, supports CIDR)"
                    },
                    "blocked_ips": {
                        "type": "string",
                        "description": "Addresses this line may not be used from (one per line: an address, a CIDR block or a range a-b). Wins over the allowed addresses."
                    },
                    "notes": {
                        "type": "string",
                        "title": "Admin notes",
                        "description": "Operator-only notes. Hidden from the reseller who owns this line."
                    },
                    "reseller_notes": {
                        "type": "string",
                        "description": "The owning reseller's own notes — order references, billing history. Visible to the owner and to anyone above them."
                    },
                    "is_expired": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "last_activity": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "readOnly": true
                    },
                    "bouquets_display": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/LineBouquetRef"
                        },
                        "readOnly": true
                    },
                    "is_trial": {
                        "type": "boolean",
                        "description": "Line was provisioned from a trial package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "description": "Authorized restream line (relays content downstream)."
                    },
                    "forced_countries": {
                        "type": "string",
                        "description": "Comma-separated ISO country codes the line may connect from. Empty = anywhere.",
                        "maxLength": 255
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "description": "Bind the line to the ISP seen on its first connection."
                    },
                    "locked_isp": {
                        "type": "string",
                        "readOnly": true,
                        "description": "ISP captured on the first connection while lock_to_isp is on."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Stream only from this server; auto routing is bypassed."
                    },
                    "forced_server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "output_formats": {
                        "type": "string",
                        "description": "Comma-separated delivery formats this line was sold. Not enforced: streams are delivered as MPEG-TS.",
                        "maxLength": 64
                    },
                    "package": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineCurrentPackage"
                            }
                        ],
                        "nullable": true,
                        "description": "The package the line is on now; null when none.",
                        "readOnly": true
                    }
                },
                "required": [
                    "bouquets",
                    "bouquets_display",
                    "created_at",
                    "created_by_username",
                    "forced_server_name",
                    "is_expired",
                    "last_activity",
                    "locked_isp",
                    "package",
                    "status_display",
                    "updated_at"
                ]
            },
            "LineUserProfileStatusEnum": {
                "enum": [
                    "active",
                    "inactive",
                    "suspended",
                    "banned",
                    "expired"
                ],
                "type": "string",
                "description": "* `active` - Active\n* `inactive` - Inactive\n* `suspended` - Suspended\n* `banned` - Banned\n* `expired` - Expired"
            },
            "LineUserSetPasswordRequest": {
                "type": "object",
                "description": "The line's new password.",
                "properties": {
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    }
                },
                "required": [
                    "password"
                ]
            },
            "LineUserWithProfile": {
                "type": "object",
                "description": "A line: its account, its settings (`line_profile`) and how many connections it has open.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "profile": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/UserProfile"
                            }
                        ],
                        "readOnly": true
                    },
                    "line_profile": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineUserProfile"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "active_connections": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    },
                    "is_online": {
                        "type": "boolean",
                        "readOnly": true
                    }
                },
                "required": [
                    "active_connections",
                    "created_at",
                    "groups",
                    "id",
                    "is_active",
                    "is_online",
                    "is_staff",
                    "line_profile",
                    "profile",
                    "updated_at",
                    "username"
                ]
            },
            "LinkFormatEnum": {
                "enum": [
                    "ts",
                    "m3u8"
                ],
                "type": "string",
                "description": "* `ts` - MPEG-TS (.ts)\n* `m3u8` - HLS (.m3u8)"
            },
            "LiveConnection": {
                "type": "object",
                "description": "One connection watching now: the line and its owner, what it\nwatches (`kind`: `live`, `movie` or `episode`), the server, the\nviewer's address, player and where it comes from (`country_code`,\n`isp`, `city`: empty when unknown). `restreamer` says whether the rules\nof Settings → Security think it passes the stream on, and\n`restreamer_reasons` which rules did.",
                "properties": {
                    "session_id": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "line": {
                        "type": "string",
                        "readOnly": true
                    },
                    "line_id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "owner": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Username of the account that created the line; empty when none did."
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true,
                        "description": "That account's groups, e.g. Reseller."
                    },
                    "stream_name": {
                        "type": "string",
                        "title": "Stream Name",
                        "readOnly": true
                    },
                    "kind": {
                        "type": "string",
                        "readOnly": true
                    },
                    "title": {
                        "type": "string",
                        "readOnly": true
                    },
                    "server": {
                        "type": "string",
                        "readOnly": true,
                        "nullable": true,
                        "description": "The server the viewer was sent to."
                    },
                    "ip": {
                        "type": "string",
                        "readOnly": true
                    },
                    "player": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "country_code": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "isp": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "city": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "output": {
                        "type": "string",
                        "readOnly": true
                    },
                    "restreamer": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "restreamer_reasons": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "datacenter": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "vpn": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "tor": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "last_heartbeat": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "city",
                    "country_code",
                    "datacenter",
                    "groups",
                    "ip",
                    "isp",
                    "kind",
                    "last_heartbeat",
                    "line",
                    "line_id",
                    "output",
                    "owner",
                    "player",
                    "restreamer",
                    "restreamer_reasons",
                    "server",
                    "session_id",
                    "started_at",
                    "stream_name",
                    "title",
                    "tor",
                    "vpn"
                ]
            },
            "LiveOrMovieEnum": {
                "enum": [
                    "live",
                    "movie"
                ],
                "type": "string",
                "description": "* `live` - live\n* `movie` - movie"
            },
            "LogoCornerEnum": {
                "enum": [
                    "top-right",
                    "top-left",
                    "bottom-right",
                    "bottom-left"
                ],
                "type": "string",
                "description": "* `top-right` - Top right\n* `top-left` - Top left\n* `bottom-right` - Bottom right\n* `bottom-left` - Bottom left"
            },
            "LogoModeEnum": {
                "enum": [
                    "missing",
                    "auto"
                ],
                "type": "string",
                "description": "* `missing` - missing\n* `auto` - auto"
            },
            "M3UImport": {
                "type": "object",
                "description": "A playlist import and its progress. `group_summary` lists the\nplaylist's groups with their channel counts once it is read.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "filename": {
                        "type": "string",
                        "readOnly": true,
                        "title": "File Name"
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/M3UImportStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "group_summary": {
                        "readOnly": true,
                        "title": "Groups Found",
                        "description": "[[group-title, channel count], …] as parsed from the upload."
                    },
                    "selected_groups": {
                        "readOnly": true
                    },
                    "options": {
                        "readOnly": true,
                        "title": "Import Options",
                        "description": "The settings applied to every stream this import creates."
                    },
                    "total": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Channels Selected"
                    },
                    "created": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "updated": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "skipped": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "failed_count": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Failed"
                    },
                    "started_count": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Started"
                    },
                    "total_channels": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Channels in the playlist, before any group is left out."
                    },
                    "processed": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Channels dealt with so far, whatever was done with them."
                    },
                    "start_total": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Streams waiting to be started a few at a time; `started_count` of them have started."
                    },
                    "is_finished": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "message": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Result"
                    },
                    "warnings": {
                        "readOnly": true
                    },
                    "streams_count": {
                        "type": "integer",
                        "description": "Streams that still carry this import's stamp — created or\nupdated by it, and not deleted since.",
                        "readOnly": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created",
                    "created_at",
                    "created_by_username",
                    "failed_count",
                    "filename",
                    "group_summary",
                    "id",
                    "is_finished",
                    "message",
                    "options",
                    "processed",
                    "selected_groups",
                    "skipped",
                    "start_total",
                    "started_count",
                    "status",
                    "streams_count",
                    "total",
                    "total_channels",
                    "updated",
                    "updated_at",
                    "warnings"
                ]
            },
            "M3UImportStatusEnum": {
                "enum": [
                    "parsing",
                    "parsed",
                    "running",
                    "starting",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `parsing` - Reading playlist\n* `parsed` - Awaiting configuration\n* `running` - Importing\n* `starting` - Starting streams\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "M3UUploadRequest": {
                "type": "object",
                "description": "The playlist to import: an M3U file, or its text.",
                "properties": {
                    "playlist_file": {
                        "type": "string",
                        "format": "binary"
                    },
                    "playlist_text": {
                        "type": "string"
                    },
                    "filename": {
                        "type": "string",
                        "maxLength": 255
                    }
                }
            },
            "MatchByEnum": {
                "enum": [
                    "name",
                    "url",
                    "stream_id",
                    "tmdb"
                ],
                "type": "string",
                "description": "* `name` - name\n* `url` - url\n* `stream_id` - stream_id\n* `tmdb` - tmdb"
            },
            "MatchRequest": {
                "type": "object",
                "properties": {
                    "tmdb_id": {
                        "type": "string",
                        "pattern": "^\\s*\\d{1,12}\\s*$"
                    },
                    "as_is": {
                        "type": "boolean",
                        "default": false
                    },
                    "kind": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/WatchFileKindEnum"
                            },
                            {
                                "$ref": "#/components/schemas/BlankEnum"
                            }
                        ]
                    }
                }
            },
            "MediaAsset": {
                "type": "object",
                "description": "One node's copy. `server_name` is projected so the list page can\nrender a per-node chip strip without a second round trip.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "server_instance_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MediaAssetStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "progress_pct": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "bytes_done": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Bytes Transferred"
                    },
                    "bytes_total": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Bytes Expected"
                    },
                    "error": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Last Error",
                        "description": "Why the last attempt failed. Cleared on a successful retry."
                    },
                    "last_verified_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "description": "When the node last confirmed the file is present and the right size."
                    }
                },
                "required": [
                    "bytes_done",
                    "bytes_total",
                    "error",
                    "id",
                    "last_verified_at",
                    "progress_pct",
                    "server",
                    "server_instance_id",
                    "server_name",
                    "status"
                ]
            },
            "MediaAssetStatusEnum": {
                "enum": [
                    "pending",
                    "downloading",
                    "remuxing",
                    "ready",
                    "failed"
                ],
                "type": "string",
                "description": "* `pending` - Pending\n* `downloading` - Downloading\n* `remuxing` - Remuxing\n* `ready` - Ready\n* `failed` - Failed"
            },
            "MediaFile": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "state": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MediaFileStateEnum"
                            }
                        ],
                        "readOnly": true,
                        "description": "Lifecycle of the file itself, not of any one node's copy. \"ready\" means at least one node finished ingest and can serve it; per-node progress lives on MediaAsset.\n\n* `draft` - Draft\n* `ingesting` - Ingesting\n* `ready` - Ready\n* `failed` - Failed"
                    },
                    "original_name": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Original Filename",
                        "description": "Filename as uploaded, downloaded, or found in the watch folder. Kept for operator recognition only."
                    },
                    "container": {
                        "type": "string",
                        "readOnly": true,
                        "description": "File extension of what is actually served (mkv, mp4, ts, …). Ingest keeps the source's own container byte for byte, so this is whatever the file arrived as; the play URL carries it because players pick a demuxer from the extension."
                    },
                    "size_bytes": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Size (bytes)",
                        "description": "Size of the finished file. Drives the per-node storage quota."
                    },
                    "duration_seconds": {
                        "type": "number",
                        "format": "double",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Duration (seconds)",
                        "description": "Null until a node probes the file."
                    },
                    "video_codec": {
                        "type": "string",
                        "readOnly": true,
                        "description": "e.g. H.264, HEVC. Decides whether the operator preview player can show it."
                    },
                    "width": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "height": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "fps": {
                        "type": "number",
                        "format": "double",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Null when the file declares a variable or unknown rate."
                    },
                    "checksum": {
                        "type": "string",
                        "readOnly": true,
                        "title": "SHA-256",
                        "description": "Of the finished file. Node-to-node replication verifies against this, so a truncated copy is caught before it is ever served."
                    },
                    "is_ready": {
                        "type": "boolean",
                        "description": "Whether a streaming server can serve this file now.",
                        "readOnly": true
                    },
                    "assets": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/MediaAsset"
                        },
                        "readOnly": true
                    },
                    "audio_tracks": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/AudioTrack"
                        },
                        "readOnly": true
                    },
                    "subtitle_tracks": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SubtitleTrack"
                        },
                        "readOnly": true
                    },
                    "delivery": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MediaFileDeliveryEnum"
                            }
                        ],
                        "readOnly": true,
                        "description": "Who carries the bytes. \"stored\" is the normal path: a node holds a copy and serves it off local disk. \"proxy\" keeps nothing — a node opens the source per viewer and passes the bytes through, so the title costs no storage and the viewer never learns the origin, but every byte crosses your bandwidth. \"redirect\" costs you neither: the viewer is sent to the source and fetches it themselves — which necessarily shows them the URL, and puts playback beyond anything you can observe or cut off. All three inherit the source's reliability: if it goes away, so does the film.\n\n* `stored` - Stored on a node\n* `proxy` - Proxied through a node\n* `redirect` - Sent straight to the source"
                    },
                    "source_url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true,
                        "description": "Upstream this file is proxied from. Empty for stored files. Operator-visible only: it is handed to a node over the authenticated server-to-server channel and never reaches a viewer, which is the point of proxying."
                    },
                    "source_storage": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Source bucket",
                        "description": "Set when the source is an object in one of the panel's buckets (Settings → Storage). The file is then addressed by its key and a signed URL is made each time it is needed, because a signed URL expires and a stored one would stop the film after a few hours."
                    },
                    "source_storage_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "source_key": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Source object key"
                    },
                    "source_label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "supports_ranges": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Source supports seeking",
                        "description": "Whether the proxied source answered a range request when it was probed. False means the film plays from the start but cannot be scrubbed — accepted rather than refused, because a source that plays is worth more than one that is rejected for a feature the viewer may not use."
                    },
                    "proxy_server": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Proxy node",
                        "description": "The node that carries a proxied title's traffic. Chosen by the operator rather than routed, because this is a bandwidth bill and picking which machine pays it is their decision, not a load-balancing one. Required for \"proxy\"; meaningless for the other two, since one serves from disk and the other never touches us."
                    },
                    "proxy_server_name": {
                        "type": "string",
                        "readOnly": true,
                        "default": ""
                    },
                    "proxy_balanced": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Proxy through any node",
                        "description": "Proxied through whichever streaming node the panel picks at each play (load balanced: a viewer stays on one node, different viewers spread over all of them) instead of one chosen node. The operator opts into spreading the bandwidth bill; with it off, `proxy_server` alone carries the title."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "assets",
                    "audio_tracks",
                    "checksum",
                    "container",
                    "created_at",
                    "delivery",
                    "duration_seconds",
                    "fps",
                    "height",
                    "id",
                    "is_ready",
                    "original_name",
                    "proxy_balanced",
                    "proxy_server",
                    "proxy_server_name",
                    "size_bytes",
                    "source_key",
                    "source_label",
                    "source_storage",
                    "source_storage_name",
                    "source_url",
                    "state",
                    "subtitle_tracks",
                    "supports_ranges",
                    "updated_at",
                    "video_codec",
                    "width"
                ]
            },
            "MediaFileDeliveryEnum": {
                "enum": [
                    "stored",
                    "proxy",
                    "redirect"
                ],
                "type": "string",
                "description": "* `stored` - Stored on a node\n* `proxy` - Proxied through a node\n* `redirect` - Sent straight to the source"
            },
            "MediaFileStateEnum": {
                "enum": [
                    "draft",
                    "ingesting",
                    "ready",
                    "failed"
                ],
                "type": "string",
                "description": "* `draft` - Draft\n* `ingesting` - Ingesting\n* `ready` - Ready\n* `failed` - Failed"
            },
            "MessageResponseDoc": {
                "type": "object",
                "properties": {
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "message"
                ]
            },
            "MissingEnum": {
                "enum": [
                    "delete",
                    "hide",
                    "keep"
                ],
                "type": "string",
                "description": "* `delete` - delete\n* `hide` - hide\n* `keep` - keep"
            },
            "Movie": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "xtream_id": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "The number players know it by, in player links and the player API. Given when it is created, never changed or reused, because players save favourites against it."
                    },
                    "name": {
                        "type": "string",
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this movie reports as its own where exactly one is allowed: the M3U playlist group, and the title-uniqueness rule below. Always present, and always among `categories`."
                    },
                    "category_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this movie appears under. Browsing and filtering read this; it always contains `category`. Same arrangement as streams, for the same reason — a playlist entry carries exactly one group, and a movie in three genres still has to answer that with one value."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this movie belongs to. A line with none of them in common cannot watch it."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Artwork is referenced by URL rather than uploaded — the same convention streams use for thumbnails, and it keeps the panel out of the business of serving images.",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the metadata was fetched from TMDB. Lets a re-fetch go straight to the right title instead of searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Inactive movies disappear from playlists and refuse playback, without being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "media_file": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "The file behind this title. Null until a source is attached. One title, one file — selling the same title in two qualities means two entries, which is also how every player's VOD list expects to see it."
                    },
                    "media": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/MediaFile"
                            }
                        ],
                        "readOnly": true
                    },
                    "is_playable": {
                        "type": "boolean",
                        "description": "Whether a viewer asking for it now could be served.",
                        "readOnly": true
                    },
                    "ready_node_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "category",
                    "category_name",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "id",
                    "is_playable",
                    "media",
                    "name",
                    "ready_node_count",
                    "updated_at",
                    "xtream_id"
                ]
            },
            "MovieCounts": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "active": {
                        "type": "integer"
                    },
                    "playable": {
                        "type": "integer",
                        "description": "Active, with a file a viewer can be sent to."
                    },
                    "ingesting": {
                        "type": "integer",
                        "description": "File on its way."
                    },
                    "failed": {
                        "type": "integer"
                    },
                    "no_media": {
                        "type": "integer",
                        "description": "No file yet."
                    },
                    "total_bytes": {
                        "type": "integer",
                        "description": "Size of their files."
                    }
                },
                "required": [
                    "active",
                    "failed",
                    "ingesting",
                    "no_media",
                    "playable",
                    "total",
                    "total_bytes"
                ]
            },
            "MovieOrEpisodeEnum": {
                "enum": [
                    "movie",
                    "episode"
                ],
                "type": "string",
                "description": "* `movie` - movie\n* `episode` - episode"
            },
            "MovieOrSeriesEnum": {
                "enum": [
                    "movie",
                    "series"
                ],
                "type": "string",
                "description": "* `movie` - movie\n* `series` - series"
            },
            "MovieRequest": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this movie reports as its own where exactly one is allowed: the M3U playlist group, and the title-uniqueness rule below. Always present, and always among `categories`."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this movie appears under. Browsing and filtering read this; it always contains `category`. Same arrangement as streams, for the same reason — a playlist entry carries exactly one group, and a movie in three genres still has to answer that with one value."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this movie belongs to. A line with none of them in common cannot watch it."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Artwork is referenced by URL rather than uploaded — the same convention streams use for thumbnails, and it keeps the panel out of the business of serving images.",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the metadata was fetched from TMDB. Lets a re-fetch go straight to the right title instead of searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Inactive movies disappear from playlists and refuse playback, without being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "media_file": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "The file behind this title. Null until a source is attached. One title, one file — selling the same title in two qualities means two entries, which is also how every player's VOD list expects to see it."
                    }
                },
                "required": [
                    "category",
                    "name"
                ]
            },
            "NodesUpdateResult": {
                "type": "object",
                "properties": {
                    "queued": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "The servers told to update."
                    },
                    "skipped": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/NodesUpdateSkipped"
                        },
                        "description": "The servers that cannot be updated from here, and why."
                    },
                    "version": {
                        "type": "string",
                        "description": "The release they move to."
                    }
                },
                "required": [
                    "queued",
                    "skipped",
                    "version"
                ]
            },
            "NodesUpdateSkipped": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "reason": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "reason"
                ]
            },
            "NullEnum": {
                "enum": [
                    null
                ]
            },
            "OrderEnum": {
                "enum": [
                    "in_order",
                    "shuffle"
                ],
                "type": "string",
                "description": "* `in_order` - In order\n* `shuffle` - Shuffled"
            },
            "Package": {
                "type": "object",
                "description": "A package: what a line on it gets (length, connections, restrictions, bouquets) and its price. `my_price` is what you pay for a line on it, as a reseller.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_enabled": {
                        "type": "boolean"
                    },
                    "is_trial": {
                        "type": "boolean",
                        "description": "Trial package: lines created from it are marked as trials."
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,8}(?:\\.\\d{0,2})?$",
                        "description": "What a reseller pays, in credits, for a line on this package (new or extended). 0 = free. A reseller's own price, when one is set, is used instead."
                    },
                    "duration_value": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Duration value (number of hours or days)"
                    },
                    "duration_type": {
                        "$ref": "#/components/schemas/DurationTypeEnum"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Simultaneous connections granted to lines created from this package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "description": "Authorized-restream package: lines are marked as restreamers."
                    },
                    "forced_countries": {
                        "type": "string",
                        "description": "Comma-separated ISO country codes (e.g. FR,MA). Empty = no country restriction.",
                        "maxLength": 255
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "description": "Lock the line to the ISP seen on its first connection."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Force lines to stream from this server instead of auto routing."
                    },
                    "forced_server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "output_formats": {
                        "type": "string",
                        "description": "Comma-separated allowed delivery formats (hls, mpegts, rtmp). Empty = all.",
                        "maxLength": 64
                    },
                    "allowed_groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Groups that can assign this package to line users"
                    },
                    "allowed_groups_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageGroupRef"
                        },
                        "readOnly": true
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets included in this package"
                    },
                    "bouquets_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Bouquet"
                        },
                        "readOnly": true
                    },
                    "bouquet_ids": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "my_price": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "my_price_source": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "parent_packages": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Parent packages this package derives bouquets from (for super resellers)"
                    },
                    "parent_packages_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageParentRef"
                        },
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "User who created this package"
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "allowed_groups_data",
                    "bouquet_ids",
                    "bouquets_data",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "forced_server_name",
                    "id",
                    "my_price",
                    "my_price_source",
                    "name",
                    "parent_packages_data",
                    "updated_at"
                ]
            },
            "PackageGroupRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "PackageList": {
                "type": "object",
                "description": "A package as the list shows it: its bouquets by id and count. `my_price` is what you pay for a line on it, as a reseller.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "description": {
                        "type": "string",
                        "readOnly": true,
                        "nullable": true
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "is_trial": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "Trial package: lines created from it are marked as trials."
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,8}(?:\\.\\d{0,2})?$",
                        "readOnly": true,
                        "description": "What a reseller pays, in credits, for a line on this package (new or extended). 0 = free. A reseller's own price, when one is set, is used instead."
                    },
                    "duration_value": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Duration value (number of hours or days)"
                    },
                    "duration_type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/DurationTypeEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "max_connections": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "Simultaneous connections granted to lines created from this package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "Authorized-restream package: lines are marked as restreamers."
                    },
                    "forced_countries": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Comma-separated ISO country codes (e.g. FR,MA). Empty = no country restriction."
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "Lock the line to the ISP seen on its first connection."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Force lines to stream from this server instead of auto routing."
                    },
                    "forced_server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "output_formats": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Comma-separated allowed delivery formats (hls, mpegts, rtmp). Empty = all."
                    },
                    "allowed_groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "readOnly": true,
                        "description": "Groups that can assign this package to line users"
                    },
                    "allowed_groups_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageGroupRef"
                        },
                        "readOnly": true
                    },
                    "bouquets_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "bouquet_ids": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "my_price": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "my_price_source": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "User who created this package"
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "allowed_groups",
                    "allowed_groups_data",
                    "bouquet_ids",
                    "bouquets_count",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "credit_cost",
                    "description",
                    "duration_type",
                    "duration_value",
                    "forced_countries",
                    "forced_server",
                    "forced_server_name",
                    "id",
                    "is_enabled",
                    "is_restreamer",
                    "is_trial",
                    "lock_to_isp",
                    "max_connections",
                    "my_price",
                    "my_price_source",
                    "name",
                    "output_formats",
                    "updated_at"
                ]
            },
            "PackageParentRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "PackagePriceFloor": {
                "type": "object",
                "properties": {
                    "floor": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "nullable": true,
                        "description": "The lowest price allowed; null for no floor (always null for a panel operator)."
                    },
                    "parent": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PackageRef"
                            }
                        ],
                        "nullable": true,
                        "description": "The package it comes from that sets the floor."
                    },
                    "refused": {
                        "type": "string",
                        "nullable": true,
                        "description": "Why saving these terms would be refused."
                    },
                    "refused_field": {
                        "type": "string",
                        "nullable": true,
                        "description": "The field the refusal is about."
                    }
                },
                "required": [
                    "floor",
                    "parent",
                    "refused",
                    "refused_field"
                ]
            },
            "PackageRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "PackageRequest": {
                "type": "object",
                "description": "A package: what a line on it gets (length, connections, restrictions, bouquets) and its price. `my_price` is what you pay for a line on it, as a reseller.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_enabled": {
                        "type": "boolean"
                    },
                    "is_trial": {
                        "type": "boolean",
                        "description": "Trial package: lines created from it are marked as trials."
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,8}(?:\\.\\d{0,2})?$",
                        "description": "What a reseller pays, in credits, for a line on this package (new or extended). 0 = free. A reseller's own price, when one is set, is used instead."
                    },
                    "duration_value": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Duration value (number of hours or days)"
                    },
                    "duration_type": {
                        "$ref": "#/components/schemas/DurationTypeEnum"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Simultaneous connections granted to lines created from this package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "description": "Authorized-restream package: lines are marked as restreamers."
                    },
                    "forced_countries": {
                        "type": "string",
                        "description": "Comma-separated ISO country codes (e.g. FR,MA). Empty = no country restriction.",
                        "maxLength": 255
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "description": "Lock the line to the ISP seen on its first connection."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Force lines to stream from this server instead of auto routing."
                    },
                    "output_formats": {
                        "type": "string",
                        "description": "Comma-separated allowed delivery formats (hls, mpegts, rtmp). Empty = all.",
                        "maxLength": 64
                    },
                    "allowed_groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Groups that can assign this package to line users"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets included in this package"
                    },
                    "parent_packages": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Parent packages this package derives bouquets from (for super resellers)"
                    }
                },
                "required": [
                    "name"
                ]
            },
            "PackageUpdated": {
                "type": "object",
                "description": "The package as saved, with `warnings`.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_enabled": {
                        "type": "boolean"
                    },
                    "is_trial": {
                        "type": "boolean",
                        "description": "Trial package: lines created from it are marked as trials."
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,8}(?:\\.\\d{0,2})?$",
                        "description": "What a reseller pays, in credits, for a line on this package (new or extended). 0 = free. A reseller's own price, when one is set, is used instead."
                    },
                    "duration_value": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Duration value (number of hours or days)"
                    },
                    "duration_type": {
                        "$ref": "#/components/schemas/DurationTypeEnum"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Simultaneous connections granted to lines created from this package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "description": "Authorized-restream package: lines are marked as restreamers."
                    },
                    "forced_countries": {
                        "type": "string",
                        "description": "Comma-separated ISO country codes (e.g. FR,MA). Empty = no country restriction.",
                        "maxLength": 255
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "description": "Lock the line to the ISP seen on its first connection."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Force lines to stream from this server instead of auto routing."
                    },
                    "forced_server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "output_formats": {
                        "type": "string",
                        "description": "Comma-separated allowed delivery formats (hls, mpegts, rtmp). Empty = all.",
                        "maxLength": 64
                    },
                    "allowed_groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Groups that can assign this package to line users"
                    },
                    "allowed_groups_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageGroupRef"
                        },
                        "readOnly": true
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets included in this package"
                    },
                    "bouquets_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Bouquet"
                        },
                        "readOnly": true
                    },
                    "bouquet_ids": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "my_price": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "my_price_source": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "parent_packages": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Parent packages this package derives bouquets from (for super resellers)"
                    },
                    "parent_packages_data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageParentRef"
                        },
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "User who created this package"
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "warnings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageWarning"
                        },
                        "description": "Packages resellers built from this one that the change leaves giving more than it."
                    }
                },
                "required": [
                    "allowed_groups_data",
                    "bouquet_ids",
                    "bouquets_data",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "forced_server_name",
                    "id",
                    "my_price",
                    "my_price_source",
                    "name",
                    "parent_packages_data",
                    "updated_at",
                    "warnings"
                ]
            },
            "PackageWarning": {
                "type": "object",
                "properties": {
                    "package": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PackageRef"
                            }
                        ],
                        "description": "A package a reseller built from this one."
                    },
                    "built_by": {
                        "type": "string",
                        "nullable": true,
                        "description": "Its reseller."
                    },
                    "field": {
                        "type": "string",
                        "description": "What it now gives more of."
                    },
                    "message": {
                        "type": "string"
                    }
                },
                "required": [
                    "built_by",
                    "field",
                    "message",
                    "package"
                ]
            },
            "PaginatedAccountList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Account"
                        }
                    }
                }
            },
            "PaginatedActivityLogList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 123
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "http://api.example.org/accounts/?page=4"
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "http://api.example.org/accounts/?page=2"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ActivityLog"
                        }
                    }
                }
            },
            "PaginatedBackgroundTaskList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BackgroundTask"
                        }
                    }
                }
            },
            "PaginatedBackupList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Backup"
                        }
                    }
                }
            },
            "PaginatedBlockedIPList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BlockedIP"
                        }
                    }
                }
            },
            "PaginatedBouquetContentRowList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BouquetContentRow"
                        }
                    }
                }
            },
            "PaginatedBouquetListList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/BouquetList"
                        }
                    }
                }
            },
            "PaginatedCategoryList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Category"
                        }
                    }
                }
            },
            "PaginatedEntryList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Entry"
                        }
                    }
                }
            },
            "PaginatedEpgChannelRefList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EpgChannelRef"
                        }
                    }
                }
            },
            "PaginatedEpisodeList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Episode"
                        }
                    }
                }
            },
            "PaginatedGroupListList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GroupList"
                        }
                    }
                }
            },
            "PaginatedIngestJobList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/IngestJob"
                        }
                    }
                }
            },
            "PaginatedLineUserWithProfileList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/LineUserWithProfile"
                        }
                    }
                }
            },
            "PaginatedM3UImportList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/M3UImport"
                        }
                    }
                }
            },
            "PaginatedMovieList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Movie"
                        }
                    }
                }
            },
            "PaginatedPackageListList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PackageList"
                        }
                    }
                }
            },
            "PaginatedProviderCatalogueItemList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderCatalogueItem"
                        }
                    }
                }
            },
            "PaginatedProviderRowList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderRow"
                        }
                    }
                }
            },
            "PaginatedResellerDomainRowList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ResellerDomainRow"
                        }
                    }
                }
            },
            "PaginatedSeriesList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Series"
                        }
                    }
                }
            },
            "PaginatedServerList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Server"
                        }
                    }
                }
            },
            "PaginatedSourceList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Source"
                        }
                    }
                }
            },
            "PaginatedStaffUserListList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StaffUserList"
                        }
                    }
                }
            },
            "PaginatedStreamList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Stream"
                        }
                    }
                }
            },
            "PaginatedTranscodingProfileList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TranscodingProfile"
                        }
                    }
                }
            },
            "PaginatedUserListList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/UserList"
                        }
                    }
                }
            },
            "PaginatedUserPackageList": {
                "type": "object",
                "required": [
                    "count",
                    "results"
                ],
                "properties": {
                    "count": {
                        "type": "integer",
                        "example": 128,
                        "description": "How many there are in all, on every page."
                    },
                    "next": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=3&page_size=20",
                        "description": "The next page, or null on the last one."
                    },
                    "previous": {
                        "type": "string",
                        "nullable": true,
                        "format": "uri",
                        "example": "https://panel.example.com/streams/?page=1&page_size=20",
                        "description": "The page before, or null on the first one."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/UserPackage"
                        }
                    }
                }
            },
            "PaginatedWatchFileList": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "next": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                    },
                    "previous": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/WatchFile"
                        }
                    }
                },
                "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                ]
            },
            "PanelAddressesRequest": {
                "type": "object",
                "description": "The panel's and its dashboard's addresses and ports.",
                "properties": {
                    "panel": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Where players and streaming servers connect.",
                        "maxLength": 253
                    },
                    "dashboard": {
                        "type": "string",
                        "default": "",
                        "description": "Where people sign in; empty when the panel has no dashboard.",
                        "maxLength": 253
                    },
                    "remove": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 253
                        },
                        "description": "Old addresses that stop working.",
                        "maxItems": 20
                    },
                    "panel_port": {
                        "type": "integer",
                        "description": "The panel's port. Unset: the present one."
                    },
                    "ui_port": {
                        "type": "integer",
                        "description": "The dashboard's port. Unset: the present one."
                    },
                    "stream_port": {
                        "type": "integer",
                        "description": "The port this server streams on. Unset: the present one."
                    },
                    "remove_ports": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Old panel or dashboard ports that stop working.",
                        "maxItems": 20
                    }
                },
                "required": [
                    "panel"
                ]
            },
            "PanelAddressesState": {
                "type": "object",
                "description": "The panel's and its dashboard's addresses and ports.",
                "properties": {
                    "state": {
                        "type": "string",
                        "description": "`idle`, `requested`, `running`, `done` or `failed`."
                    },
                    "message": {
                        "type": "string",
                        "description": "What the server said, in plain words."
                    },
                    "at": {
                        "type": "string",
                        "description": "When it was asked or last moved (ISO 8601), or empty."
                    },
                    "panel": {
                        "type": "string",
                        "description": "Where players and streaming servers connect."
                    },
                    "dashboard": {
                        "type": "string",
                        "description": "Where people sign in."
                    },
                    "old_panel": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Earlier panel addresses that still work."
                    },
                    "old_dashboard": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Earlier dashboard addresses that still work."
                    },
                    "panel_port": {
                        "type": "integer"
                    },
                    "ui_port": {
                        "type": "integer",
                        "description": "The dashboard's port."
                    },
                    "stream_port": {
                        "type": "integer",
                        "description": "The port the panel's own server streams on."
                    },
                    "old_panel_ports": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "old_ui_ports": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "possible": {
                        "type": "boolean",
                        "description": "The addresses can be changed from here."
                    },
                    "ports_possible": {
                        "type": "boolean",
                        "description": "The ports can be changed from here too."
                    },
                    "watched": {
                        "type": "boolean",
                        "description": "A new address is kept only once it answers; otherwise the previous ones come back."
                    },
                    "until": {
                        "type": "string",
                        "description": "While a change is being watched: until when (ISO 8601), else empty."
                    },
                    "rolled_back": {
                        "type": "boolean",
                        "description": "The last change was put back (`message` says why)."
                    },
                    "rescue": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PanelRescueAddress"
                            }
                        ],
                        "nullable": true,
                        "description": "The rescue address, open only while the addresses change; shown to the panel's owner only. Null while it is closed."
                    }
                },
                "required": [
                    "at",
                    "dashboard",
                    "message",
                    "old_dashboard",
                    "old_panel",
                    "old_panel_ports",
                    "old_ui_ports",
                    "panel",
                    "panel_port",
                    "ports_possible",
                    "possible",
                    "rescue",
                    "rolled_back",
                    "state",
                    "stream_port",
                    "ui_port",
                    "until",
                    "watched"
                ]
            },
            "PanelRelease": {
                "type": "object",
                "description": "A Minimus release, as the download server lists it.",
                "properties": {
                    "version": {
                        "type": "string",
                        "description": "The release, e.g. `2026.11.2`."
                    },
                    "published_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "notes": {
                        "type": "string",
                        "description": "What it brings, in plain words."
                    },
                    "track": {
                        "type": "string",
                        "description": "`stable` or `beta`."
                    },
                    "lts": {
                        "type": "boolean",
                        "description": "A long-term release: one the panel may roll back to."
                    },
                    "forced": {
                        "type": "boolean",
                        "description": "A security release: it cannot be rolled back."
                    },
                    "allowed": {
                        "type": "boolean",
                        "description": "Not older than the newest security release, so it may be installed."
                    },
                    "builds": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string"
                        },
                        "description": "The build of each part: `panel`, `ui` and `node` (the streaming software)."
                    }
                },
                "required": [
                    "allowed",
                    "builds",
                    "forced",
                    "lts",
                    "published_at",
                    "version"
                ]
            },
            "PanelReleaseNews": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "string"
                    },
                    "published_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "notes": {
                        "type": "string"
                    }
                },
                "required": [
                    "notes",
                    "published_at",
                    "version"
                ]
            },
            "PanelRescueAddress": {
                "type": "object",
                "properties": {
                    "port": {
                        "type": "integer"
                    },
                    "url": {
                        "type": "string",
                        "description": "Empty when the server's IP address is not known."
                    }
                },
                "required": [
                    "port",
                    "url"
                ]
            },
            "PanelSettings": {
                "type": "object",
                "description": "The panel-wide settings (Settings → Panel). Each value has bounds; one outside them is refused.",
                "properties": {
                    "stream_token_lifetime": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Play link lifetime",
                        "description": "How long a play URL stays usable once the panel hands it out. Links are single-use and only have to survive the redirect to the streaming server, so keep this short: a long lifetime lets a captured link be replayed."
                    },
                    "preview_conversions": {
                        "type": "integer",
                        "maximum": 4,
                        "minimum": 0,
                        "title": "Preview conversions per server",
                        "description": "A browser that cannot play a channel as it is (HEVC or MPEG-2 video, AC-3 sound on most computers) is sent the preview converted, by the server that streams it: about half a processor core for the picture (or the video card), almost nothing for the sound alone. Each one stops when its preview closes, or after 10 minutes. At most this many at once on each server; 0 = never (the preview then says what it cannot play)."
                    },
                    "session_timeout": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 60,
                        "title": "Silence before a viewer counts as gone",
                        "description": "Streaming servers report who is watching every 30 seconds. A session not mentioned for this long is closed and its connection slot freed. Too short closes sessions of people still watching when one report is late; too long keeps dead sessions holding a line's connections."
                    },
                    "fresh_session_timeout": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 10,
                        "title": "Unused play link cleanup",
                        "description": "A session opened for a play request whose player never reached the streaming server is removed after this long, so failed plays do not hold a line's connection slots. Only has to outlast the redirect."
                    },
                    "disconnect_cooldown": {
                        "type": "integer",
                        "maximum": 86400,
                        "minimum": 0,
                        "title": "Reconnect block after a disconnect",
                        "description": "When you disconnect a session from Live Connections, that device (same line, IP and player) is refused for this long. Players retry every second, so a short block only delays them. Use Block IP or disable the line to remove someone for good."
                    },
                    "restart_counter_window": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 0,
                        "description": "The streams list shows how many times each stream restarted within this window — a stream that reads Online after thirty restarts in an hour is flapping, and every restart drops its viewers. Off stops recording restarts and hides the column."
                    },
                    "sweeper_interval": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Cleanup interval",
                        "description": "How often the panel looks for sessions and streams that went quiet. Each worker process runs its own pass."
                    },
                    "sweep_batch_size": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 100,
                        "title": "Rows per cleanup batch",
                        "description": "Session rows one cleanup statement may touch. A pass keeps going until the backlog is drained, so this caps one statement and its locks, not the total work. Keep it small enough that other queries can run in between."
                    },
                    "sweep_max_batches": {
                        "type": "integer",
                        "maximum": 10000,
                        "minimum": 1,
                        "title": "Batches per cleanup pass",
                        "description": "Safety stop on one cleanup pass, so it always returns to its interval even if sessions arrive faster than they are cleared."
                    },
                    "session_reconcile_grace": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Grace before a server's report ends a session",
                        "description": "A streaming server that is alive but no longer lists a session has dropped that viewer. The panel ends such a session after this grace, which only has to cover a viewer joining while the report was being sent."
                    },
                    "status_reconcile_grace": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Grace before a stream is marked offline",
                        "description": "Same rule for streams: a stream its server has stopped listing is marked Offline after this long."
                    },
                    "session_retention_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "title": "Viewing history kept (fallback)",
                        "description": "How many days of ended sessions to keep when the retention on the Activity Logs page is left at its default. The table grows by a row per play request — millions a week on a busy panel — so keeping it forever is only sensible with an external archive."
                    },
                    "metrics_retention_days": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": 1,
                        "title": "Server metrics kept for",
                        "description": "How many days of CPU, memory and bandwidth history the dashboard charts can show. The panel keeps one sample per server per minute, about 11 MB per server at 30 days; older samples are removed once an hour."
                    },
                    "node_check_interval": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Server health check interval",
                        "description": "How often the panel checks which streaming servers stopped reporting."
                    },
                    "node_heartbeat_timeout": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Silence before a server is marked down",
                        "description": "A streaming server not heard from for this long is marked unhealthy and no new stream is sent to it. Servers report every 30 seconds, so the default of 2 minutes allows three missed reports. Never shorter than the check interval."
                    },
                    "import_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 50,
                        "title": "Streams written per batch",
                        "description": "Rows written per database transaction during an import. Larger is fewer round trips; smaller makes progress move more often and loses less to one failure."
                    },
                    "import_start_tick_seconds": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 1,
                        "title": "Seconds per start step",
                        "description": "Imported streams are started a few at a time so the provider is not flooded. This is the length of one step."
                    },
                    "import_starts_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams started per step",
                        "description": "How many imported streams start in one step, across all providers."
                    },
                    "import_starts_per_provider_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams started per provider per step",
                        "description": "The same limit for one provider. Connection-limited provider lines answer a burst with errors until nothing plays."
                    },
                    "import_max_live_per_provider": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Connections allowed per provider",
                        "description": "When set, starting waits once a provider already has this many streams running. Leave at no limit unless you know the provider's real allowance."
                    },
                    "import_start_streams_threshold": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Suggest on demand above",
                        "description": "The import wizard suggests importing as on demand instead of starting the streams when more than this many channels are selected — each running stream holds a provider connection. Only a suggestion."
                    },
                    "import_max_stall_ticks": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 1,
                        "title": "Give up on a full provider after (steps)",
                        "description": "How many start steps an import waits for a provider that stays at its connection limit before it stops and reports the streams it could not start."
                    },
                    "bulk_max_selection": {
                        "type": "integer",
                        "maximum": 1000000,
                        "minimum": 1,
                        "title": "Largest mass edit or delete",
                        "description": "Most streams one mass edit or delete may cover. Larger selections are refused and have to be split."
                    },
                    "bulk_edit_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 10,
                        "title": "Streams changed per batch",
                        "description": "Streams a mass edit writes per database transaction."
                    },
                    "bulk_edit_sync_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams restarted per step",
                        "description": "After a mass edit, streams whose playback settings changed are restarted a few at a time, like an import's starts."
                    },
                    "bulk_edit_sync_tick_seconds": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 1,
                        "title": "Seconds per restart step",
                        "description": "Length of one restart step after a mass edit."
                    },
                    "bulk_edit_sync_scan": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 100,
                        "title": "Streams checked per step",
                        "description": "Most changed streams need no restart (an idle on-demand stream has nothing running). This bounds how many one step looks through to find those that do."
                    },
                    "bulk_delete_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 10,
                        "title": "Streams deleted per batch",
                        "description": "Streams a mass delete removes per transaction, with everything they own."
                    },
                    "bulk_delete_session_batch_size": {
                        "type": "integer",
                        "maximum": 50000,
                        "minimum": 50,
                        "title": "Viewing history rows removed per batch",
                        "description": "A long-running channel has thousands of session rows. They are removed in batches of this size so no lock is held for long."
                    },
                    "bulk_delete_max_stops": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Stop requests per delete",
                        "description": "Emergency ceiling on how many running streams one delete stops on their servers. Past it, deleted streams keep running on the server until stopped by hand, so leave it at no limit unless you need it."
                    },
                    "bulk_delete_background_threshold": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 1,
                        "title": "Admin deletes run in the background from",
                        "description": "Deletes started from the back office run in the background from this many rows. Deletes from the dashboard always run in the background."
                    },
                    "line_down_streams": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 2,
                        "title": "A line looks down when this many channels fail",
                        "description": "When this many channels on one provider line (its server and login) failed to open recently, and almost none on it opened, the Streams page and the provider say the line looks down, with a way to move its streams to another line."
                    },
                    "line_down_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "…within (minutes)",
                        "description": "How recent those failures must be. Only failures the streaming servers already saw count: nothing is tried just to find out."
                    },
                    "provider_warn_days": {
                        "type": "integer",
                        "maximum": 90,
                        "minimum": 1,
                        "title": "Warn before a provider line ends (days)",
                        "description": "A provider whose line ends within this many days is shown on the overview and on its page, as is one that is full, refused or switched off by the provider."
                    },
                    "source_checks_per_server": {
                        "type": "integer",
                        "maximum": 8,
                        "minimum": 1,
                        "title": "Sources one server checks at once",
                        "description": "\"Check sources now\" reads each source once through a streaming server, this many at a time per server, and never more at once on one line than the line has free connections."
                    },
                    "task_stall_seconds": {
                        "type": "integer",
                        "maximum": 86400,
                        "minimum": 60,
                        "title": "Silence before a task counts as stalled",
                        "description": "A running task that has made no progress for this long is shown as stalled — usually the panel restarted while it ran — and can be resumed. Too short flags slow tasks that are still working."
                    },
                    "background_task_threads": {
                        "type": "integer",
                        "maximum": 32,
                        "minimum": 1,
                        "title": "Background worker threads",
                        "description": "Threads each panel process uses for background work: imports, bulk jobs, messages to streaming servers. Each holds a database connection, so more threads on a small box can exhaust the database. Applies after the panel restarts."
                    },
                    "db_deadlock_retries": {
                        "type": "integer",
                        "maximum": 20,
                        "minimum": 0,
                        "title": "Retries after a database deadlock",
                        "description": "Bulk jobs and cleanup run alongside viewers starting sessions, and the database occasionally cancels one of two colliding transactions. The cancelled one is retried this many times before the job fails."
                    },
                    "db_deadlock_backoff_ms": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 1,
                        "title": "First retry delay",
                        "description": "Wait before the first retry; it doubles each time."
                    },
                    "db_deadlock_max_backoff_ms": {
                        "type": "integer",
                        "maximum": 60000,
                        "minimum": 1,
                        "title": "Longest retry delay",
                        "description": "Upper bound on the doubling wait."
                    },
                    "player_api_cache_seconds": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 0,
                        "title": "Catalogue lists kept for",
                        "description": "Player apps download the whole channel, film and series lists when they log in. Each list is built once per set of bouquets and reused for this long, so a wave of logins after an outage costs one build rather than one per player. Catalogue changes reach player apps within this time. Off builds every list on every request."
                    },
                    "playlist_cache_mb": {
                        "type": "integer",
                        "maximum": 102400,
                        "minimum": 0,
                        "title": "Disk kept for ready playlists",
                        "description": "The film and episode part of a playlist is written once per set of bouquets and reused until the catalogue changes, so a playlist of half a million titles downloads in about a second instead of being rebuilt each time. The least recently downloaded ones are removed past this size. Off builds every playlist on every download."
                    },
                    "logo_auto_fill": {
                        "type": "boolean",
                        "title": "Fill in missing logos automatically",
                        "description": "Streams with no logo get the one Minimus finds for them: new and imported streams within minutes, the others once a day. A logo you set is never replaced."
                    },
                    "logo_min_score": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 80,
                        "title": "Logo match sureness",
                        "description": "How sure Minimus must be that a logo is the channel's before a stream gets it, in percent. Higher gives fewer streams a logo, and fewer wrong ones. A stream with a guide channel always gets that channel's logo."
                    },
                    "logo_disk_mb": {
                        "type": "integer",
                        "maximum": 10240,
                        "minimum": 0,
                        "title": "Disk kept for channel logos",
                        "description": "Logos found for streams are kept on this panel and served from its own address, so viewers never see another one. Past this size no more are kept. Off: playlists link to the pictures on Minimus instead, which uses no disk."
                    },
                    "tidy_unwatched_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 1,
                        "title": "Not watched for",
                        "description": "Streams → Tidy up lists streams nobody has watched for this many days. A stream nobody ever watched counts from the day it was added."
                    },
                    "tidy_failing_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "Failing for",
                        "description": "Streams → Tidy up lists streams that have not played for this many days and whose every source failed the last time it was tried."
                    },
                    "tidy_disabled_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 1,
                        "title": "Disabled for",
                        "description": "Streams → Tidy up lists disabled streams nobody has changed for this many days."
                    },
                    "reseller_trials": {
                        "type": "boolean",
                        "title": "Resellers can make trials",
                        "description": "Off: resellers cannot make trial lines at all, whatever their group allows. Operators always can. Each group sets how many trials its resellers may make (Users → Groups)."
                    },
                    "api_requests_per_minute": {
                        "type": "integer",
                        "maximum": 6000,
                        "minimum": 10,
                        "title": "Calls a minute per API key",
                        "description": "How many calls one API key, or one connected AI app, may make in a minute. Past it the panel answers \"too many requests\" until the minute is over, so one runaway script never slows the panel down for everyone."
                    },
                    "api_log_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "API calls listed for",
                        "description": "How many days each API key's and AI app's calls stay listed. Revoked and ended keys leave the API keys page after as long."
                    },
                    "api_log_max_rows": {
                        "type": "integer",
                        "maximum": 10000000,
                        "minimum": 10000,
                        "title": "API calls kept at most",
                        "description": "The list of calls never holds more than this many: past it the oldest go first, whatever their age. Each takes about 200 bytes."
                    },
                    "ai_app_access_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "AI app access lifetime",
                        "description": "How long an AI app's access lasts before it renews it on its own. Shorter means a stolen access is useful for less time; the app renews it without asking the person again."
                    },
                    "ai_app_idle_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "AI app stays signed in for",
                        "description": "An AI app that is not used for this many days must be approved again. Every use starts the count again. Disconnecting an app (AI apps) ends it at once."
                    }
                }
            },
            "PanelSettingsField": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    },
                    "help": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "description": "`integer` or `boolean`."
                    },
                    "unit": {
                        "type": "string",
                        "description": "seconds, days, streams… or `switch`."
                    },
                    "default": {},
                    "zero_means": {
                        "type": "string",
                        "nullable": true,
                        "description": "What 0 means, when it is a mode (\"off\")."
                    },
                    "restart_required": {
                        "type": "boolean",
                        "description": "A change applies after the panel restarts."
                    },
                    "min": {
                        "type": "integer",
                        "nullable": true
                    },
                    "max": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "default",
                    "help",
                    "label",
                    "max",
                    "min",
                    "name",
                    "restart_required",
                    "type",
                    "unit",
                    "zero_means"
                ]
            },
            "PanelSettingsIgnored": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "An old server setting still set on the panel host, now ignored."
                    },
                    "setting": {
                        "type": "string",
                        "nullable": true,
                        "description": "The setting that replaced it."
                    },
                    "page": {
                        "type": "string",
                        "nullable": true,
                        "description": "Where that setting is now."
                    }
                },
                "required": [
                    "name",
                    "page",
                    "setting"
                ]
            },
            "PanelSettingsPage": {
                "type": "object",
                "properties": {
                    "values": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PanelSettings"
                            }
                        ],
                        "description": "Every setting, by name."
                    },
                    "sections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelSettingsSection"
                        },
                        "description": "How the settings page groups and explains them."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "can_edit": {
                        "type": "boolean",
                        "description": "Whether you may change them."
                    },
                    "ignored_environment": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelSettingsIgnored"
                        }
                    }
                },
                "required": [
                    "can_edit",
                    "ignored_environment",
                    "sections",
                    "updated_at",
                    "values"
                ]
            },
            "PanelSettingsSection": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "fields": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelSettingsField"
                        }
                    }
                },
                "required": [
                    "description",
                    "fields",
                    "key",
                    "title"
                ]
            },
            "PanelStreamingRequest": {
                "type": "object",
                "properties": {
                    "domain": {
                        "type": "string",
                        "nullable": true,
                        "minLength": 1,
                        "description": "The address to stream on (a bare hostname, not the panel's), or null to stop streaming."
                    }
                },
                "required": [
                    "domain"
                ]
            },
            "PanelStreamingState": {
                "type": "object",
                "description": "Whether the panel's own server streams too.",
                "properties": {
                    "state": {
                        "type": "string",
                        "description": "`idle`, `requested`, `running`, `done` or `failed`."
                    },
                    "message": {
                        "type": "string",
                        "description": "What the server said, in plain words."
                    },
                    "at": {
                        "type": "string",
                        "description": "When it was asked or last moved (ISO 8601), or empty."
                    },
                    "streaming": {
                        "type": "boolean"
                    },
                    "domain": {
                        "type": "string",
                        "description": "Its main streaming address."
                    },
                    "addresses": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Every address viewers may be sent to, the main one first."
                    },
                    "rule": {
                        "type": "string",
                        "description": "How each new viewer gets an address: `turns`, `least_busy`, `same_viewer` or `random`."
                    },
                    "possible": {
                        "type": "boolean",
                        "description": "The panel's server can add or remove streaming from here."
                    }
                },
                "required": [
                    "addresses",
                    "at",
                    "domain",
                    "message",
                    "possible",
                    "rule",
                    "state",
                    "streaming"
                ]
            },
            "PanelTotals": {
                "type": "object",
                "properties": {
                    "active_connections": {
                        "type": "integer"
                    },
                    "online_users": {
                        "type": "integer",
                        "description": "Lines watching now."
                    },
                    "active_streams": {
                        "type": "integer"
                    },
                    "bytes_in_total": {
                        "type": "integer"
                    },
                    "bytes_out_total": {
                        "type": "integer"
                    },
                    "bytes_in_rate_bps": {
                        "type": "integer"
                    },
                    "bytes_out_rate_bps": {
                        "type": "integer"
                    },
                    "under_attack": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/UnderAttack"
                            }
                        ],
                        "nullable": true
                    }
                },
                "required": [
                    "active_connections",
                    "online_users"
                ]
            },
            "PanelUpdateRequest": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "string",
                        "nullable": true,
                        "minLength": 1,
                        "description": "A release to move to: newer, or one in `rollback`. Unset: the newest."
                    },
                    "nodes": {
                        "type": "boolean",
                        "default": false,
                        "description": "The streaming servers follow once the panel runs it."
                    }
                }
            },
            "PanelUpdateState": {
                "type": "object",
                "description": "How updating the panel is going.",
                "properties": {
                    "state": {
                        "type": "string",
                        "description": "`idle`, `requested`, `running`, `done` or `failed`."
                    },
                    "message": {
                        "type": "string",
                        "description": "What the server said, in plain words."
                    },
                    "at": {
                        "type": "string",
                        "description": "When it was asked or last moved (ISO 8601), or empty."
                    },
                    "installed": {
                        "type": "boolean",
                        "description": "The panel's server can update it from the dashboard (set up once on the server)."
                    },
                    "log": {
                        "type": "string",
                        "description": "The end of the update's log, when it failed."
                    }
                },
                "required": [
                    "at",
                    "installed",
                    "log",
                    "message",
                    "state"
                ]
            },
            "PasswordSet": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    },
                    "username": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail",
                    "username"
                ]
            },
            "PatchedBackupDestinationRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "kind": {
                        "$ref": "#/components/schemas/BackupStorageKindEnum"
                    },
                    "folder": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Bucket"
                    },
                    "is_default": {
                        "type": "boolean",
                        "title": "Preselected",
                        "description": "Ticked when a backup is started by hand."
                    }
                }
            },
            "PatchedBackupPlanRequest": {
                "type": "object",
                "description": "A backup schedule: what to back up, when, where, and how many backups to keep.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "scope": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScopeEnum"
                            }
                        ],
                        "title": "What to back up"
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ComponentsEnum"
                        }
                    },
                    "destinations": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "frequency": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/FrequencyEnum"
                            }
                        ],
                        "title": "Runs"
                    },
                    "time_of_day": {
                        "type": "string",
                        "format": "time",
                        "title": "At",
                        "description": "Daily, weekly and monthly runs; for \"every few hours\" only the minute is used."
                    },
                    "every_hours": {
                        "type": "integer",
                        "maximum": 23,
                        "minimum": 1,
                        "title": "Every … hours"
                    },
                    "weekday": {
                        "type": "integer",
                        "maximum": 6,
                        "minimum": 0,
                        "title": "Day of the week",
                        "description": "0 is Monday."
                    },
                    "day_of_month": {
                        "type": "integer",
                        "maximum": 28,
                        "minimum": 1,
                        "title": "Day of the month",
                        "description": "1 to 28, so it exists in every month."
                    },
                    "timezone": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Time zone",
                        "maxLength": 64
                    },
                    "keep_last": {
                        "type": "integer",
                        "maximum": 10000,
                        "minimum": 0,
                        "title": "Keep the last",
                        "description": "Older backups of this schedule are deleted. 0 keeps all."
                    },
                    "keep_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "title": "Keep for (days)",
                        "description": "Backups older than this are deleted. 0 keeps them regardless of age."
                    },
                    "compression": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CompressionEnum"
                            }
                        ],
                        "minimum": 0,
                        "maximum": 32767
                    },
                    "encrypt": {
                        "type": "boolean"
                    },
                    "passphrase": {
                        "type": "string",
                        "writeOnly": true
                    }
                }
            },
            "PatchedBouquetRequest": {
                "type": "object",
                "description": "A bouquet's own fields, plus how much it holds.\n\nIts contents are not listed here: a bouquet can hold tens of thousands\nof streams, and this shape is also nested into every package. They are\nread and changed a page at a time through `bouquets/<id>/content/`.\n`streams` is still accepted on create and update, as a full replacement,\nfor API clients that build a bouquet in one call.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order (lowest first). Ties fall back to name."
                    },
                    "streams": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid",
                            "writeOnly": true
                        },
                        "writeOnly": true
                    }
                }
            },
            "PatchedCategoryRequest": {
                "type": "object",
                "description": "A category: groups and orders streams, movies or TV shows in players and the dashboard. `primary_count` counts what has it as its main category: a category with any can't be deleted.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "type": {
                        "$ref": "#/components/schemas/CategoryTypeEnum"
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Display order within its type (lowest first)."
                    }
                }
            },
            "PatchedEditorApiEntryBatchRequest": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorApiEntryChangeRequest"
                        }
                    }
                }
            },
            "PatchedEditorCustomerRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "password": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "enabled": {
                        "type": "boolean"
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "sync_expiry": {
                        "type": "boolean"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "message": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "notes": {
                        "type": "string",
                        "maxLength": 5000
                    },
                    "language": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "all_live": {
                        "type": "boolean"
                    },
                    "live_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "all_movie": {
                        "type": "boolean"
                    },
                    "movie_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "all_series": {
                        "type": "boolean"
                    },
                    "series_categories": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "maxItems": 20000
                    },
                    "providers": {},
                    "copy_login": {
                        "type": "boolean"
                    }
                }
            },
            "PatchedEditorGuideEventRequest": {
                "type": "object",
                "properties": {
                    "title": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 300
                    },
                    "description": {
                        "type": "string",
                        "default": "",
                        "maxLength": 5000
                    },
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "repeat": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RepeatEnum"
                            }
                        ],
                        "default": "none"
                    }
                }
            },
            "PatchedEditorGuideNameRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    }
                }
            },
            "PatchedEditorOwnGuideChannelRequest": {
                "type": "object",
                "properties": {
                    "tvg_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120,
                        "pattern": "^[^\\s<>\"&]{1,120}$"
                    },
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                    }
                }
            },
            "PatchedEditorPlaylistUpdateRequest": {
                "type": "object",
                "description": "Its name, what players are told (expiry date, message) and every setting.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "expiry": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "message": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": -1
                    },
                    "track_connections": {
                        "type": "boolean"
                    },
                    "limit_connections": {
                        "type": "boolean"
                    },
                    "time_shift": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,2})?$"
                    },
                    "language": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "provider_vod_info": {
                        "type": "boolean"
                    },
                    "auto_vod_info": {
                        "type": "boolean"
                    },
                    "vod_info_options": {},
                    "epg_gzip": {
                        "type": "boolean"
                    },
                    "use_tvg_id": {
                        "type": "boolean"
                    },
                    "epg_dummy_text": {
                        "type": "string",
                        "maxLength": 200
                    },
                    "epg_days": {
                        "type": "integer",
                        "maximum": 14,
                        "minimum": 1
                    },
                    "epg_fields": {},
                    "epg_precision": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 40
                    },
                    "epg_override": {
                        "type": "boolean"
                    },
                    "epg_hide_short": {
                        "type": "boolean"
                    },
                    "epg_show_ids": {
                        "type": "boolean"
                    },
                    "logo_precision": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 40
                    },
                    "logo_override": {
                        "type": "boolean"
                    },
                    "hidden_provider": {
                        "type": "boolean"
                    },
                    "custom_domain": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "welcome": {},
                    "app_color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "app_logo": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "stream_format": {
                        "$ref": "#/components/schemas/StreamFormatEnum"
                    }
                }
            },
            "PatchedEditorPresetRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "color": {
                        "type": "string",
                        "maxLength": 16
                    },
                    "icon": {
                        "type": "string",
                        "maxLength": 40
                    },
                    "steps": {},
                    "kinds": {},
                    "position": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    }
                }
            },
            "PatchedEditorProviderChangeRequest": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500
                    },
                    "param1": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "param2": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "label": {
                        "type": "string",
                        "maxLength": 120
                    }
                }
            },
            "PatchedEditorSettingsRequest": {
                "type": "object",
                "properties": {
                    "max_playlists": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Playlists per account",
                        "description": "How many playlists one reseller may keep. Administrators have no limit."
                    },
                    "max_users": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Customers per account",
                        "description": "How many customers one reseller may hand playlists to, all playlists together. Administrators have no limit."
                    },
                    "max_entries": {
                        "type": "integer",
                        "maximum": 2000000,
                        "minimum": 1000,
                        "title": "Channels and titles per playlist",
                        "description": "Imports stop adding past this many channels, films and shows together."
                    },
                    "max_episodes": {
                        "type": "integer",
                        "maximum": 5000000,
                        "minimum": 1000,
                        "title": "Episodes per playlist"
                    },
                    "output_cache_seconds": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 0,
                        "title": "Links cache (seconds)",
                        "description": "How long a built playlist or guide is reused before an edit shows. 0 rebuilds on every download."
                    },
                    "live_sync_hours": {
                        "type": "integer",
                        "maximum": 48,
                        "minimum": 1,
                        "title": "Sync channels every (hours)"
                    },
                    "vod_sync_hours": {
                        "type": "integer",
                        "maximum": 168,
                        "minimum": 6,
                        "title": "Sync films and shows every (hours)"
                    },
                    "history_depth": {
                        "type": "integer",
                        "maximum": 1000,
                        "minimum": 10,
                        "title": "Undo steps kept per playlist"
                    },
                    "auto_backups": {
                        "type": "boolean",
                        "title": "Back up playlists automatically",
                        "description": "A copy of every playlist twice a day, kept for a week, plus one a week kept for a month."
                    },
                    "tracking_minutes": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 2,
                        "title": "A customer counts as watching for (minutes)",
                        "description": "After their last request: what \"online\" and the connection limit go by."
                    }
                }
            },
            "PatchedEditorUpdaterRequest": {
                "type": "object",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "options": {
                        "$ref": "#/components/schemas/EditorUpdaterOptionsRequest"
                    },
                    "mappings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/EditorMappingRequest"
                        }
                    },
                    "enabled": {
                        "type": "boolean",
                        "default": true
                    }
                }
            },
            "PatchedEpgSettingsRequest": {
                "type": "object",
                "description": "`EpgSettings`: the key is write-only; a blank one keeps the stored\nkey (the page never has it to send back).",
                "properties": {
                    "farm_url": {
                        "type": "string",
                        "format": "uri",
                        "minLength": 1,
                        "title": "Minimus EPG address",
                        "description": "Where the guide is downloaded from. Leave the default unless Minimus support gives you another address.",
                        "maxLength": 200
                    },
                    "api_key": {
                        "type": "string",
                        "writeOnly": true
                    },
                    "refresh_hours": {
                        "type": "integer",
                        "maximum": 48,
                        "minimum": 1,
                        "title": "Refresh every (hours)",
                        "description": "How often the panel checks for a newer guide. Unchanged files are not downloaded again."
                    },
                    "keep_days": {
                        "type": "integer",
                        "maximum": 14,
                        "minimum": 1,
                        "title": "Days of guide to keep",
                        "description": "Programmes further ahead are not imported, and the past is dropped after a day. More days means a bigger database."
                    },
                    "auto_assign": {
                        "type": "boolean",
                        "title": "Assign EPG automatically",
                        "description": "When a stream is created or imported without an EPG channel, give it the channel its name clearly matches."
                    }
                }
            },
            "PatchedEpgSourceRequest": {
                "type": "object",
                "description": "`EpgSource`. A Minimus EPG country's address is never shown: it is\nbuilt from the settings, and its key never leaves the server.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "priority": {
                        "type": "integer",
                        "maximum": 1000,
                        "minimum": 0,
                        "description": "When two sources carry the same channel, the higher priority one supplies its programmes."
                    }
                }
            },
            "PatchedEpisodeRequest": {
                "type": "object",
                "description": "An episode, with its file, whether it can play now, and where its copies are.",
                "properties": {
                    "season": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Episode Number"
                    },
                    "name": {
                        "type": "string",
                        "title": "Title",
                        "description": "Empty reads as \"Episode N\" wherever a title is shown.",
                        "maxLength": 255
                    },
                    "plot": {
                        "type": "string"
                    },
                    "still_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "A frame from the episode, shown as its thumbnail. The series poster stands in when empty.",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "runtime_minutes": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true,
                        "title": "Runtime (minutes)"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "writer": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "guest_stars": {
                        "type": "string"
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "The episode's own TMDB record, filled by a sync.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive episode disappears from playlists and refuses playback, without being deleted."
                    }
                }
            },
            "PatchedGroupWriteRequest": {
                "type": "object",
                "description": "A group as created or changed. The flags and credit rules are kept on\nthe group's profile; the credit rules are changed by panel operators only.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Permission ids. You can give only permissions you hold."
                    },
                    "parent": {
                        "type": "integer",
                        "nullable": true,
                        "description": "On create: the group it goes under, one of yours. Left out: your own group when you have one."
                    },
                    "is_reseller": {
                        "type": "boolean",
                        "description": "Its members are resellers who pay with credits."
                    },
                    "can_customize_packages": {
                        "type": "boolean",
                        "description": "Members may build their own packages (only if you may)."
                    },
                    "can_customize_bouquets": {
                        "type": "boolean",
                        "description": "Members may build their own bouquets (only if you may)."
                    },
                    "trials_limit": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "nullable": true,
                        "description": "Trial lines each member may make per period; null: no limit, 0: none."
                    },
                    "trials_period": {
                        "$ref": "#/components/schemas/TrialsPeriodEnum"
                    },
                    "trials_min_balance": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,10}(?:\\.\\d{0,2})?$",
                        "description": "The balance a member needs to make a trial line."
                    },
                    "refund_window_hours": {
                        "type": "integer",
                        "maximum": 720,
                        "minimum": 0,
                        "description": "A line deleted within this many hours of its payment is refunded; 0: never."
                    }
                }
            },
            "PatchedLineUpdateRequest": {
                "type": "object",
                "description": "A line's details and settings. A field left out is left as it is.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 10,
                        "minimum": 1
                    },
                    "expire_date": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "allowed_ips": {
                        "type": "string"
                    },
                    "blocked_ips": {
                        "type": "string"
                    },
                    "allowed_user_agent": {
                        "type": "string"
                    },
                    "notes": {
                        "type": "string"
                    },
                    "reseller_notes": {
                        "type": "string"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LineUpdateStatusEnum"
                            }
                        ],
                        "description": "Only `active` can watch.\n\n* `active` - Can watch\n* `inactive` - Not in service yet\n* `suspended` - On hold, e.g. a payment pending\n* `banned` - Kept out for abuse\n* `expired` - Past its expiry date"
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "is_restreamer": {
                        "type": "boolean"
                    },
                    "forced_countries": {
                        "type": "string"
                    },
                    "lock_to_isp": {
                        "type": "boolean"
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "output_formats": {
                        "type": "string"
                    }
                }
            },
            "PatchedMovieRequest": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this movie reports as its own where exactly one is allowed: the M3U playlist group, and the title-uniqueness rule below. Always present, and always among `categories`."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this movie appears under. Browsing and filtering read this; it always contains `category`. Same arrangement as streams, for the same reason — a playlist entry carries exactly one group, and a movie in three genres still has to answer that with one value."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this movie belongs to. A line with none of them in common cannot watch it."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Artwork is referenced by URL rather than uploaded — the same convention streams use for thumbnails, and it keeps the panel out of the business of serving images.",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the metadata was fetched from TMDB. Lets a re-fetch go straight to the right title instead of searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Inactive movies disappear from playlists and refuse playback, without being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "media_file": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "The file behind this title. Null until a source is attached. One title, one file — selling the same title in two qualities means two entries, which is also how every player's VOD list expects to see it."
                    }
                }
            },
            "PatchedPackageRequest": {
                "type": "object",
                "description": "A package: what a line on it gets (length, connections, restrictions, bouquets) and its price. `my_price` is what you pay for a line on it, as a reseller.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "is_enabled": {
                        "type": "boolean"
                    },
                    "is_trial": {
                        "type": "boolean",
                        "description": "Trial package: lines created from it are marked as trials."
                    },
                    "credit_cost": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,8}(?:\\.\\d{0,2})?$",
                        "description": "What a reseller pays, in credits, for a line on this package (new or extended). 0 = free. A reseller's own price, when one is set, is used instead."
                    },
                    "duration_value": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Duration value (number of hours or days)"
                    },
                    "duration_type": {
                        "$ref": "#/components/schemas/DurationTypeEnum"
                    },
                    "max_connections": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Simultaneous connections granted to lines created from this package."
                    },
                    "is_restreamer": {
                        "type": "boolean",
                        "description": "Authorized-restream package: lines are marked as restreamers."
                    },
                    "forced_countries": {
                        "type": "string",
                        "description": "Comma-separated ISO country codes (e.g. FR,MA). Empty = no country restriction.",
                        "maxLength": 255
                    },
                    "lock_to_isp": {
                        "type": "boolean",
                        "description": "Lock the line to the ISP seen on its first connection."
                    },
                    "forced_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Force lines to stream from this server instead of auto routing."
                    },
                    "output_formats": {
                        "type": "string",
                        "description": "Comma-separated allowed delivery formats (hls, mpegts, rtmp). Empty = all.",
                        "maxLength": 64
                    },
                    "allowed_groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Groups that can assign this package to line users"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets included in this package"
                    },
                    "parent_packages": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Parent packages this package derives bouquets from (for super resellers)"
                    }
                }
            },
            "PatchedPanelSettingsRequest": {
                "type": "object",
                "description": "The panel-wide settings (Settings → Panel). Each value has bounds; one outside them is refused.",
                "properties": {
                    "stream_token_lifetime": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Play link lifetime",
                        "description": "How long a play URL stays usable once the panel hands it out. Links are single-use and only have to survive the redirect to the streaming server, so keep this short: a long lifetime lets a captured link be replayed."
                    },
                    "preview_conversions": {
                        "type": "integer",
                        "maximum": 4,
                        "minimum": 0,
                        "title": "Preview conversions per server",
                        "description": "A browser that cannot play a channel as it is (HEVC or MPEG-2 video, AC-3 sound on most computers) is sent the preview converted, by the server that streams it: about half a processor core for the picture (or the video card), almost nothing for the sound alone. Each one stops when its preview closes, or after 10 minutes. At most this many at once on each server; 0 = never (the preview then says what it cannot play)."
                    },
                    "session_timeout": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 60,
                        "title": "Silence before a viewer counts as gone",
                        "description": "Streaming servers report who is watching every 30 seconds. A session not mentioned for this long is closed and its connection slot freed. Too short closes sessions of people still watching when one report is late; too long keeps dead sessions holding a line's connections."
                    },
                    "fresh_session_timeout": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 10,
                        "title": "Unused play link cleanup",
                        "description": "A session opened for a play request whose player never reached the streaming server is removed after this long, so failed plays do not hold a line's connection slots. Only has to outlast the redirect."
                    },
                    "disconnect_cooldown": {
                        "type": "integer",
                        "maximum": 86400,
                        "minimum": 0,
                        "title": "Reconnect block after a disconnect",
                        "description": "When you disconnect a session from Live Connections, that device (same line, IP and player) is refused for this long. Players retry every second, so a short block only delays them. Use Block IP or disable the line to remove someone for good."
                    },
                    "restart_counter_window": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 0,
                        "description": "The streams list shows how many times each stream restarted within this window — a stream that reads Online after thirty restarts in an hour is flapping, and every restart drops its viewers. Off stops recording restarts and hides the column."
                    },
                    "sweeper_interval": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Cleanup interval",
                        "description": "How often the panel looks for sessions and streams that went quiet. Each worker process runs its own pass."
                    },
                    "sweep_batch_size": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 100,
                        "title": "Rows per cleanup batch",
                        "description": "Session rows one cleanup statement may touch. A pass keeps going until the backlog is drained, so this caps one statement and its locks, not the total work. Keep it small enough that other queries can run in between."
                    },
                    "sweep_max_batches": {
                        "type": "integer",
                        "maximum": 10000,
                        "minimum": 1,
                        "title": "Batches per cleanup pass",
                        "description": "Safety stop on one cleanup pass, so it always returns to its interval even if sessions arrive faster than they are cleared."
                    },
                    "session_reconcile_grace": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Grace before a server's report ends a session",
                        "description": "A streaming server that is alive but no longer lists a session has dropped that viewer. The panel ends such a session after this grace, which only has to cover a viewer joining while the report was being sent."
                    },
                    "status_reconcile_grace": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Grace before a stream is marked offline",
                        "description": "Same rule for streams: a stream its server has stopped listing is marked Offline after this long."
                    },
                    "session_retention_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 0,
                        "title": "Viewing history kept (fallback)",
                        "description": "How many days of ended sessions to keep when the retention on the Activity Logs page is left at its default. The table grows by a row per play request — millions a week on a busy panel — so keeping it forever is only sensible with an external archive."
                    },
                    "metrics_retention_days": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": 1,
                        "title": "Server metrics kept for",
                        "description": "How many days of CPU, memory and bandwidth history the dashboard charts can show. The panel keeps one sample per server per minute, about 11 MB per server at 30 days; older samples are removed once an hour."
                    },
                    "node_check_interval": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Server health check interval",
                        "description": "How often the panel checks which streaming servers stopped reporting."
                    },
                    "node_heartbeat_timeout": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 30,
                        "title": "Silence before a server is marked down",
                        "description": "A streaming server not heard from for this long is marked unhealthy and no new stream is sent to it. Servers report every 30 seconds, so the default of 2 minutes allows three missed reports. Never shorter than the check interval."
                    },
                    "import_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 50,
                        "title": "Streams written per batch",
                        "description": "Rows written per database transaction during an import. Larger is fewer round trips; smaller makes progress move more often and loses less to one failure."
                    },
                    "import_start_tick_seconds": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 1,
                        "title": "Seconds per start step",
                        "description": "Imported streams are started a few at a time so the provider is not flooded. This is the length of one step."
                    },
                    "import_starts_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams started per step",
                        "description": "How many imported streams start in one step, across all providers."
                    },
                    "import_starts_per_provider_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams started per provider per step",
                        "description": "The same limit for one provider. Connection-limited provider lines answer a burst with errors until nothing plays."
                    },
                    "import_max_live_per_provider": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Connections allowed per provider",
                        "description": "When set, starting waits once a provider already has this many streams running. Leave at no limit unless you know the provider's real allowance."
                    },
                    "import_start_streams_threshold": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Suggest on demand above",
                        "description": "The import wizard suggests importing as on demand instead of starting the streams when more than this many channels are selected — each running stream holds a provider connection. Only a suggestion."
                    },
                    "import_max_stall_ticks": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 1,
                        "title": "Give up on a full provider after (steps)",
                        "description": "How many start steps an import waits for a provider that stays at its connection limit before it stops and reports the streams it could not start."
                    },
                    "bulk_max_selection": {
                        "type": "integer",
                        "maximum": 1000000,
                        "minimum": 1,
                        "title": "Largest mass edit or delete",
                        "description": "Most streams one mass edit or delete may cover. Larger selections are refused and have to be split."
                    },
                    "bulk_edit_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 10,
                        "title": "Streams changed per batch",
                        "description": "Streams a mass edit writes per database transaction."
                    },
                    "bulk_edit_sync_per_tick": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 1,
                        "title": "Streams restarted per step",
                        "description": "After a mass edit, streams whose playback settings changed are restarted a few at a time, like an import's starts."
                    },
                    "bulk_edit_sync_tick_seconds": {
                        "type": "integer",
                        "maximum": 60,
                        "minimum": 1,
                        "title": "Seconds per restart step",
                        "description": "Length of one restart step after a mass edit."
                    },
                    "bulk_edit_sync_scan": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 100,
                        "title": "Streams checked per step",
                        "description": "Most changed streams need no restart (an idle on-demand stream has nothing running). This bounds how many one step looks through to find those that do."
                    },
                    "bulk_delete_chunk_size": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 10,
                        "title": "Streams deleted per batch",
                        "description": "Streams a mass delete removes per transaction, with everything they own."
                    },
                    "bulk_delete_session_batch_size": {
                        "type": "integer",
                        "maximum": 50000,
                        "minimum": 50,
                        "title": "Viewing history rows removed per batch",
                        "description": "A long-running channel has thousands of session rows. They are removed in batches of this size so no lock is held for long."
                    },
                    "bulk_delete_max_stops": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 0,
                        "title": "Stop requests per delete",
                        "description": "Emergency ceiling on how many running streams one delete stops on their servers. Past it, deleted streams keep running on the server until stopped by hand, so leave it at no limit unless you need it."
                    },
                    "bulk_delete_background_threshold": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 1,
                        "title": "Admin deletes run in the background from",
                        "description": "Deletes started from the back office run in the background from this many rows. Deletes from the dashboard always run in the background."
                    },
                    "line_down_streams": {
                        "type": "integer",
                        "maximum": 100000,
                        "minimum": 2,
                        "title": "A line looks down when this many channels fail",
                        "description": "When this many channels on one provider line (its server and login) failed to open recently, and almost none on it opened, the Streams page and the provider say the line looks down, with a way to move its streams to another line."
                    },
                    "line_down_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "…within (minutes)",
                        "description": "How recent those failures must be. Only failures the streaming servers already saw count: nothing is tried just to find out."
                    },
                    "provider_warn_days": {
                        "type": "integer",
                        "maximum": 90,
                        "minimum": 1,
                        "title": "Warn before a provider line ends (days)",
                        "description": "A provider whose line ends within this many days is shown on the overview and on its page, as is one that is full, refused or switched off by the provider."
                    },
                    "source_checks_per_server": {
                        "type": "integer",
                        "maximum": 8,
                        "minimum": 1,
                        "title": "Sources one server checks at once",
                        "description": "\"Check sources now\" reads each source once through a streaming server, this many at a time per server, and never more at once on one line than the line has free connections."
                    },
                    "task_stall_seconds": {
                        "type": "integer",
                        "maximum": 86400,
                        "minimum": 60,
                        "title": "Silence before a task counts as stalled",
                        "description": "A running task that has made no progress for this long is shown as stalled — usually the panel restarted while it ran — and can be resumed. Too short flags slow tasks that are still working."
                    },
                    "background_task_threads": {
                        "type": "integer",
                        "maximum": 32,
                        "minimum": 1,
                        "title": "Background worker threads",
                        "description": "Threads each panel process uses for background work: imports, bulk jobs, messages to streaming servers. Each holds a database connection, so more threads on a small box can exhaust the database. Applies after the panel restarts."
                    },
                    "db_deadlock_retries": {
                        "type": "integer",
                        "maximum": 20,
                        "minimum": 0,
                        "title": "Retries after a database deadlock",
                        "description": "Bulk jobs and cleanup run alongside viewers starting sessions, and the database occasionally cancels one of two colliding transactions. The cancelled one is retried this many times before the job fails."
                    },
                    "db_deadlock_backoff_ms": {
                        "type": "integer",
                        "maximum": 5000,
                        "minimum": 1,
                        "title": "First retry delay",
                        "description": "Wait before the first retry; it doubles each time."
                    },
                    "db_deadlock_max_backoff_ms": {
                        "type": "integer",
                        "maximum": 60000,
                        "minimum": 1,
                        "title": "Longest retry delay",
                        "description": "Upper bound on the doubling wait."
                    },
                    "player_api_cache_seconds": {
                        "type": "integer",
                        "maximum": 3600,
                        "minimum": 0,
                        "title": "Catalogue lists kept for",
                        "description": "Player apps download the whole channel, film and series lists when they log in. Each list is built once per set of bouquets and reused for this long, so a wave of logins after an outage costs one build rather than one per player. Catalogue changes reach player apps within this time. Off builds every list on every request."
                    },
                    "playlist_cache_mb": {
                        "type": "integer",
                        "maximum": 102400,
                        "minimum": 0,
                        "title": "Disk kept for ready playlists",
                        "description": "The film and episode part of a playlist is written once per set of bouquets and reused until the catalogue changes, so a playlist of half a million titles downloads in about a second instead of being rebuilt each time. The least recently downloaded ones are removed past this size. Off builds every playlist on every download."
                    },
                    "logo_auto_fill": {
                        "type": "boolean",
                        "title": "Fill in missing logos automatically",
                        "description": "Streams with no logo get the one Minimus finds for them: new and imported streams within minutes, the others once a day. A logo you set is never replaced."
                    },
                    "logo_min_score": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 80,
                        "title": "Logo match sureness",
                        "description": "How sure Minimus must be that a logo is the channel's before a stream gets it, in percent. Higher gives fewer streams a logo, and fewer wrong ones. A stream with a guide channel always gets that channel's logo."
                    },
                    "logo_disk_mb": {
                        "type": "integer",
                        "maximum": 10240,
                        "minimum": 0,
                        "title": "Disk kept for channel logos",
                        "description": "Logos found for streams are kept on this panel and served from its own address, so viewers never see another one. Past this size no more are kept. Off: playlists link to the pictures on Minimus instead, which uses no disk."
                    },
                    "tidy_unwatched_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 1,
                        "title": "Not watched for",
                        "description": "Streams → Tidy up lists streams nobody has watched for this many days. A stream nobody ever watched counts from the day it was added."
                    },
                    "tidy_failing_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "Failing for",
                        "description": "Streams → Tidy up lists streams that have not played for this many days and whose every source failed the last time it was tried."
                    },
                    "tidy_disabled_days": {
                        "type": "integer",
                        "maximum": 3650,
                        "minimum": 1,
                        "title": "Disabled for",
                        "description": "Streams → Tidy up lists disabled streams nobody has changed for this many days."
                    },
                    "reseller_trials": {
                        "type": "boolean",
                        "title": "Resellers can make trials",
                        "description": "Off: resellers cannot make trial lines at all, whatever their group allows. Operators always can. Each group sets how many trials its resellers may make (Users → Groups)."
                    },
                    "api_requests_per_minute": {
                        "type": "integer",
                        "maximum": 6000,
                        "minimum": 10,
                        "title": "Calls a minute per API key",
                        "description": "How many calls one API key, or one connected AI app, may make in a minute. Past it the panel answers \"too many requests\" until the minute is over, so one runaway script never slows the panel down for everyone."
                    },
                    "api_log_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "API calls listed for",
                        "description": "How many days each API key's and AI app's calls stay listed. Revoked and ended keys leave the API keys page after as long."
                    },
                    "api_log_max_rows": {
                        "type": "integer",
                        "maximum": 10000000,
                        "minimum": 10000,
                        "title": "API calls kept at most",
                        "description": "The list of calls never holds more than this many: past it the oldest go first, whatever their age. Each takes about 200 bytes."
                    },
                    "ai_app_access_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "AI app access lifetime",
                        "description": "How long an AI app's access lasts before it renews it on its own. Shorter means a stolen access is useful for less time; the app renews it without asking the person again."
                    },
                    "ai_app_idle_days": {
                        "type": "integer",
                        "maximum": 365,
                        "minimum": 1,
                        "title": "AI app stays signed in for",
                        "description": "An AI app that is not used for this many days must be approved again. Every use starts the count again. Disconnecting an app (AI apps) ends it at once."
                    }
                }
            },
            "PatchedProviderRequest": {
                "type": "object",
                "description": "One provider, with what its form edits. `password` is write-only:\nleft empty on an edit, the saved one is kept.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "kind": {
                        "$ref": "#/components/schemas/ProviderKindEnum"
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Enabled",
                        "description": "Off: the provider is neither checked nor synced."
                    },
                    "sync_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SyncEveryMinutesEnum"
                            }
                        ],
                        "title": "Sync",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "use_live": {
                        "type": "boolean",
                        "title": "Live channels",
                        "description": "Its live channels are offered for streams to follow. Off: a provider for its films or TV shows only."
                    },
                    "import_movies": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new films are added to Films."
                    },
                    "import_series": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new shows and episodes are added to TV shows."
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    },
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "maxLength": 255
                    },
                    "extra_hosts": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                        },
                        "maxItems": 20
                    },
                    "link_format": {
                        "$ref": "#/components/schemas/LinkFormatEnum"
                    },
                    "sync_names": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its name whenever the provider's differs."
                    },
                    "sync_logos": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its logo."
                    },
                    "sync_epg_ids": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its guide id, when the panel's guide has it."
                    },
                    "keep_history": {
                        "type": "boolean",
                        "description": "Keep a list of past syncs (the last 50). Off saves space: only the last result is kept."
                    },
                    "vod_categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodCategoriesEnum"
                            }
                        ],
                        "description": "Where imported titles are filed: under the provider's own categories, under their TMDB genres, or as your mapping says.\n\n* `playlist` - The provider's categories\n* `tmdb` - TMDB genres\n* `custom` - My own mapping"
                    },
                    "vod_category_map": {},
                    "vod_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_delivery": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodDeliveryEnum"
                            }
                        ],
                        "description": "Straight from the provider: the player is sent to the provider, which costs you no bandwidth but shows the player its address. Through a streaming server: a server passes the film through, hiding the provider, and every byte crosses it — always the one you choose, or any healthy one the panel picks (load balanced).\n\n* `redirect` - Straight from the provider\n* `proxy` - Through one streaming server\n* `balanced` - Through any streaming server (load balanced)"
                    },
                    "vod_proxy_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "vod_tmdb": {
                        "type": "boolean",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "spare": {
                        "type": "integer",
                        "nullable": true
                    }
                }
            },
            "PatchedSeasonRequest": {
                "type": "object",
                "properties": {
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "title": "TV Show"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Season Number",
                        "description": "0 for specials."
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "plot": {
                        "type": "string",
                        "title": "Overview"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    }
                }
            },
            "PatchedSecuritySettingsRequest": {
                "type": "object",
                "description": "The security rules (Settings → Security), the same for every line and server. `diagnostics` is read-only.",
                "properties": {
                    "rule_datacenter": {
                        "type": "boolean",
                        "title": "Rule: datacenter IP",
                        "description": "Treat a viewer whose ASN belongs to a hosting provider as a restreamer — a real customer watches from home, not from a rented server. IPs recognised as consumer VPN exits are excluded, so a customer using NordVPN or Surfshark is not caught by this rule."
                    },
                    "rule_pull_tool_ua": {
                        "type": "boolean",
                        "title": "Rule: pull-tool User-Agent",
                        "description": "Treat ffmpeg, GStreamer, curl, streamlink and similar tools as restreamers rather than players. Cheap and precise, but easy to fake: a restreamer only has to call itself a player."
                    },
                    "rule_many_sessions": {
                        "type": "boolean",
                        "title": "Rule: many sessions from one IP",
                        "description": "Treat a line running several simultaneous sessions from a single IP as a restreamer, unless the line is flagged as an authorised restreamer. This is the fan-out signal and the hardest to fake — the connections are counted on our side."
                    },
                    "many_sessions_threshold": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Sessions from one IP before it counts",
                        "description": "How many simultaneous sessions from the same IP trip the rule above. A household with several TVs is normal; keep this above the largest family you sell to."
                    },
                    "rule_long_session": {
                        "type": "boolean",
                        "title": "Rule: session running too long",
                        "description": "Treat a session that never stops as a restreamer. A person watches for hours and then stops; a relay holds the channel open indefinitely. Cannot be spoofed — it is measured, not declared."
                    },
                    "long_session_hours": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Hours before a session counts as too long",
                        "description": "Default 36 (a day and a half). Set it above anything a real viewer could plausibly do, including a TV left on overnight."
                    },
                    "block_restreamers": {
                        "type": "boolean",
                        "title": "Refuse detected restreamers",
                        "description": "When on, a connection the rules call a restreamer is refused (403) unless its line is flagged as an authorised restreamer. On by default, so a new panel is protected from the first stream rather than after someone remembers to arm it. Watch the Live Connections monitor early on and switch off any rule that catches real customers, because a viewer refused this way is not told why."
                    },
                    "auto_block": {
                        "type": "boolean",
                        "title": "Block attackers automatically",
                        "description": "Blocks an address for a while when it guesses passwords or floods the panel: sign-in, playlists and streams are all refused there, on the panel and every streaming server. Your servers, Cloudflare, and addresses where two or more of your customers are watching are never blocked; failed sign-ins never block an address where an admin signed in during the last 30 days. Locked out? On the panel's server run \"docker compose exec web uv run python manage.py unblock <address>\" in /opt/iptv-panel."
                    },
                    "signin_guard": {
                        "type": "boolean",
                        "title": "Failed sign-ins",
                        "description": "Too many failed sign-ins to this panel (the dashboard or the admin) from one address."
                    },
                    "signin_failures": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 3,
                        "title": "Failed sign-ins before a block",
                        "description": "From one address, within the time below. Past it, sign-in from there is refused before any password is checked."
                    },
                    "signin_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back failed sign-ins are counted."
                    },
                    "guess_guard": {
                        "type": "boolean",
                        "title": "Wrong passwords in customer links",
                        "description": "Too many different wrong usernames and passwords from one address in playlist links, player logins, channels, films, catch-up and the TV guide. A player that keeps retrying the same old password counts once."
                    },
                    "guess_limit": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 5,
                        "title": "Different wrong passwords before a block",
                        "description": "From one address, within the time below."
                    },
                    "guess_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back wrong passwords are counted."
                    },
                    "flood_guard": {
                        "type": "boolean",
                        "title": "Request floods",
                        "description": "Far more requests to this panel from one address than anyone sends, without a valid login. Plays, playlists and player apps signed in with a real account never count. Big attacks from many addresses need your hosting provider or Cloudflare."
                    },
                    "flood_per_minute": {
                        "type": "integer",
                        "maximum": 60000,
                        "minimum": 120,
                        "title": "Requests a minute before a block",
                        "description": "Requests a minute from one address that sign in with nothing valid. Plays, playlists and player logins with a real account (one that may watch) never count."
                    },
                    "block_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "Block for (minutes)",
                        "description": "How long the first automatic block of an address lasts."
                    },
                    "block_max_hours": {
                        "type": "integer",
                        "maximum": 720,
                        "minimum": 1,
                        "title": "Longest block (hours)",
                        "description": "An address blocked again within a day of its last block is blocked twice as long each time, up to this."
                    },
                    "never_block": {
                        "type": "string",
                        "title": "Never block these addresses",
                        "description": "One address, block (198.51.100.0/24) or range per line: never counted and never blocked automatically. Blocking one by hand still works."
                    },
                    "trust_own_proxy": {
                        "type": "boolean",
                        "title": "My own proxy sends the visitor's address",
                        "description": "Only for a panel installed without its own web server. Attack protection stays paused until you turn this on, because anyone could pretend to be another address and get it blocked. Turn it on only when the panel's port can be reached from your proxy alone (the installer publishes it on 127.0.0.1 unless told otherwise), and your proxy sets the header chosen below itself. CF-Connecting-IP is believed only from Cloudflare's addresses."
                    },
                    "proxy_header": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProxyHeaderEnum"
                            }
                        ],
                        "title": "Header your proxy names the visitor in",
                        "description": "With X-Forwarded-For, the panel reads the last address in it: the one your proxy added. If another CDN than Cloudflare sits in front of your proxy, make it pass the visitor's address, or its addresses get counted.\n\n* `x-forwarded-for` - X-Forwarded-For\n* `x-real-ip` - X-Real-IP"
                    },
                    "proxy_addresses": {
                        "type": "string",
                        "title": "Your proxy's addresses",
                        "description": "One address or block per line, as the panel sees your proxy. A proxy on the panel's private network needs none, except one that reaches it through Docker's gateway (a proxy on this server, through a published port): list that gateway here."
                    },
                    "hash_budget_per_minute": {
                        "type": "integer",
                        "maximum": 6000,
                        "minimum": 0,
                        "title": "Password checks a minute from failing addresses",
                        "description": "Shared by every address already at half its limit of wrong passwords: checking a password costs CPU, so past this they wait a minute. Other addresses, an admin's own sign-in and passwords the panel already knows are never held back. 0: 60 per CPU core of this server."
                    },
                    "under_attack": {
                        "type": "boolean",
                        "description": "For when the panel is being attacked: every check runs, even one switched off, limits drop to about a quarter and blocks last four times as long. Your team, your servers and private networks are still never blocked, but customers who share an address (a mobile network, an office) may be refused more often. Every page shows a red banner while it is on."
                    },
                    "under_attack_hours": {
                        "type": "integer",
                        "maximum": 168,
                        "minimum": 0,
                        "title": "Turn it off by itself after (hours)",
                        "description": "So a busy day does not leave the panel strict for good. 0 keeps it on until you turn it off."
                    }
                }
            },
            "PatchedSeriesRequest": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this show reports as its own where exactly one is allowed: the M3U playlist group of every episode, and the title-uniqueness rule below. Always among `categories`."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this show appears under. Browsing and filtering read this; it always contains `category`."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this show belongs to. A line with none of them in common cannot watch any of its episodes."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true,
                        "title": "First Aired"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "title": "Created By",
                        "description": "The show's creators — what TMDB lists for a series instead of a director.",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the show was matched on TMDB. Seasons and episodes are looked up under it, so a sync fills every episode's own metadata without searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive show disappears from playlists and refuses playback of every episode, without anything being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    }
                }
            },
            "PatchedServerRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Display Name",
                        "maxLength": 128
                    },
                    "domain": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Public domain",
                        "description": "The server's public address (a host name). The install sets it on streaming servers.",
                        "maxLength": 255
                    },
                    "addresses": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 253
                        },
                        "writeOnly": true,
                        "description": "The names viewers are sent to on this server, the main one first.",
                        "maxItems": 10,
                        "minItems": 1
                    },
                    "address_rule": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/AddressRuleEnum"
                            }
                        ],
                        "title": "How viewers are spread",
                        "description": "Which of the streaming addresses each new viewer is sent to.\n\n* `turns` - Take turns\n* `least_busy` - Least busy\n* `same_viewer` - Same address per viewer\n* `random` - At random"
                    },
                    "caddy_managed": {
                        "type": "boolean",
                        "title": "Auto-configure Caddy",
                        "description": "Whether the panel keeps the server's web address set up by itself."
                    },
                    "stream_port": {
                        "type": "integer",
                        "description": "The port viewers reach the streams on. Setting it asks the server to move there."
                    },
                    "max_streams": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Hard ceiling. Rejected by FILL/LEAST_LOADED when reached."
                    },
                    "weight": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Higher = more streams routed here under HASH mode."
                    },
                    "network_capacity_mbps": {
                        "type": "integer",
                        "maximum": 400000,
                        "minimum": 10,
                        "nullable": true,
                        "title": "Network capacity (Mbps)",
                        "description": "The bandwidth this server's port can push, in megabits per second — for example 10000 for a 10 Gbps port. Leave empty to use the speed its network card reports."
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "description": "Operator switch. Set False to drain a server."
                    },
                    "serves_streams": {
                        "type": "boolean",
                        "description": "Whether streams are sent to this server. Streaming servers are, once added, until you take one out; the panel's own server only after it is set to stream."
                    },
                    "serves_vod": {
                        "type": "boolean",
                        "description": "Whether this node may hold movie files and serve them. Every streaming node does by default — it is set when a node registers or the panel is promoted. Placement still only sends a file where it fits (`vod_has_room`: the quota, or the free space the node reports), so a node with no room is skipped rather than filled. Turn it off to keep movies off a node entirely."
                    },
                    "vod_max_bytes": {
                        "type": "integer",
                        "maximum": 9223372036854775807,
                        "minimum": 0,
                        "format": "int64",
                        "title": "VOD storage quota (bytes)",
                        "description": "Ceiling on what movies may occupy here. 0 means 'use the disk's real free space instead'. Set this when VOD shares a filesystem with anything else you care about — a full disk stops live streams on this node too, not just movies."
                    },
                    "archive_max_bytes": {
                        "type": "integer",
                        "maximum": 9223372036854775807,
                        "minimum": 0,
                        "format": "int64",
                        "title": "Catch-up storage limit (bytes)",
                        "description": "The most catch-up recordings may use here. Over it, the oldest recordings go first. 0 = no limit beyond the disk, which always keeps a share free for movies."
                    }
                }
            },
            "PatchedSourceRequest": {
                "type": "object",
                "description": "One address a stream is read from.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Source Name",
                        "maxLength": 255
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "minLength": 1,
                        "title": "Source URL",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "quality": {
                        "type": "string",
                        "nullable": true,
                        "description": "e.g., 720p, 1080p, 4K",
                        "maxLength": 10
                    },
                    "bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648,
                        "nullable": true,
                        "description": "Bitrate in kbps"
                    }
                }
            },
            "PatchedStorageConnectionRequest": {
                "type": "object",
                "description": "A bucket. The secret is write-only: `has_secret` says whether one is\nset, and leaving it out of an update keeps the stored one.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "description": "How this bucket is named wherever it can be picked, e.g. \"Movies (Wasabi)\".",
                        "maxLength": 100
                    },
                    "endpoint": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Endpoint URL",
                        "description": "e.g. https://s3.eu-west-1.amazonaws.com, or your MinIO / Wasabi / R2 / Backblaze endpoint.",
                        "maxLength": 255
                    },
                    "bucket": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "region": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Part of the request signature. MinIO accepts us-east-1 unless configured otherwise.",
                        "maxLength": 64
                    },
                    "access_key": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Access key ID",
                        "maxLength": 255
                    },
                    "secret_key": {
                        "type": "string",
                        "writeOnly": true
                    }
                }
            },
            "PatchedStreamRequest": {
                "type": "object",
                "description": "A stream: what it plays from (`sources`), where it is listed\n(`categories`, `bouquets`) and how servers play it. A created channel\n(`plan`) plays movies and episodes on a schedule; a delayed stream\n(`delay`) plays a channel later.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Stream Name",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category it is listed under; always holds `category`, its main one."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this stream belongs to"
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSourceRequest"
                        }
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "thumbnail": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 1000
                    },
                    "epg_channel_id": {
                        "type": "string",
                        "title": "EPG channel",
                        "description": "The guide channel players show for this stream. Blank: no guide.",
                        "maxLength": 255
                    },
                    "streaming_engine": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamingEngineEnum"
                            }
                        ],
                        "description": "Engine used for video processing\n\n* `gstreamer` - GStreamer\n* `ffmpeg` - FFmpeg"
                    },
                    "engine_config": {
                        "title": "Engine Configuration",
                        "description": "JSON configuration for streaming engine parameters"
                    },
                    "transcoding_profile": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Optional: converts the stream's picture and sound this way."
                    },
                    "allow_passthrough": {
                        "type": "boolean",
                        "description": "On (the default): a source players can play is sent as it is, and one they cannot is converted. Off: the stream is always converted. A transcoding profile always converts."
                    },
                    "user_agent": {
                        "type": "string",
                        "description": "Sent to the source instead of the server's own. Leave empty unless the provider refuses other players.",
                        "maxLength": 512
                    },
                    "http_proxy": {
                        "type": "string",
                        "title": "Proxy",
                        "description": "Reach the source through this HTTP proxy, e.g. http://10.0.0.5:3128.",
                        "maxLength": 255
                    },
                    "http_headers": {
                        "type": "string",
                        "title": "Extra headers",
                        "description": "One \"Name: value\" per line, e.g. \"Referer: https://example.com\" or \"Cookie: session=abc\"."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "is_on_demand": {
                        "type": "boolean",
                        "description": "Started when someone watches and stopped once nobody does. Off: it runs all the time."
                    },
                    "is_direct": {
                        "type": "boolean",
                        "title": "Direct Mode",
                        "description": "Send viewers straight to the source instead of playing it through a server. The line and its rules are still checked, but the source address (and any login in it) is shown to the viewer, there is no connection limit, no live connection row and no backup source."
                    },
                    "routing_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RoutingModeEnum"
                            }
                        ],
                        "description": "`auto`: any streaming server with room plays it (never the panel's own); `pinned`: the servers of `pinned_servers` in order, the next taking over when one fails.\n\n* `auto` - Auto load-balance (excludes panel)\n* `pinned` - Pinned (ordered failover)"
                    },
                    "pinned_servers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamPinnedServerRequest"
                        }
                    },
                    "auto_eligible_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "archive_days": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": 0,
                        "title": "Catch-up days",
                        "description": "Record this channel so viewers can watch what aired in the last this many days (TV archive). 0 = off.\n\nWhat it costs: the channel runs all the time on the server that records it, so it holds one provider connection permanently, and it uses disk at its own bitrate (about 10.8 GB a day per Mb/s). Recordings are the channel as viewers get it, never re-encoded. Turning it off deletes the recordings."
                    },
                    "archive_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Catch-up server",
                        "description": "The server that records this channel and plays its catch-up. The channel runs there, so viewers of the live channel are sent there too: one provider connection, not two. If it goes down, the channel moves to another server and recording waits for it."
                    },
                    "plan": {
                        "writeOnly": true
                    },
                    "delay": {
                        "writeOnly": true
                    }
                }
            },
            "PatchedStreamingSettingsRequest": {
                "type": "object",
                "description": "The streaming settings (Settings → Streaming). The channel-down video is uploaded on its own; this says whether there is one.",
                "properties": {
                    "down_video_enabled": {
                        "type": "boolean",
                        "title": "Show a video when a channel is down",
                        "description": "Viewers of a channel that cannot start watch it for a while, then their player tries the channel again. Off: the player gets an error at once."
                    },
                    "down_video_seconds": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Retry after (seconds)",
                        "description": "How long a viewer watches it before the player tries the channel again."
                    },
                    "use_video_card": {
                        "type": "boolean",
                        "title": "Encode on the video card when a server has one",
                        "description": "NVIDIA (NVENC), Intel or AMD cards encode transcoded streams and the converted titles of created channels for a fraction of the processor. Off: the processor encodes."
                    }
                }
            },
            "PatchedTranscodingProfileRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Profile Name",
                        "description": "Display name (e.g. SD, HD, FHD).",
                        "maxLength": 64
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "video_codec": {
                        "$ref": "#/components/schemas/VideoCodecEnum"
                    },
                    "audio_codec": {
                        "$ref": "#/components/schemas/AudioCodecEnum"
                    },
                    "width": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame width in pixels (e.g. 1280)."
                    },
                    "height": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame height in pixels (e.g. 720)."
                    },
                    "fps": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame rate. Use 30 for TV unless the source is 60fps."
                    },
                    "video_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Video bitrate ceiling in kbps (encoder uses less for quiet scenes)."
                    },
                    "audio_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Audio bitrate in kbps."
                    },
                    "keyframe_interval": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Keyframe interval in frames. 30 ≈ 1s at 30fps."
                    },
                    "preset": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PresetEnum"
                            }
                        ],
                        "description": "Encoder speed preset (only honoured by software x264enc).\n\n* `ultrafast` - Ultrafast\n* `superfast` - Superfast\n* `veryfast` - Veryfast\n* `faster` - Faster\n* `fast` - Fast\n* `medium` - Medium"
                    },
                    "quality": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Quantizer / CRF. 18-28 sane range; 22 ≈ transparent."
                    }
                }
            },
            "PatchedUnlimitedRequest": {
                "type": "object",
                "properties": {
                    "unlimited": {
                        "type": "boolean"
                    }
                }
            },
            "PatchedUserPackageRequest": {
                "type": "object",
                "properties": {
                    "line_user": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Line user who received this package"
                    },
                    "package": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When this package expires for the user"
                    },
                    "is_active": {
                        "type": "boolean"
                    }
                }
            },
            "PatchedUserRequest": {
                "type": "object",
                "description": "An account: its details, status, groups, permissions and credits.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_superuser": {
                        "type": "boolean",
                        "title": "Superuser status",
                        "description": "Designates that this user has all permissions without explicitly assigning them."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                }
            },
            "PatchedVodSettingsRequest": {
                "type": "object",
                "description": "The movie and TV show settings (Settings → VOD). The API key is write-only: it is never sent back.",
                "properties": {
                    "tmdb_api_key": {
                        "type": "string",
                        "writeOnly": true
                    },
                    "tmdb_language": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Language for plots and titles, e.g. en-US, fr-FR, ar-SA.",
                        "maxLength": 16
                    },
                    "tmdb_image_base": {
                        "type": "string",
                        "minLength": 1,
                        "title": "TMDB image base URL",
                        "description": "Prefix for poster and backdrop paths. The trailing size segment (w500, original, ...) decides how large the stored artwork URLs are.",
                        "maxLength": 255
                    },
                    "s3_storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Movie storage",
                        "description": "The bucket movies are browsed and read from. Empty turns the object-storage source off. Buckets are added under Settings → Storage."
                    },
                    "s3_presign_ttl": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Signed link lifetime (seconds)",
                        "description": "How long a signed download link stays valid. It must outlast the transfer itself: if it expires mid-download, a node resuming a large file is refused partway through. Default 6 hours."
                    },
                    "ticket_expiration": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Playback ticket lifetime (seconds)",
                        "description": "How long a movie link stays valid once a viewer opens it. Longer than a live token by necessity — a seeking player reopens the connection on every scrub, so the link has to survive a whole film. This is the blast-radius control: shorten it if a shared link matters more than a viewer having to reopen a long movie. Default 4 hours."
                    },
                    "upload_chunk_mb": {
                        "type": "integer",
                        "maximum": 16,
                        "minimum": 1,
                        "title": "Upload chunk size (MB)",
                        "description": "How much of a file the browser sends per request when you upload a movie. Smaller loses less to a dropped connection; larger means fewer round trips. Streaming servers refuse chunks above their own limit (16 MB unless changed on the server). Default 8 MB."
                    },
                    "upload_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Upload permission lifetime (seconds)",
                        "description": "How long a browser may keep sending one upload. It has to outlast the upload itself — a 40 GB file on a slow line takes hours — but it authorises writes, so not much longer. Default 6 hours."
                    },
                    "replica_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Server-to-server copy lifetime (seconds)",
                        "description": "How long one streaming server may pull a movie from another when copying it. Fast links, but a large library copied one file at a time can take a while. Default 24 hours."
                    }
                }
            },
            "PatchedWatchFolderRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Empty: the folder's own name.",
                        "maxLength": 120
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Watching",
                        "description": "Off: paused, the folder is scanned only when asked."
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFolderKindEnum"
                            }
                        ],
                        "description": "What the folder holds. A file that looks like the other kind is skipped, and says so.\n\n* `movies` - Movies\n* `series` - TV shows\n* `both` - Movies and TV shows"
                    },
                    "source": {
                        "$ref": "#/components/schemas/WatchFolderSourceEnum"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "root": {
                        "description": "Incoming folder: files are moved into the server's storage. Media folder: files stay where they are.\n\n* `incoming` - Incoming folder\n* `media` - Media folder",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/RootEnum"
                            },
                            {
                                "$ref": "#/components/schemas/BlankEnum"
                            }
                        ]
                    },
                    "path": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "delivery": {
                        "$ref": "#/components/schemas/WatchFolderDeliveryEnum"
                    },
                    "scan_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScanEveryMinutesEnum"
                            }
                        ],
                        "title": "Scan",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CategoriesEnum"
                            }
                        ],
                        "description": "Folder names: \"Action/Heat (1995).mkv\" goes under Action (a file in no such folder goes under its TMDB genres). TMDB genres. One category for movies and one for TV shows. Or your own mapping of folder names (else genres) to categories.\n\n* `folder` - Folder names\n* `tmdb` - TMDB genres\n* `fixed` - One category\n* `custom` - My own mapping"
                    },
                    "movie_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "series_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "category_map": {},
                    "movie_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "use_tmdb": {
                        "type": "boolean",
                        "title": "Details from TMDB",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "add_unmatched": {
                        "type": "boolean",
                        "description": "A title TMDB does not know is added with its file name. Off: it waits for you."
                    },
                    "tmdb_language": {
                        "type": "string",
                        "description": "Language of titles and plots from TMDB, e.g. fr-FR. Empty: the one in Settings → VOD.",
                        "maxLength": 16
                    },
                    "extensions": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Only files with these extensions are read, e.g. mkv,mp4.",
                        "maxLength": 255
                    }
                }
            },
            "PeriodEnum": {
                "enum": [
                    "day",
                    "week",
                    "month"
                ],
                "type": "string",
                "description": "* `day` - day\n* `week` - week\n* `month` - month"
            },
            "Permission": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "codename": {
                        "type": "string",
                        "maxLength": 100
                    },
                    "content_type": {
                        "type": "integer",
                        "readOnly": true
                    }
                },
                "required": [
                    "codename",
                    "content_type",
                    "id",
                    "name"
                ]
            },
            "PlannedFile": {
                "type": "object",
                "properties": {
                    "ref": {
                        "type": "string",
                        "description": "What to send back in `items`: a path, key or link."
                    },
                    "name": {
                        "type": "string"
                    },
                    "size": {
                        "type": "integer"
                    },
                    "season": {
                        "type": "integer",
                        "nullable": true
                    },
                    "episode": {
                        "type": "integer",
                        "nullable": true
                    },
                    "matched": {
                        "type": "boolean",
                        "description": "A season and episode were read from it."
                    },
                    "duplicate": {
                        "type": "boolean",
                        "description": "An earlier file claims the same episode."
                    },
                    "existing": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ExistingEpisode"
                            }
                        ],
                        "nullable": true,
                        "description": "The episode the show already has there."
                    }
                },
                "required": [
                    "duplicate",
                    "episode",
                    "existing",
                    "matched",
                    "name",
                    "ref",
                    "season",
                    "size"
                ]
            },
            "PlaylistImportGroupsRequest": {
                "type": "object",
                "properties": {
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    }
                }
            },
            "PlaylistImportOptions": {
                "type": "object",
                "properties": {
                    "category_modes": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "conflict_modes": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "streaming_engines": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "routing_modes": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "defaults": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "max_playlist_bytes": {
                        "type": "integer"
                    },
                    "statuses": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "start_streams_threshold": {
                        "type": "integer"
                    },
                    "start_rate": {
                        "$ref": "#/components/schemas/PlaylistImportStartRate"
                    }
                },
                "required": [
                    "category_modes",
                    "conflict_modes",
                    "defaults",
                    "max_playlist_bytes",
                    "routing_modes",
                    "start_rate",
                    "start_streams_threshold",
                    "statuses",
                    "streaming_engines"
                ]
            },
            "PlaylistImportProviderMatches": {
                "type": "object",
                "properties": {
                    "channels": {
                        "type": "integer"
                    },
                    "by_source": {
                        "type": "integer"
                    },
                    "ambiguous": {
                        "type": "integer"
                    },
                    "by_name": {
                        "type": "integer"
                    }
                },
                "required": [
                    "ambiguous",
                    "by_name",
                    "by_source",
                    "channels"
                ]
            },
            "PlaylistImportStartRate": {
                "type": "object",
                "properties": {
                    "tick_seconds": {
                        "type": "integer"
                    },
                    "per_tick": {
                        "type": "integer"
                    },
                    "per_provider_per_tick": {
                        "type": "integer"
                    }
                },
                "required": [
                    "per_provider_per_tick",
                    "per_tick",
                    "tick_seconds"
                ]
            },
            "PlaylistImportStartRequest": {
                "type": "object",
                "properties": {
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "category_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CategoryModeEnum"
                            }
                        ],
                        "default": "auto",
                        "description": "`auto`: a category per group, reusing one of the same name; `existing`: all in `category`.\n\n* `auto` - auto\n* `existing` - existing"
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "extra_categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "fallback_category": {
                        "type": "string",
                        "format": "uuid",
                        "description": "For channels without a group, with `category_mode: auto`."
                    },
                    "conflict_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ConflictModeEnum"
                            }
                        ],
                        "default": "skip",
                        "description": "When a stream of the same name and category exists.\n\n* `skip` - Skip existing\n* `update` - Update existing\n* `suffix` - Create with a numbered suffix"
                    },
                    "is_on_demand": {
                        "type": "boolean",
                        "default": false
                    },
                    "is_active": {
                        "type": "boolean",
                        "default": true
                    },
                    "allow_passthrough": {
                        "type": "boolean",
                        "default": true
                    },
                    "follow_providers": {
                        "type": "boolean",
                        "default": true,
                        "description": "Streams take the name, logo or guide of a provider channel with the same source."
                    },
                    "transcoding_profile": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "streaming_engine": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamingEngineEnum"
                            }
                        ],
                        "default": "gstreamer"
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "routing_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RoutingModeEnum"
                            }
                        ],
                        "default": "auto"
                    },
                    "pinned_primary": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "pinned_backup_1": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "pinned_backup_2": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "auto_eligible_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "sort_order_start": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Numbers from here; blank: after every stream."
                    }
                },
                "required": [
                    "groups"
                ]
            },
            "PlaylistImportTextRequest": {
                "type": "object",
                "properties": {
                    "playlist_text": {
                        "type": "string",
                        "minLength": 1
                    },
                    "filename": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "required": [
                    "playlist_text"
                ]
            },
            "PresetEnum": {
                "enum": [
                    "ultrafast",
                    "superfast",
                    "veryfast",
                    "faster",
                    "fast",
                    "medium"
                ],
                "type": "string",
                "description": "* `ultrafast` - Ultrafast\n* `superfast` - Superfast\n* `veryfast` - Veryfast\n* `faster` - Faster\n* `fast` - Fast\n* `medium` - Medium"
            },
            "PromotePanelRequest": {
                "type": "object",
                "description": "The panel's own server, to stream too: its addresses and the name viewers reach it by.",
                "properties": {
                    "public_url": {
                        "type": "string",
                        "minLength": 1
                    },
                    "internal_url": {
                        "type": "string",
                        "minLength": 1
                    },
                    "streaming_domain": {
                        "type": "string",
                        "default": "",
                        "description": "The address the panel's own server streams on. The panel's own address does not change.",
                        "maxLength": 255
                    },
                    "capabilities": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 32
                        }
                    },
                    "max_streams": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "rotate": {
                        "type": "boolean",
                        "default": false,
                        "description": "Make new credentials for the panel's own streaming server, instead of reusing the current ones."
                    }
                },
                "required": [
                    "internal_url",
                    "public_url"
                ]
            },
            "Provider": {
                "type": "object",
                "description": "One provider, with what its form edits. `password` is write-only:\nleft empty on an edit, the saved one is kept.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 120
                    },
                    "kind": {
                        "$ref": "#/components/schemas/ProviderKindEnum"
                    },
                    "address": {
                        "type": "string",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Enabled",
                        "description": "Off: the provider is neither checked nor synced."
                    },
                    "status": {
                        "type": "string",
                        "readOnly": true
                    },
                    "status_detail": {
                        "type": "string",
                        "readOnly": true
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "connections": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderConnections"
                            }
                        ],
                        "readOnly": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "expires_known": {
                        "type": "boolean",
                        "description": "Whether `expires_at` is what the provider said (null: never\nexpires) rather than nothing known: it refused the login, could not\nbe reached, or is an M3U, which says nothing about an expiry.",
                        "readOnly": true
                    },
                    "is_trial": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "account_created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "counts": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderCounts"
                            }
                        ],
                        "readOnly": true
                    },
                    "sync_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SyncEveryMinutesEnum"
                            }
                        ],
                        "title": "Sync",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "last_sync_started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_ok": {
                        "type": "boolean",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_summary": {
                        "readOnly": true
                    },
                    "next_sync_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "syncing": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "linked_streams": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    },
                    "gone_links": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    },
                    "use_live": {
                        "type": "boolean",
                        "title": "Live channels",
                        "description": "Its live channels are offered for streams to follow. Off: a provider for its films or TV shows only."
                    },
                    "import_movies": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new films are added to Films."
                    },
                    "import_series": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new shows and episodes are added to TV shows."
                    },
                    "url": {
                        "type": "string",
                        "maxLength": 2000
                    },
                    "has_password": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "extra_hosts": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "maxLength": 300
                        },
                        "maxItems": 20
                    },
                    "link_format": {
                        "$ref": "#/components/schemas/LinkFormatEnum"
                    },
                    "sync_names": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its name whenever the provider's differs."
                    },
                    "sync_logos": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its logo."
                    },
                    "sync_epg_ids": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its guide id, when the panel's guide has it."
                    },
                    "keep_history": {
                        "type": "boolean",
                        "description": "Keep a list of past syncs (the last 50). Off saves space: only the last result is kept."
                    },
                    "vod_categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodCategoriesEnum"
                            }
                        ],
                        "description": "Where imported titles are filed: under the provider's own categories, under their TMDB genres, or as your mapping says.\n\n* `playlist` - The provider's categories\n* `tmdb` - TMDB genres\n* `custom` - My own mapping"
                    },
                    "vod_category_map": {},
                    "vod_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_delivery": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodDeliveryEnum"
                            }
                        ],
                        "description": "Straight from the provider: the player is sent to the provider, which costs you no bandwidth but shows the player its address. Through a streaming server: a server passes the film through, hiding the provider, and every byte crosses it — always the one you choose, or any healthy one the panel picks (load balanced).\n\n* `redirect` - Straight from the provider\n* `proxy` - Through one streaming server\n* `balanced` - Through any streaming server (load balanced)"
                    },
                    "vod_proxy_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "vod_tmdb": {
                        "type": "boolean",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "vod": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderVodOverview"
                            }
                        ],
                        "readOnly": true
                    },
                    "spare": {
                        "type": "integer",
                        "nullable": true
                    },
                    "spare_name": {
                        "type": "string",
                        "readOnly": true,
                        "default": ""
                    }
                },
                "required": [
                    "account_created_at",
                    "address",
                    "checked_at",
                    "connections",
                    "counts",
                    "expires_at",
                    "expires_known",
                    "gone_links",
                    "has_password",
                    "id",
                    "is_trial",
                    "last_sync_at",
                    "last_sync_ok",
                    "last_sync_started_at",
                    "last_sync_summary",
                    "linked_streams",
                    "name",
                    "next_sync_at",
                    "spare_name",
                    "status",
                    "status_detail",
                    "syncing",
                    "url",
                    "vod"
                ]
            },
            "ProviderAlert": {
                "type": "object",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/ProviderAlertKindEnum"
                    },
                    "tone": {
                        "$ref": "#/components/schemas/ToneEnum"
                    },
                    "text": {
                        "type": "string"
                    }
                },
                "required": [
                    "kind",
                    "name",
                    "provider",
                    "text",
                    "tone"
                ]
            },
            "ProviderAlertKindEnum": {
                "enum": [
                    "expired",
                    "disabled",
                    "wrong_login",
                    "unreachable",
                    "expiring",
                    "full"
                ],
                "type": "string",
                "description": "* `expired` - expired\n* `disabled` - disabled\n* `wrong_login` - wrong_login\n* `unreachable` - unreachable\n* `expiring` - expiring\n* `full` - full"
            },
            "ProviderAlertLine": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "`server|username` of the line."
                    },
                    "host": {
                        "type": "string"
                    },
                    "user": {
                        "type": "string"
                    },
                    "provider": {
                        "type": "integer",
                        "nullable": true
                    },
                    "provider_name": {
                        "type": "string"
                    },
                    "failed": {
                        "type": "integer",
                        "description": "Streams on it that failed to open lately."
                    },
                    "opened": {
                        "type": "integer",
                        "description": "Sources on it that opened lately."
                    },
                    "reason": {
                        "type": "string",
                        "description": "The most frequent reason, as a code."
                    },
                    "reason_words": {
                        "type": "string"
                    },
                    "since": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "last": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "streams": {
                        "type": "integer",
                        "description": "Streams with a source on this line."
                    }
                },
                "required": [
                    "failed",
                    "host",
                    "key",
                    "last",
                    "opened",
                    "provider",
                    "provider_name",
                    "reason",
                    "reason_words",
                    "since",
                    "streams",
                    "user"
                ]
            },
            "ProviderAlerts": {
                "type": "object",
                "properties": {
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderAlertLine"
                        },
                        "description": "Lines that look down, most failed first."
                    },
                    "warnings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderAlert"
                        },
                        "description": "The most serious first."
                    }
                },
                "required": [
                    "lines",
                    "warnings"
                ]
            },
            "ProviderCatalogueItem": {
                "type": "object",
                "properties": {
                    "item_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "category": {
                        "type": "string",
                        "readOnly": true
                    },
                    "category_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "icon": {
                        "type": "string",
                        "readOnly": true
                    },
                    "epg_channel_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "added_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "changed_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "gone_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "state": {
                        "type": "string",
                        "nullable": true,
                        "description": "`new` / `changed` in the provider's last sync, `gone`, or\nnull: the same rule as the `state` filter.",
                        "readOnly": true
                    },
                    "linked_stream": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderNamedRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "link_url": {
                        "type": "string",
                        "readOnly": true
                    },
                    "panel_category": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderNamedRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "season": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "episode_num": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "import_state": {
                        "readOnly": true,
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/ImportStateEnum"
                            },
                            {
                                "$ref": "#/components/schemas/BlankEnum"
                            }
                        ]
                    },
                    "import_note": {
                        "type": "string",
                        "readOnly": true
                    },
                    "title": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderItemTitle"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    }
                },
                "required": [
                    "added_at",
                    "category",
                    "category_id",
                    "changed_at",
                    "epg_channel_id",
                    "episode_num",
                    "gone_at",
                    "icon",
                    "import_note",
                    "import_state",
                    "item_id",
                    "link_url",
                    "linked_stream",
                    "name",
                    "panel_category",
                    "season",
                    "state",
                    "title"
                ]
            },
            "ProviderConnections": {
                "type": "object",
                "properties": {
                    "active": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Connections in use, as the provider said."
                    },
                    "max": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Connections the line allows."
                    },
                    "ours": {
                        "type": "integer",
                        "description": "Connections this panel's servers hold on it now."
                    }
                },
                "required": [
                    "active",
                    "max",
                    "ours"
                ]
            },
            "ProviderCounts": {
                "type": "object",
                "properties": {
                    "live": {
                        "type": "integer",
                        "description": "Channels."
                    },
                    "movies": {
                        "type": "integer"
                    },
                    "series": {
                        "type": "integer",
                        "description": "TV shows."
                    }
                },
                "required": [
                    "live",
                    "movies",
                    "series"
                ]
            },
            "ProviderDeleted": {
                "type": "object",
                "properties": {
                    "unlinked": {
                        "type": "integer",
                        "description": "Streams that followed it."
                    }
                },
                "required": [
                    "unlinked"
                ]
            },
            "ProviderItemSearch": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "next": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                    },
                    "previous": {
                        "type": "string",
                        "format": "uri",
                        "nullable": true
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderItemSearchGroup"
                        }
                    }
                },
                "required": [
                    "count",
                    "next",
                    "previous",
                    "results"
                ]
            },
            "ProviderItemSearchGroup": {
                "type": "object",
                "properties": {
                    "provider": {
                        "$ref": "#/components/schemas/ProviderItemSearchProvider"
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderPickerItem"
                        }
                    }
                },
                "required": [
                    "items",
                    "provider"
                ]
            },
            "ProviderItemSearchProvider": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "ProviderItemTitle": {
                "type": "object",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/ProviderItemTitleKindEnum"
                    },
                    "id": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "kind"
                ]
            },
            "ProviderItemTitleKindEnum": {
                "enum": [
                    "movie",
                    "series",
                    "episode"
                ],
                "type": "string",
                "description": "* `movie` - movie\n* `series` - series\n* `episode` - episode"
            },
            "ProviderKindEnum": {
                "enum": [
                    "xtream",
                    "m3u"
                ],
                "type": "string",
                "description": "* `xtream` - A provider login: server, username and password\n* `m3u` - An M3U address"
            },
            "ProviderLastImport": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "status": {
                        "type": "string",
                        "description": "pending, running, completed, failed or cancelled."
                    },
                    "phase": {
                        "type": "string"
                    },
                    "done": {
                        "type": "integer"
                    },
                    "total": {
                        "type": "integer"
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        }
                    },
                    "message": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "counts",
                    "created_at",
                    "done",
                    "finished_at",
                    "id",
                    "message",
                    "phase",
                    "started_at",
                    "status",
                    "total",
                    "updated_at"
                ]
            },
            "ProviderLinkMatch": {
                "type": "object",
                "properties": {
                    "stream": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "stream_name": {
                        "type": "string"
                    },
                    "provider": {
                        "type": "integer"
                    },
                    "provider_name": {
                        "type": "string"
                    },
                    "item_id": {
                        "type": "string"
                    },
                    "item_name": {
                        "type": "string"
                    },
                    "why": {
                        "$ref": "#/components/schemas/ProviderLinkMatchWhyEnum"
                    },
                    "source_order": {
                        "type": "integer",
                        "nullable": true
                    },
                    "ambiguous": {
                        "type": "boolean"
                    },
                    "replaces": {
                        "type": "boolean",
                        "description": "It follows another channel now."
                    },
                    "name_differs": {
                        "type": "boolean"
                    },
                    "will_rename": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "ambiguous",
                    "item_id",
                    "item_name",
                    "name_differs",
                    "provider",
                    "provider_name",
                    "replaces",
                    "source_order",
                    "stream",
                    "stream_name",
                    "why",
                    "will_rename"
                ]
            },
            "ProviderLinkMatchQueryRequest": {
                "type": "object",
                "description": "Which streams a bulk action is for: the rows ticked (`stream_ids`), or every stream the stream list's `filter` selects, less those unticked (`exclude`).",
                "properties": {
                    "stream_ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "filter": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "exclude": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "provider": {
                        "type": "integer",
                        "nullable": true
                    }
                }
            },
            "ProviderLinkMatchWhyEnum": {
                "enum": [
                    "source",
                    "name"
                ],
                "type": "string",
                "description": "* `source` - source\n* `name` - name"
            },
            "ProviderLinkMatches": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer",
                        "description": "Streams with a proposal."
                    },
                    "by_source": {
                        "type": "integer"
                    },
                    "ambiguous": {
                        "type": "integer",
                        "description": "Streams whose sources play more than one channel."
                    },
                    "by_name": {
                        "type": "integer"
                    },
                    "pairs_total": {
                        "type": "integer"
                    },
                    "name_differs": {
                        "type": "integer"
                    },
                    "will_rename": {
                        "type": "integer"
                    },
                    "capped": {
                        "type": "boolean",
                        "description": "More pairs than are listed."
                    },
                    "pairs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderLinkMatch"
                        }
                    }
                },
                "required": [
                    "ambiguous",
                    "by_name",
                    "by_source",
                    "capped",
                    "count",
                    "name_differs",
                    "pairs",
                    "pairs_total",
                    "will_rename"
                ]
            },
            "ProviderLinkPairRequest": {
                "type": "object",
                "properties": {
                    "stream": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "provider": {
                        "type": "integer"
                    },
                    "item_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    }
                },
                "required": [
                    "item_id",
                    "provider",
                    "stream"
                ]
            },
            "ProviderLinkSelectionRequest": {
                "type": "object",
                "description": "Which streams a bulk action is for: the rows ticked (`stream_ids`), or every stream the stream list's `filter` selects, less those unticked (`exclude`).",
                "properties": {
                    "stream_ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "filter": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "exclude": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    }
                }
            },
            "ProviderLinkSettingsChanged": {
                "type": "object",
                "properties": {
                    "changed": {
                        "type": "integer"
                    },
                    "renamed": {
                        "type": "integer",
                        "description": "Streams renamed to their channel."
                    },
                    "renames": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderRename"
                        },
                        "description": "The first 100 of them."
                    }
                },
                "required": [
                    "changed",
                    "renamed",
                    "renames"
                ]
            },
            "ProviderLinkSuggestQueryRequest": {
                "type": "object",
                "description": "A stream not saved yet, as its form has it: its name and sources.",
                "properties": {
                    "name": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "maxLength": 1000
                        },
                        "maxItems": 20
                    }
                }
            },
            "ProviderLinkSuggestion": {
                "type": "object",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "provider_name": {
                        "type": "string"
                    },
                    "item_id": {
                        "type": "string",
                        "description": "The channel's id at the provider."
                    },
                    "item_name": {
                        "type": "string"
                    },
                    "why": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderLinkSuggestionWhyEnum"
                            }
                        ],
                        "description": "`source`: one of the stream's sources plays it; `name`: same name; `similar`: a name that contains it.\n\n* `source` - source\n* `name` - name\n* `similar` - similar"
                    },
                    "source_order": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Which source plays it (0: the main one)."
                    },
                    "ambiguous": {
                        "type": "boolean",
                        "description": "The sources play more than one channel: pick one."
                    }
                },
                "required": [
                    "ambiguous",
                    "item_id",
                    "item_name",
                    "provider",
                    "provider_name",
                    "source_order",
                    "why"
                ]
            },
            "ProviderLinkSuggestionWhyEnum": {
                "enum": [
                    "source",
                    "name",
                    "similar"
                ],
                "type": "string",
                "description": "* `source` - source\n* `name` - name\n* `similar` - similar"
            },
            "ProviderLinkSuggestions": {
                "type": "object",
                "properties": {
                    "suggestions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderLinkSuggestion"
                        }
                    }
                },
                "required": [
                    "suggestions"
                ]
            },
            "ProviderLinkSwitchesRequest": {
                "type": "object",
                "description": "Which streams a bulk action is for: the rows ticked (`stream_ids`), or every stream the stream list's `filter` selects, less those unticked (`exclude`).",
                "properties": {
                    "stream_ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "filter": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "exclude": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "sync_name": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "sync_logo": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "sync_epg_id": {
                        "type": "boolean",
                        "nullable": true
                    }
                }
            },
            "ProviderLinksApplied": {
                "type": "object",
                "properties": {
                    "linked": {
                        "type": "integer"
                    },
                    "skipped": {
                        "type": "integer"
                    },
                    "renamed": {
                        "type": "integer",
                        "description": "Streams renamed to their channel."
                    },
                    "renames": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderRename"
                        },
                        "description": "The first 100 of them."
                    }
                },
                "required": [
                    "linked",
                    "renamed",
                    "renames",
                    "skipped"
                ]
            },
            "ProviderLinksApplyRequest": {
                "type": "object",
                "properties": {
                    "links": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderLinkPairRequest"
                        }
                    },
                    "sync_name": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "sync_logo": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "sync_epg_id": {
                        "type": "boolean",
                        "nullable": true
                    }
                },
                "required": [
                    "links"
                ]
            },
            "ProviderLinksRemoved": {
                "type": "object",
                "properties": {
                    "removed": {
                        "type": "integer"
                    }
                },
                "required": [
                    "removed"
                ]
            },
            "ProviderNamedRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "ProviderPickerItem": {
                "type": "object",
                "description": "An item in the stream form's picker (no address: the form links,\nit does not play).",
                "properties": {
                    "item_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "category": {
                        "type": "string",
                        "readOnly": true
                    },
                    "icon": {
                        "type": "string",
                        "readOnly": true
                    },
                    "epg_channel_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "gone_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "linked_stream": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderNamedRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    }
                },
                "required": [
                    "category",
                    "epg_channel_id",
                    "gone_at",
                    "icon",
                    "item_id",
                    "linked_stream",
                    "name"
                ]
            },
            "ProviderRename": {
                "type": "object",
                "properties": {
                    "stream": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "from": {
                        "type": "string",
                        "description": "Its name before."
                    },
                    "to": {
                        "type": "string",
                        "description": "Its name now."
                    }
                },
                "required": [
                    "from",
                    "stream",
                    "to"
                ]
            },
            "ProviderRequest": {
                "type": "object",
                "description": "One provider, with what its form edits. `password` is write-only:\nleft empty on an edit, the saved one is kept.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                    },
                    "kind": {
                        "$ref": "#/components/schemas/ProviderKindEnum"
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Enabled",
                        "description": "Off: the provider is neither checked nor synced."
                    },
                    "sync_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SyncEveryMinutesEnum"
                            }
                        ],
                        "title": "Sync",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "use_live": {
                        "type": "boolean",
                        "title": "Live channels",
                        "description": "Its live channels are offered for streams to follow. Off: a provider for its films or TV shows only."
                    },
                    "import_movies": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new films are added to Films."
                    },
                    "import_series": {
                        "type": "boolean",
                        "description": "After each sync, the provider's new shows and episodes are added to TV shows."
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    },
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "maxLength": 255
                    },
                    "extra_hosts": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                        },
                        "maxItems": 20
                    },
                    "link_format": {
                        "$ref": "#/components/schemas/LinkFormatEnum"
                    },
                    "sync_names": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its name whenever the provider's differs."
                    },
                    "sync_logos": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its logo."
                    },
                    "sync_epg_ids": {
                        "type": "boolean",
                        "description": "Streams that follow a channel take its guide id, when the panel's guide has it."
                    },
                    "keep_history": {
                        "type": "boolean",
                        "description": "Keep a list of past syncs (the last 50). Off saves space: only the last result is kept."
                    },
                    "vod_categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodCategoriesEnum"
                            }
                        ],
                        "description": "Where imported titles are filed: under the provider's own categories, under their TMDB genres, or as your mapping says.\n\n* `playlist` - The provider's categories\n* `tmdb` - TMDB genres\n* `custom` - My own mapping"
                    },
                    "vod_category_map": {},
                    "vod_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "vod_delivery": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/VodDeliveryEnum"
                            }
                        ],
                        "description": "Straight from the provider: the player is sent to the provider, which costs you no bandwidth but shows the player its address. Through a streaming server: a server passes the film through, hiding the provider, and every byte crosses it — always the one you choose, or any healthy one the panel picks (load balanced).\n\n* `redirect` - Straight from the provider\n* `proxy` - Through one streaming server\n* `balanced` - Through any streaming server (load balanced)"
                    },
                    "vod_proxy_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "vod_tmdb": {
                        "type": "boolean",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "spare": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "name",
                    "url"
                ]
            },
            "ProviderRow": {
                "type": "object",
                "description": "One row of the Providers page.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderKindEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "address": {
                        "type": "string",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Enabled",
                        "description": "Off: the provider is neither checked nor synced."
                    },
                    "status": {
                        "type": "string",
                        "readOnly": true
                    },
                    "status_detail": {
                        "type": "string",
                        "readOnly": true
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "connections": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderConnections"
                            }
                        ],
                        "readOnly": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "expires_known": {
                        "type": "boolean",
                        "description": "Whether `expires_at` is what the provider said (null: never\nexpires) rather than nothing known: it refused the login, could not\nbe reached, or is an M3U, which says nothing about an expiry.",
                        "readOnly": true
                    },
                    "is_trial": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "account_created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "counts": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderCounts"
                            }
                        ],
                        "readOnly": true
                    },
                    "sync_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SyncEveryMinutesEnum"
                            }
                        ],
                        "readOnly": true,
                        "title": "Sync"
                    },
                    "last_sync_started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_ok": {
                        "type": "boolean",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_sync_summary": {
                        "readOnly": true
                    },
                    "next_sync_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "syncing": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "linked_streams": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    },
                    "gone_links": {
                        "type": "integer",
                        "readOnly": true,
                        "default": 0
                    },
                    "use_live": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Live channels",
                        "description": "Its live channels are offered for streams to follow. Off: a provider for its films or TV shows only."
                    },
                    "import_movies": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "After each sync, the provider's new films are added to Films."
                    },
                    "import_series": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "After each sync, the provider's new shows and episodes are added to TV shows."
                    }
                },
                "required": [
                    "account_created_at",
                    "address",
                    "checked_at",
                    "connections",
                    "counts",
                    "expires_at",
                    "expires_known",
                    "gone_links",
                    "id",
                    "import_movies",
                    "import_series",
                    "is_enabled",
                    "is_trial",
                    "kind",
                    "last_sync_at",
                    "last_sync_ok",
                    "last_sync_started_at",
                    "last_sync_summary",
                    "linked_streams",
                    "name",
                    "next_sync_at",
                    "status",
                    "status_detail",
                    "sync_every_minutes",
                    "syncing",
                    "use_live",
                    "username"
                ]
            },
            "ProviderSyncStarted": {
                "type": "object",
                "properties": {
                    "syncing": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "syncing"
                ]
            },
            "ProviderTestConnections": {
                "type": "object",
                "properties": {
                    "active": {
                        "type": "integer",
                        "nullable": true
                    },
                    "max": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "active",
                    "max"
                ]
            },
            "ProviderTestRequest": {
                "type": "object",
                "description": "A login to try without saving it. `id`: the provider being edited,\nwhose saved password is used when none is sent.",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderKindEnum"
                            }
                        ],
                        "default": "xtream"
                    },
                    "url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000
                    },
                    "username": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    },
                    "password": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    }
                },
                "required": [
                    "url"
                ]
            },
            "ProviderTestResult": {
                "type": "object",
                "properties": {
                    "status": {
                        "$ref": "#/components/schemas/ProviderTestResultStatusEnum"
                    },
                    "status_detail": {
                        "type": "string"
                    },
                    "connections": {
                        "$ref": "#/components/schemas/ProviderTestConnections"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "expires_known": {
                        "type": "boolean",
                        "description": "Whether `expires_at` is what the provider said (null: never ends)."
                    },
                    "is_trial": {
                        "type": "boolean"
                    },
                    "counts": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderCounts"
                            }
                        ],
                        "nullable": true,
                        "description": "How many channels, movies and TV shows it lists."
                    }
                },
                "required": [
                    "connections",
                    "counts",
                    "expires_at",
                    "expires_known",
                    "is_trial",
                    "status",
                    "status_detail"
                ]
            },
            "ProviderTestResultStatusEnum": {
                "enum": [
                    "unknown",
                    "ok",
                    "wrong_login",
                    "expired",
                    "disabled",
                    "unreachable",
                    "off"
                ],
                "type": "string",
                "description": "* `unknown` - Not checked yet\n* `ok` - OK\n* `wrong_login` - Wrong login\n* `expired` - Expired\n* `disabled` - Disabled by provider\n* `unreachable` - Unreachable\n* `off` - Off"
            },
            "ProviderVodCategories": {
                "type": "object",
                "properties": {
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProviderVodCategory"
                        }
                    },
                    "genres": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "categories",
                    "genres"
                ]
            },
            "ProviderVodCategory": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "count": {
                        "type": "integer"
                    }
                },
                "required": [
                    "count",
                    "name"
                ]
            },
            "ProviderVodImport": {
                "type": "object",
                "description": "One import of a provider's movies and TV shows.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "status": {
                        "type": "string",
                        "description": "pending, running, completed, failed or cancelled."
                    },
                    "phase": {
                        "type": "string"
                    },
                    "done": {
                        "type": "integer"
                    },
                    "total": {
                        "type": "integer"
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        }
                    },
                    "message": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "trigger": {
                        "$ref": "#/components/schemas/ProviderVodImportTriggerEnum"
                    },
                    "errors": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        },
                        "description": "The first errors, as `{name, error}`."
                    }
                },
                "required": [
                    "counts",
                    "created_at",
                    "done",
                    "errors",
                    "finished_at",
                    "id",
                    "message",
                    "phase",
                    "started_at",
                    "status",
                    "total",
                    "trigger",
                    "updated_at"
                ]
            },
            "ProviderVodImportStarted": {
                "type": "object",
                "properties": {
                    "syncing": {
                        "type": "boolean",
                        "description": "Nothing was waiting: a sync looks for what is new first."
                    },
                    "import": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderVodImport"
                            }
                        ],
                        "nullable": true,
                        "description": "The import started."
                    }
                },
                "required": [
                    "import",
                    "syncing"
                ]
            },
            "ProviderVodImportTriggerEnum": {
                "enum": [
                    "schedule",
                    "manual"
                ],
                "type": "string",
                "description": "* `schedule` - On schedule\n* `manual` - Sync now"
            },
            "ProviderVodOverview": {
                "type": "object",
                "properties": {
                    "waiting": {
                        "type": "integer",
                        "description": "Movies and episodes waiting to be imported."
                    },
                    "imported": {
                        "type": "integer"
                    },
                    "skipped": {
                        "type": "integer"
                    },
                    "failed": {
                        "type": "integer"
                    },
                    "last": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProviderLastImport"
                            }
                        ],
                        "nullable": true,
                        "description": "The last import, if any."
                    }
                },
                "required": [
                    "failed",
                    "imported",
                    "last",
                    "skipped",
                    "waiting"
                ]
            },
            "ProvidersEnum": {
                "enum": [
                    "replace",
                    "merge",
                    "keep"
                ],
                "type": "string",
                "description": "* `replace` - replace\n* `merge` - merge\n* `keep` - keep"
            },
            "ProxyHeaderEnum": {
                "enum": [
                    "x-forwarded-for",
                    "x-real-ip"
                ],
                "type": "string",
                "description": "* `x-forwarded-for` - X-Forwarded-For\n* `x-real-ip` - X-Real-IP"
            },
            "ProxySourceDeliveryEnum": {
                "enum": [
                    "proxy",
                    "redirect"
                ],
                "type": "string",
                "description": "* `proxy` - proxy\n* `redirect` - redirect"
            },
            "ProxySourceRequest": {
                "type": "object",
                "description": "Attach a source we serve without storing it.",
                "properties": {
                    "delivery": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProxySourceDeliveryEnum"
                            }
                        ],
                        "default": "proxy",
                        "description": "\"proxy\": a node of yours fetches the source and passes it through, hiding the origin and paying the bandwidth. \"redirect\": the viewer is sent to the source and fetches it themselves — no bandwidth cost, but the URL is visible to them and playback is beyond your reach.\n\n* `proxy` - proxy\n* `redirect` - redirect"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Node that will carry a proxied title, and probe the source for either."
                    },
                    "url": {
                        "type": "string",
                        "description": "Direct HTTP(S) source. Never sent to a proxied viewer.",
                        "maxLength": 2000
                    },
                    "s3_key": {
                        "type": "string",
                        "maxLength": 1024
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Bucket for `s3_key`; the VOD bucket when absent."
                    }
                },
                "required": [
                    "server"
                ]
            },
            "ProxySourceResult": {
                "type": "object",
                "properties": {
                    "media": {
                        "$ref": "#/components/schemas/MediaFile"
                    },
                    "replaced": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "The file it replaced, if any."
                    },
                    "warning": {
                        "type": "string",
                        "nullable": true,
                        "description": "Said when the source cannot be seeked: most players will not open it by redirect."
                    }
                },
                "required": [
                    "media",
                    "replaced",
                    "warning"
                ]
            },
            "QueuedBackgroundTask": {
                "type": "object",
                "description": "A background task, as the Background tasks list shows it.",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string",
                        "description": "The kind of task, e.g. `bulk_edit`, `bulk_delete`, `import`."
                    },
                    "kind_label": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "subtitle": {
                        "type": "string"
                    },
                    "state": {
                        "type": "string",
                        "description": "`queued`, `running`, `waiting`, `stalled`, `completed`, `failed` or `cancelled`."
                    },
                    "state_label": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "description": "The task's own status, before it is grouped into `state`."
                    },
                    "status_label": {
                        "type": "string"
                    },
                    "progress": {
                        "$ref": "#/components/schemas/_TaskProgressDoc"
                    },
                    "message": {
                        "type": "string"
                    },
                    "details": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "errors": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "link": {
                        "type": "object",
                        "additionalProperties": {},
                        "nullable": true,
                        "description": "The dashboard page about it: `{path, query, label}`, or null."
                    },
                    "actions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "What the caller may do with it now: `cancel`, `resume`, `retry`."
                    },
                    "created_by_username": {
                        "type": "string",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "actions",
                    "created_at",
                    "created_by_username",
                    "details",
                    "errors",
                    "finished_at",
                    "id",
                    "kind",
                    "kind_label",
                    "link",
                    "message",
                    "progress",
                    "started_at",
                    "state",
                    "state_label",
                    "status",
                    "status_label",
                    "subtitle",
                    "title",
                    "updated_at"
                ]
            },
            "RangeEnum": {
                "enum": [
                    "1h",
                    "6h",
                    "24h",
                    "7d",
                    "30d"
                ],
                "type": "string",
                "description": "* `1h` - 1h\n* `6h` - 6h\n* `24h` - 24h\n* `7d` - 7d\n* `30d` - 30d"
            },
            "ReasonEnum": {
                "enum": [
                    "source",
                    "guide"
                ],
                "type": "string",
                "description": "* `source` - source\n* `guide` - guide"
            },
            "RefusedFieldEnum": {
                "enum": [
                    "package",
                    "credits"
                ],
                "type": "string",
                "description": "* `package` - package\n* `credits` - credits"
            },
            "RemoveUserFromGroupResponseDoc": {
                "type": "object",
                "properties": {
                    "message": {
                        "type": "string"
                    },
                    "user_id": {
                        "type": "string"
                    },
                    "group_id": {
                        "type": "integer"
                    },
                    "group_name": {
                        "type": "string"
                    }
                },
                "required": [
                    "group_id",
                    "group_name",
                    "message",
                    "user_id"
                ]
            },
            "RepeatEnum": {
                "enum": [
                    "none",
                    "2h",
                    "daily",
                    "weekly"
                ],
                "type": "string",
                "description": "* `none` - Does not repeat\n* `2h` - Every 2 hours\n* `daily` - Every day\n* `weekly` - Every week"
            },
            "ReplaceEnum": {
                "enum": [
                    "old",
                    "primary"
                ],
                "type": "string",
                "description": "* `old` - old\n* `primary` - primary"
            },
            "ReplicaServerRequest": {
                "type": "object",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The server to copy the file to."
                    }
                },
                "required": [
                    "server"
                ]
            },
            "ResellerDomain": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "status": {
                        "$ref": "#/components/schemas/ResellerDomainStatusEnum"
                    },
                    "status_text": {
                        "type": "string"
                    },
                    "detail": {
                        "type": "string",
                        "description": "What the last check found."
                    },
                    "serving": {
                        "type": "string",
                        "description": "The name links use now; empty until this one works."
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "next_check_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "changed_by": {
                        "type": "string",
                        "nullable": true
                    },
                    "changed_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "changed_at",
                    "changed_by",
                    "checked_at",
                    "detail",
                    "name",
                    "next_check_at",
                    "serving",
                    "status",
                    "status_text"
                ]
            },
            "ResellerDomainAccount": {
                "type": "object",
                "properties": {
                    "account": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string"
                        },
                        "description": "`{id, username}`."
                    },
                    "domain": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ResellerDomain"
                            }
                        ],
                        "nullable": true,
                        "description": "Null when no domain is set."
                    },
                    "uses": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ResellerDomainUses"
                            }
                        ],
                        "description": "Where this reseller's lines' links point now."
                    },
                    "fallback": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ResellerDomainUses"
                            }
                        ],
                        "description": "Where they would point without a domain of their own."
                    },
                    "dns": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ResellerDomainDns"
                            }
                        ],
                        "description": "The DNS record to make."
                    }
                },
                "required": [
                    "account",
                    "dns",
                    "domain",
                    "fallback",
                    "uses"
                ]
            },
            "ResellerDomainDns": {
                "type": "object",
                "properties": {
                    "cname": {
                        "type": "string",
                        "description": "The panel's own name: point a subdomain at it (CNAME)."
                    },
                    "ipv4": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "For a domain itself: A records."
                    },
                    "ipv6": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "For a domain itself: AAAA records."
                    },
                    "port": {
                        "type": "integer",
                        "description": "The port links use."
                    },
                    "proxy_managed": {
                        "type": "boolean",
                        "description": "Whether the panel gets the certificate itself."
                    }
                },
                "required": [
                    "cname",
                    "ipv4",
                    "ipv6",
                    "port",
                    "proxy_managed"
                ]
            },
            "ResellerDomainNameRequest": {
                "type": "object",
                "description": "A domain or subdomain for links; a pasted link is read as its name.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "description": "A domain or subdomain, like tv.example.com.",
                        "maxLength": 300
                    }
                },
                "required": [
                    "name"
                ]
            },
            "ResellerDomainRow": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "username": {
                        "type": "string"
                    },
                    "parent": {
                        "type": "string",
                        "nullable": true,
                        "description": "The reseller above, if any."
                    },
                    "domain": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ResellerDomain"
                            }
                        ],
                        "nullable": true
                    },
                    "uses": {
                        "$ref": "#/components/schemas/ResellerDomainUses"
                    }
                },
                "required": [
                    "domain",
                    "id",
                    "parent",
                    "username",
                    "uses"
                ]
            },
            "ResellerDomainStatusEnum": {
                "enum": [
                    "pending",
                    "certificate",
                    "active",
                    "trouble"
                ],
                "type": "string",
                "description": "* `pending` - Waiting for DNS\n* `certificate` - Getting a certificate\n* `active` - Active\n* `trouble` - Not answering"
            },
            "ResellerDomainUses": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The domain links use; empty for the panel's own address."
                    },
                    "origin": {
                        "type": "string",
                        "description": "The start of every link, like https://tv.example.com."
                    },
                    "from": {
                        "type": "string",
                        "nullable": true,
                        "description": "The account above whose domain is used, when it is not their own."
                    }
                },
                "required": [
                    "from",
                    "name",
                    "origin"
                ]
            },
            "RootEnum": {
                "enum": [
                    "incoming",
                    "media"
                ],
                "type": "string",
                "description": "* `incoming` - Incoming folder\n* `media` - Media folder"
            },
            "RoutingModeEnum": {
                "enum": [
                    "auto",
                    "pinned"
                ],
                "type": "string",
                "description": "* `auto` - Auto load-balance (excludes panel)\n* `pinned` - Pinned (ordered failover)"
            },
            "RuleEnum": {
                "enum": [
                    "turns",
                    "least_busy",
                    "same_viewer",
                    "random"
                ],
                "type": "string",
                "description": "* `turns` - turns\n* `least_busy` - least_busy\n* `same_viewer` - same_viewer\n* `random` - random"
            },
            "Scan": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "trigger": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScanTriggerEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScanStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "phase": {
                        "type": "string",
                        "readOnly": true
                    },
                    "done": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "total": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "counts": {
                        "readOnly": true
                    },
                    "message": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    }
                },
                "required": [
                    "counts",
                    "created_at",
                    "done",
                    "finished_at",
                    "id",
                    "message",
                    "phase",
                    "started_at",
                    "status",
                    "total",
                    "trigger"
                ]
            },
            "ScanEveryMinutesEnum": {
                "enum": [
                    15,
                    30,
                    60,
                    180,
                    360,
                    720,
                    1440,
                    0
                ],
                "type": "integer",
                "description": "* `15` - Every 15 minutes\n* `30` - Every 30 minutes\n* `60` - Every hour\n* `180` - Every 3 hours\n* `360` - Every 6 hours\n* `720` - Every 12 hours\n* `1440` - Every day\n* `0` - Only when asked"
            },
            "ScanStatusEnum": {
                "enum": [
                    "pending",
                    "running",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `pending` - Queued\n* `running` - Running\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "ScanTriggerEnum": {
                "enum": [
                    "schedule",
                    "manual",
                    "setup"
                ],
                "type": "string",
                "description": "* `schedule` - On schedule\n* `manual` - Scan now\n* `setup` - First scan"
            },
            "ScopeEnum": {
                "enum": [
                    "everything",
                    "no_logs",
                    "custom"
                ],
                "type": "string",
                "description": "* `everything` - Everything\n* `no_logs` - Everything except history and logs\n* `custom` - Only what I choose"
            },
            "Season": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "title": "TV Show"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Season Number",
                        "description": "0 for specials."
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "label": {
                        "type": "string",
                        "readOnly": true
                    },
                    "plot": {
                        "type": "string",
                        "title": "Overview"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "episode_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "episode_count",
                    "id",
                    "label",
                    "number",
                    "series",
                    "updated_at"
                ]
            },
            "SeasonRequest": {
                "type": "object",
                "properties": {
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "title": "TV Show"
                    },
                    "number": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Season Number",
                        "description": "0 for specials."
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "plot": {
                        "type": "string",
                        "title": "Overview"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    }
                },
                "required": [
                    "number",
                    "series"
                ]
            },
            "SectionsEnum": {
                "enum": [
                    "live",
                    "movie",
                    "series",
                    "users",
                    "updaters"
                ],
                "type": "string",
                "description": "* `live` - live\n* `movie` - movie\n* `series` - series\n* `users` - users\n* `updaters` - updaters"
            },
            "SecuritySettings": {
                "type": "object",
                "description": "The security rules (Settings → Security), the same for every line and server. `diagnostics` is read-only.",
                "properties": {
                    "rule_datacenter": {
                        "type": "boolean",
                        "title": "Rule: datacenter IP",
                        "description": "Treat a viewer whose ASN belongs to a hosting provider as a restreamer — a real customer watches from home, not from a rented server. IPs recognised as consumer VPN exits are excluded, so a customer using NordVPN or Surfshark is not caught by this rule."
                    },
                    "rule_pull_tool_ua": {
                        "type": "boolean",
                        "title": "Rule: pull-tool User-Agent",
                        "description": "Treat ffmpeg, GStreamer, curl, streamlink and similar tools as restreamers rather than players. Cheap and precise, but easy to fake: a restreamer only has to call itself a player."
                    },
                    "rule_many_sessions": {
                        "type": "boolean",
                        "title": "Rule: many sessions from one IP",
                        "description": "Treat a line running several simultaneous sessions from a single IP as a restreamer, unless the line is flagged as an authorised restreamer. This is the fan-out signal and the hardest to fake — the connections are counted on our side."
                    },
                    "many_sessions_threshold": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Sessions from one IP before it counts",
                        "description": "How many simultaneous sessions from the same IP trip the rule above. A household with several TVs is normal; keep this above the largest family you sell to."
                    },
                    "rule_long_session": {
                        "type": "boolean",
                        "title": "Rule: session running too long",
                        "description": "Treat a session that never stops as a restreamer. A person watches for hours and then stops; a relay holds the channel open indefinitely. Cannot be spoofed — it is measured, not declared."
                    },
                    "long_session_hours": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Hours before a session counts as too long",
                        "description": "Default 36 (a day and a half). Set it above anything a real viewer could plausibly do, including a TV left on overnight."
                    },
                    "block_restreamers": {
                        "type": "boolean",
                        "title": "Refuse detected restreamers",
                        "description": "When on, a connection the rules call a restreamer is refused (403) unless its line is flagged as an authorised restreamer. On by default, so a new panel is protected from the first stream rather than after someone remembers to arm it. Watch the Live Connections monitor early on and switch off any rule that catches real customers, because a viewer refused this way is not told why."
                    },
                    "auto_block": {
                        "type": "boolean",
                        "title": "Block attackers automatically",
                        "description": "Blocks an address for a while when it guesses passwords or floods the panel: sign-in, playlists and streams are all refused there, on the panel and every streaming server. Your servers, Cloudflare, and addresses where two or more of your customers are watching are never blocked; failed sign-ins never block an address where an admin signed in during the last 30 days. Locked out? On the panel's server run \"docker compose exec web uv run python manage.py unblock <address>\" in /opt/iptv-panel."
                    },
                    "signin_guard": {
                        "type": "boolean",
                        "title": "Failed sign-ins",
                        "description": "Too many failed sign-ins to this panel (the dashboard or the admin) from one address."
                    },
                    "signin_failures": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 3,
                        "title": "Failed sign-ins before a block",
                        "description": "From one address, within the time below. Past it, sign-in from there is refused before any password is checked."
                    },
                    "signin_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back failed sign-ins are counted."
                    },
                    "guess_guard": {
                        "type": "boolean",
                        "title": "Wrong passwords in customer links",
                        "description": "Too many different wrong usernames and passwords from one address in playlist links, player logins, channels, films, catch-up and the TV guide. A player that keeps retrying the same old password counts once."
                    },
                    "guess_limit": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 5,
                        "title": "Different wrong passwords before a block",
                        "description": "From one address, within the time below."
                    },
                    "guess_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back wrong passwords are counted."
                    },
                    "flood_guard": {
                        "type": "boolean",
                        "title": "Request floods",
                        "description": "Far more requests to this panel from one address than anyone sends, without a valid login. Plays, playlists and player apps signed in with a real account never count. Big attacks from many addresses need your hosting provider or Cloudflare."
                    },
                    "flood_per_minute": {
                        "type": "integer",
                        "maximum": 60000,
                        "minimum": 120,
                        "title": "Requests a minute before a block",
                        "description": "Requests a minute from one address that sign in with nothing valid. Plays, playlists and player logins with a real account (one that may watch) never count."
                    },
                    "block_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "Block for (minutes)",
                        "description": "How long the first automatic block of an address lasts."
                    },
                    "block_max_hours": {
                        "type": "integer",
                        "maximum": 720,
                        "minimum": 1,
                        "title": "Longest block (hours)",
                        "description": "An address blocked again within a day of its last block is blocked twice as long each time, up to this."
                    },
                    "never_block": {
                        "type": "string",
                        "title": "Never block these addresses",
                        "description": "One address, block (198.51.100.0/24) or range per line: never counted and never blocked automatically. Blocking one by hand still works."
                    },
                    "trust_own_proxy": {
                        "type": "boolean",
                        "title": "My own proxy sends the visitor's address",
                        "description": "Only for a panel installed without its own web server. Attack protection stays paused until you turn this on, because anyone could pretend to be another address and get it blocked. Turn it on only when the panel's port can be reached from your proxy alone (the installer publishes it on 127.0.0.1 unless told otherwise), and your proxy sets the header chosen below itself. CF-Connecting-IP is believed only from Cloudflare's addresses."
                    },
                    "proxy_header": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProxyHeaderEnum"
                            }
                        ],
                        "title": "Header your proxy names the visitor in",
                        "description": "With X-Forwarded-For, the panel reads the last address in it: the one your proxy added. If another CDN than Cloudflare sits in front of your proxy, make it pass the visitor's address, or its addresses get counted.\n\n* `x-forwarded-for` - X-Forwarded-For\n* `x-real-ip` - X-Real-IP"
                    },
                    "proxy_addresses": {
                        "type": "string",
                        "title": "Your proxy's addresses",
                        "description": "One address or block per line, as the panel sees your proxy. A proxy on the panel's private network needs none, except one that reaches it through Docker's gateway (a proxy on this server, through a published port): list that gateway here."
                    },
                    "hash_budget_per_minute": {
                        "type": "integer",
                        "maximum": 6000,
                        "minimum": 0,
                        "title": "Password checks a minute from failing addresses",
                        "description": "Shared by every address already at half its limit of wrong passwords: checking a password costs CPU, so past this they wait a minute. Other addresses, an admin's own sign-in and passwords the panel already knows are never held back. 0: 60 per CPU core of this server."
                    },
                    "under_attack": {
                        "type": "boolean",
                        "description": "For when the panel is being attacked: every check runs, even one switched off, limits drop to about a quarter and blocks last four times as long. Your team, your servers and private networks are still never blocked, but customers who share an address (a mobile network, an office) may be refused more often. Every page shows a red banner while it is on."
                    },
                    "under_attack_since": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "under_attack_hours": {
                        "type": "integer",
                        "maximum": 168,
                        "minimum": 0,
                        "title": "Turn it off by itself after (hours)",
                        "description": "So a busy day does not leave the panel strict for good. 0 keeps it on until you turn it off."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "diagnostics": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "What each rule can do on this panel, so the page can grey out a switch that would never match: `*_available` (the rule has the data it needs), `vpn_exclusion_available`, and `acts_on` (whether a rule refuses a request or ends a session already playing).",
                        "readOnly": true
                    },
                    "limits": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Each attack protection number's bounds, read off the model, so\nthe page holds no copy of them.",
                        "readOnly": true
                    },
                    "protection": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Whether attack protection runs and what it did lately: `running`, `own_proxy`, `blocked_today`, `in_force`, `gateways`, `hash_budget_auto`, `gateway_requests`, `under_attack` (`{since, ends, running}` while Under attack is on, else null) and `strict` (the limits while it is on).",
                        "readOnly": true
                    }
                },
                "required": [
                    "diagnostics",
                    "limits",
                    "protection",
                    "under_attack_since",
                    "updated_at"
                ]
            },
            "SecuritySettingsRequest": {
                "type": "object",
                "description": "The security rules (Settings → Security), the same for every line and server. `diagnostics` is read-only.",
                "properties": {
                    "rule_datacenter": {
                        "type": "boolean",
                        "title": "Rule: datacenter IP",
                        "description": "Treat a viewer whose ASN belongs to a hosting provider as a restreamer — a real customer watches from home, not from a rented server. IPs recognised as consumer VPN exits are excluded, so a customer using NordVPN or Surfshark is not caught by this rule."
                    },
                    "rule_pull_tool_ua": {
                        "type": "boolean",
                        "title": "Rule: pull-tool User-Agent",
                        "description": "Treat ffmpeg, GStreamer, curl, streamlink and similar tools as restreamers rather than players. Cheap and precise, but easy to fake: a restreamer only has to call itself a player."
                    },
                    "rule_many_sessions": {
                        "type": "boolean",
                        "title": "Rule: many sessions from one IP",
                        "description": "Treat a line running several simultaneous sessions from a single IP as a restreamer, unless the line is flagged as an authorised restreamer. This is the fan-out signal and the hardest to fake — the connections are counted on our side."
                    },
                    "many_sessions_threshold": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Sessions from one IP before it counts",
                        "description": "How many simultaneous sessions from the same IP trip the rule above. A household with several TVs is normal; keep this above the largest family you sell to."
                    },
                    "rule_long_session": {
                        "type": "boolean",
                        "title": "Rule: session running too long",
                        "description": "Treat a session that never stops as a restreamer. A person watches for hours and then stops; a relay holds the channel open indefinitely. Cannot be spoofed — it is measured, not declared."
                    },
                    "long_session_hours": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "title": "Hours before a session counts as too long",
                        "description": "Default 36 (a day and a half). Set it above anything a real viewer could plausibly do, including a TV left on overnight."
                    },
                    "block_restreamers": {
                        "type": "boolean",
                        "title": "Refuse detected restreamers",
                        "description": "When on, a connection the rules call a restreamer is refused (403) unless its line is flagged as an authorised restreamer. On by default, so a new panel is protected from the first stream rather than after someone remembers to arm it. Watch the Live Connections monitor early on and switch off any rule that catches real customers, because a viewer refused this way is not told why."
                    },
                    "auto_block": {
                        "type": "boolean",
                        "title": "Block attackers automatically",
                        "description": "Blocks an address for a while when it guesses passwords or floods the panel: sign-in, playlists and streams are all refused there, on the panel and every streaming server. Your servers, Cloudflare, and addresses where two or more of your customers are watching are never blocked; failed sign-ins never block an address where an admin signed in during the last 30 days. Locked out? On the panel's server run \"docker compose exec web uv run python manage.py unblock <address>\" in /opt/iptv-panel."
                    },
                    "signin_guard": {
                        "type": "boolean",
                        "title": "Failed sign-ins",
                        "description": "Too many failed sign-ins to this panel (the dashboard or the admin) from one address."
                    },
                    "signin_failures": {
                        "type": "integer",
                        "maximum": 100,
                        "minimum": 3,
                        "title": "Failed sign-ins before a block",
                        "description": "From one address, within the time below. Past it, sign-in from there is refused before any password is checked."
                    },
                    "signin_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back failed sign-ins are counted."
                    },
                    "guess_guard": {
                        "type": "boolean",
                        "title": "Wrong passwords in customer links",
                        "description": "Too many different wrong usernames and passwords from one address in playlist links, player logins, channels, films, catch-up and the TV guide. A player that keeps retrying the same old password counts once."
                    },
                    "guess_limit": {
                        "type": "integer",
                        "maximum": 500,
                        "minimum": 5,
                        "title": "Different wrong passwords before a block",
                        "description": "From one address, within the time below."
                    },
                    "guess_window_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1,
                        "title": "Within (minutes)",
                        "description": "How far back wrong passwords are counted."
                    },
                    "flood_guard": {
                        "type": "boolean",
                        "title": "Request floods",
                        "description": "Far more requests to this panel from one address than anyone sends, without a valid login. Plays, playlists and player apps signed in with a real account never count. Big attacks from many addresses need your hosting provider or Cloudflare."
                    },
                    "flood_per_minute": {
                        "type": "integer",
                        "maximum": 60000,
                        "minimum": 120,
                        "title": "Requests a minute before a block",
                        "description": "Requests a minute from one address that sign in with nothing valid. Plays, playlists and player logins with a real account (one that may watch) never count."
                    },
                    "block_minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 5,
                        "title": "Block for (minutes)",
                        "description": "How long the first automatic block of an address lasts."
                    },
                    "block_max_hours": {
                        "type": "integer",
                        "maximum": 720,
                        "minimum": 1,
                        "title": "Longest block (hours)",
                        "description": "An address blocked again within a day of its last block is blocked twice as long each time, up to this."
                    },
                    "never_block": {
                        "type": "string",
                        "title": "Never block these addresses",
                        "description": "One address, block (198.51.100.0/24) or range per line: never counted and never blocked automatically. Blocking one by hand still works."
                    },
                    "trust_own_proxy": {
                        "type": "boolean",
                        "title": "My own proxy sends the visitor's address",
                        "description": "Only for a panel installed without its own web server. Attack protection stays paused until you turn this on, because anyone could pretend to be another address and get it blocked. Turn it on only when the panel's port can be reached from your proxy alone (the installer publishes it on 127.0.0.1 unless told otherwise), and your proxy sets the header chosen below itself. CF-Connecting-IP is believed only from Cloudflare's addresses."
                    },
                    "proxy_header": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ProxyHeaderEnum"
                            }
                        ],
                        "title": "Header your proxy names the visitor in",
                        "description": "With X-Forwarded-For, the panel reads the last address in it: the one your proxy added. If another CDN than Cloudflare sits in front of your proxy, make it pass the visitor's address, or its addresses get counted.\n\n* `x-forwarded-for` - X-Forwarded-For\n* `x-real-ip` - X-Real-IP"
                    },
                    "proxy_addresses": {
                        "type": "string",
                        "title": "Your proxy's addresses",
                        "description": "One address or block per line, as the panel sees your proxy. A proxy on the panel's private network needs none, except one that reaches it through Docker's gateway (a proxy on this server, through a published port): list that gateway here."
                    },
                    "hash_budget_per_minute": {
                        "type": "integer",
                        "maximum": 6000,
                        "minimum": 0,
                        "title": "Password checks a minute from failing addresses",
                        "description": "Shared by every address already at half its limit of wrong passwords: checking a password costs CPU, so past this they wait a minute. Other addresses, an admin's own sign-in and passwords the panel already knows are never held back. 0: 60 per CPU core of this server."
                    },
                    "under_attack": {
                        "type": "boolean",
                        "description": "For when the panel is being attacked: every check runs, even one switched off, limits drop to about a quarter and blocks last four times as long. Your team, your servers and private networks are still never blocked, but customers who share an address (a mobile network, an office) may be refused more often. Every page shows a red banner while it is on."
                    },
                    "under_attack_hours": {
                        "type": "integer",
                        "maximum": 168,
                        "minimum": 0,
                        "title": "Turn it off by itself after (hours)",
                        "description": "So a busy day does not leave the panel strict for good. 0 keeps it on until you turn it off."
                    }
                }
            },
            "SelectedStreamsRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    }
                },
                "required": [
                    "selection"
                ]
            },
            "Series": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "xtream_id": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "The number players know it by, in player links and the player API. Given when it is created, never changed or reused, because players save favourites against it."
                    },
                    "name": {
                        "type": "string",
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this show reports as its own where exactly one is allowed: the M3U playlist group of every episode, and the title-uniqueness rule below. Always among `categories`."
                    },
                    "category_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this show appears under. Browsing and filtering read this; it always contains `category`."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this show belongs to. A line with none of them in common cannot watch any of its episodes."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true,
                        "title": "First Aired"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "title": "Created By",
                        "description": "The show's creators — what TMDB lists for a series instead of a director.",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the show was matched on TMDB. Seasons and episodes are looked up under it, so a sync fills every episode's own metadata without searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive show disappears from playlists and refuses playback of every episode, without anything being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "season_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "episode_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "playable_count": {
                        "type": "integer",
                        "description": "Episodes with a file a viewer could be sent to right now —\nthe same reading as an episode's own `is_playable`, counted in\nthe database by the viewset.",
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "category",
                    "category_name",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "episode_count",
                    "id",
                    "name",
                    "playable_count",
                    "season_count",
                    "updated_at",
                    "xtream_id"
                ]
            },
            "SeriesImport": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "series": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "title": "TV Show"
                    },
                    "series_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SeriesImportKindEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SeriesImportStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "options": {
                        "readOnly": true,
                        "description": "What the operator chose: delivery, node, bucket, seasons to sync, …"
                    },
                    "items": {
                        "readOnly": true,
                        "description": "For a file import, one entry per file: where it is, which season and episode it is, and — once applied — the episode it landed on and what happened."
                    },
                    "total": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "done": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "failed": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "message": {
                        "type": "string",
                        "readOnly": true
                    },
                    "errors": {
                        "readOnly": true,
                        "description": "The first problems met, each with the item it concerns. Bounded."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    }
                },
                "required": [
                    "created_at",
                    "done",
                    "errors",
                    "failed",
                    "finished_at",
                    "id",
                    "items",
                    "kind",
                    "message",
                    "options",
                    "series",
                    "series_name",
                    "started_at",
                    "status",
                    "total",
                    "updated_at"
                ]
            },
            "SeriesImportKindEnum": {
                "enum": [
                    "tmdb",
                    "files"
                ],
                "type": "string",
                "description": "* `tmdb` - Sync from TMDB\n* `files` - Import files"
            },
            "SeriesImportStatusEnum": {
                "enum": [
                    "pending",
                    "running",
                    "completed",
                    "failed",
                    "cancelled"
                ],
                "type": "string",
                "description": "* `pending` - Pending\n* `running` - Running\n* `completed` - Completed\n* `failed` - Failed\n* `cancelled` - Cancelled"
            },
            "SeriesRequest": {
                "type": "object",
                "description": "The `category` / `categories` pair of a catalogue entry.\n\nMovies and series are filed the way streams are: one primary category\n(the playlist group, and the scope of the title-uniqueness rule) that\nis always among the many it is listed under. Mixed into a\n`ModelSerializer` whose model has both fields; `category_type` names\nthe one category type it accepts.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Title",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "title": "Primary Category",
                        "description": "The one category this show reports as its own where exactly one is allowed: the M3U playlist group of every episode, and the title-uniqueness rule below. Always among `categories`."
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category this show appears under. Browsing and filtering read this; it always contains `category`."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this show belongs to. A line with none of them in common cannot watch any of its episodes."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "backdrop_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "trailer_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 1000
                    },
                    "year": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "nullable": true
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true,
                        "title": "First Aired"
                    },
                    "rating": {
                        "type": "string",
                        "format": "decimal",
                        "pattern": "^-?\\d{0,2}(?:\\.\\d{0,1})?$",
                        "nullable": true,
                        "description": "Out of 10."
                    },
                    "genre": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "cast": {
                        "type": "string"
                    },
                    "director": {
                        "type": "string",
                        "title": "Created By",
                        "description": "The show's creators — what TMDB lists for a series instead of a director.",
                        "maxLength": 255
                    },
                    "country": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "tmdb_id": {
                        "type": "string",
                        "description": "Set when the show was matched on TMDB. Seasons and episodes are looked up under it, so a sync fills every episode's own metadata without searching again.",
                        "maxLength": 32
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "An inactive show disappears from playlists and refuses playback of every episode, without anything being deleted."
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    }
                },
                "required": [
                    "category",
                    "name"
                ]
            },
            "Server": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "instance_id": {
                        "type": "string",
                        "readOnly": true,
                        "description": "Stable identifier used in routing hashes. Must not change between restarts.",
                        "pattern": "^[-a-zA-Z0-9_]+$"
                    },
                    "name": {
                        "type": "string",
                        "title": "Display Name",
                        "maxLength": 128
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ServerKindEnum"
                            }
                        ],
                        "readOnly": true,
                        "description": "`panel` for the panel's own server (made by the install), `streaming` for every streaming server.\n\n* `panel` - Panel\n* `streaming` - Streaming node"
                    },
                    "domain": {
                        "type": "string",
                        "title": "Public domain",
                        "description": "The server's public address (a host name). The install sets it on streaming servers.",
                        "maxLength": 255
                    },
                    "address_rule": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/AddressRuleEnum"
                            }
                        ],
                        "title": "How viewers are spread",
                        "description": "Which of the streaming addresses each new viewer is sent to.\n\n* `turns` - Take turns\n* `least_busy` - Least busy\n* `same_viewer` - Same address per viewer\n* `random` - At random"
                    },
                    "caddy_managed": {
                        "type": "boolean",
                        "title": "Auto-configure Caddy",
                        "description": "Whether the panel keeps the server's web address set up by itself."
                    },
                    "internal_url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true,
                        "description": "Where the panel reaches the server. Empty for the panel itself."
                    },
                    "public_url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true,
                        "description": "Client-facing URL used in stream redirects. Empty for the panel row."
                    },
                    "ip": {
                        "type": "string",
                        "nullable": true,
                        "description": "The server's own public IP address.",
                        "readOnly": true
                    },
                    "stream_port": {
                        "type": "integer",
                        "description": "The port viewers reach the streams on. Setting it asks the server to move there."
                    },
                    "desired_stream_port": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Streaming port asked for",
                        "description": "A port change the server has not made yet. Empty when none is under way."
                    },
                    "stream_port_error": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "capabilities": {
                        "readOnly": true,
                        "description": "e.g. [\"x264\", \"nvenc\", \"vaapi\"]"
                    },
                    "max_streams": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Hard ceiling. Rejected by FILL/LEAST_LOADED when reached."
                    },
                    "weight": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Higher = more streams routed here under HASH mode."
                    },
                    "network_capacity_mbps": {
                        "type": "integer",
                        "maximum": 400000,
                        "minimum": 10,
                        "nullable": true,
                        "title": "Network capacity (Mbps)",
                        "description": "The bandwidth this server's port can push, in megabits per second — for example 10000 for a 10 Gbps port. Leave empty to use the speed its network card reports."
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "description": "Operator switch. Set False to drain a server."
                    },
                    "is_healthy": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "serves_streams": {
                        "type": "boolean",
                        "description": "Whether streams are sent to this server. Streaming servers are, once added, until you take one out; the panel's own server only after it is set to stream."
                    },
                    "serves_vod": {
                        "type": "boolean",
                        "description": "Whether this node may hold movie files and serve them. Every streaming node does by default — it is set when a node registers or the panel is promoted. Placement still only sends a file where it fits (`vod_has_room`: the quota, or the free space the node reports), so a node with no room is skipped rather than filled. Turn it off to keep movies off a node entirely."
                    },
                    "vod_max_bytes": {
                        "type": "integer",
                        "maximum": 9223372036854775807,
                        "minimum": 0,
                        "format": "int64",
                        "title": "VOD storage quota (bytes)",
                        "description": "Ceiling on what movies may occupy here. 0 means 'use the disk's real free space instead'. Set this when VOD shares a filesystem with anything else you care about — a full disk stops live streams on this node too, not just movies."
                    },
                    "archive_max_bytes": {
                        "type": "integer",
                        "maximum": 9223372036854775807,
                        "minimum": 0,
                        "format": "int64",
                        "title": "Catch-up storage limit (bytes)",
                        "description": "The most catch-up recordings may use here. Over it, the oldest recordings go first. 0 = no limit beyond the disk, which always keeps a share free for movies."
                    },
                    "last_seen": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "ping_ms": {
                        "type": "integer",
                        "nullable": true,
                        "description": "How stale this node's last heartbeat is, in ms.\n\nSame number the `analytics` action returns, carried on the list row\nso a client rendering a table of nodes needs no per-row follow-up\nrequest. Derived here rather than in the browser because it is a\ndifference against *our* clock: computed client-side, a viewer whose\nmachine is a minute off would see every node reported as stale.\n\nNot a round-trip measurement — a real one would need an echo we\ndon't run. Costs one subtraction per row, no extra query.",
                        "readOnly": true
                    },
                    "current_streams": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "health_data": {
                        "readOnly": true,
                        "description": "Latest cpu_pct, ram_pct, current_streams, and (on VOD nodes) vod_used_bytes / vod_free_bytes / vod_total_bytes. Metrics live here rather than in columns so a node can report something new without a migration."
                    },
                    "version": {
                        "type": "string",
                        "description": "The release this server runs. The panel's row is the panel's\nrelease, a node on the same server included: it is updated with\nthe panel.",
                        "readOnly": true
                    },
                    "update_state": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Whether this server can be updated from the panel, and how its last update went.",
                        "readOnly": true
                    },
                    "token_prefix": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "capabilities",
                    "created_at",
                    "current_streams",
                    "desired_stream_port",
                    "domain",
                    "health_data",
                    "id",
                    "instance_id",
                    "internal_url",
                    "ip",
                    "is_healthy",
                    "kind",
                    "last_seen",
                    "name",
                    "ping_ms",
                    "public_url",
                    "stream_port_error",
                    "token_prefix",
                    "update_state",
                    "updated_at",
                    "version"
                ]
            },
            "ServerActionResult": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string",
                        "description": "What was done, or why not."
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "ServerAnalytics": {
                "type": "object",
                "description": "A server's latest health: status, capacity, load and network throughput.",
                "properties": {
                    "instance_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "kind": {
                        "$ref": "#/components/schemas/ServerAnalyticsKindEnum"
                    },
                    "domain": {
                        "type": "string"
                    },
                    "public_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "internal_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "capabilities": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "description": "Operator switch. False ⇒ drained; LB excludes from new streams."
                    },
                    "is_healthy": {
                        "type": "boolean",
                        "description": "Last heartbeat passed and the node hasn't been demoted."
                    },
                    "is_recent": {
                        "type": "boolean",
                        "description": "True iff `last_seen` is within the last 2 minutes."
                    },
                    "serves_streams": {
                        "type": "boolean"
                    },
                    "last_seen": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "proxied": {
                        "type": "boolean",
                        "description": "Whether the server is reached through its web address (Proxied) or directly (Direct)."
                    },
                    "ping_ms": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Round-trip-ish liveness number derived from `now() - last_seen`. None when the node has never heartbeated."
                    },
                    "current_streams": {
                        "type": "integer"
                    },
                    "current_sessions": {
                        "type": "integer",
                        "description": "Active client sessions (heartbeat-reported)."
                    },
                    "max_streams": {
                        "type": "integer"
                    },
                    "version": {
                        "type": "string",
                        "description": "The release of the streaming engine the server runs."
                    },
                    "load": {
                        "$ref": "#/components/schemas/ServerHealthLoad"
                    }
                },
                "required": [
                    "capabilities",
                    "current_sessions",
                    "current_streams",
                    "domain",
                    "instance_id",
                    "internal_url",
                    "is_enabled",
                    "is_healthy",
                    "is_recent",
                    "kind",
                    "last_seen",
                    "load",
                    "max_streams",
                    "name",
                    "ping_ms",
                    "proxied",
                    "public_url",
                    "serves_streams",
                    "version"
                ]
            },
            "ServerAnalyticsKindEnum": {
                "enum": [
                    "panel",
                    "streaming"
                ],
                "type": "string",
                "description": "* `panel` - panel\n* `streaming` - streaming"
            },
            "ServerBootstrapCreateRequest": {
                "type": "object",
                "description": "A new server to install: its name, address, ports and limits. `instance_id` is made up when left out.",
                "properties": {
                    "instance_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64,
                        "pattern": "^[-a-zA-Z0-9_]+$"
                    },
                    "name": {
                        "type": "string",
                        "maxLength": 128
                    },
                    "domain": {
                        "type": "string",
                        "description": "The new server's public address, such as `node1.example.com`. Leave it empty to set up its web address yourself.",
                        "maxLength": 255
                    },
                    "ttl_minutes": {
                        "type": "integer",
                        "maximum": 10080,
                        "minimum": 1,
                        "default": 60
                    },
                    "stream_port": {
                        "type": "integer",
                        "default": 443,
                        "description": "The port the new server streams on. 443 is recommended: keep it unless something else there uses it."
                    },
                    "replaces": {
                        "type": "string",
                        "format": "uuid",
                        "description": "A server of a panel this one was moved from (Settings → Move from another panel). The node installed there serves that server's films and episodes where they are."
                    },
                    "max_streams": {
                        "type": "integer",
                        "minimum": 1,
                        "default": 5000,
                        "description": "The most streams the server runs at once."
                    }
                }
            },
            "ServerBootstrapResponse": {
                "type": "object",
                "description": "The install command and registration token for a new server. Shown once: make a new one if it is lost.",
                "properties": {
                    "instance_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "registration_token": {
                        "type": "string"
                    },
                    "install_command": {
                        "type": "string"
                    }
                },
                "required": [
                    "expires_at",
                    "install_command",
                    "instance_id",
                    "name",
                    "registration_token"
                ]
            },
            "ServerCredentialsResponse": {
                "type": "object",
                "description": "The credentials a server streams with.",
                "properties": {
                    "instance_id": {
                        "type": "string"
                    },
                    "api_token": {
                        "type": "string",
                        "description": "The server's own credential, sent as `Authorization: Token <token>`."
                    },
                    "webhook_bearer": {
                        "type": "string",
                        "description": "The secret the panel signs its calls to the server with."
                    },
                    "panel_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "heartbeat_interval": {
                        "type": "integer",
                        "description": "Seconds between heartbeats the node should target."
                    }
                },
                "required": [
                    "api_token",
                    "heartbeat_interval",
                    "instance_id",
                    "panel_url",
                    "webhook_bearer"
                ]
            },
            "ServerFile": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "Relative to the incoming folder."
                    },
                    "size_bytes": {
                        "type": "integer"
                    }
                },
                "required": [
                    "path",
                    "size_bytes"
                ]
            },
            "ServerFiles": {
                "type": "object",
                "properties": {
                    "files": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ServerFile"
                        }
                    }
                },
                "required": [
                    "files"
                ]
            },
            "ServerFolder": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "Where this is; empty at the top."
                    },
                    "parent": {
                        "type": "string",
                        "nullable": true,
                        "description": "The folder above; null at the top."
                    },
                    "entries": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ServerFolderEntry"
                        }
                    },
                    "truncated": {
                        "type": "boolean",
                        "description": "The listing was cut short."
                    },
                    "root": {
                        "type": "string",
                        "description": "`incoming` or `media`, when asked for media."
                    }
                },
                "required": [
                    "entries",
                    "parent",
                    "path",
                    "truncated"
                ]
            },
            "ServerFolderEntry": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "What to send back: relative to the incoming folder, or absolute in a media folder."
                    },
                    "name": {
                        "type": "string"
                    },
                    "is_dir": {
                        "type": "boolean"
                    },
                    "size_bytes": {
                        "type": "integer"
                    }
                },
                "required": [
                    "is_dir",
                    "name",
                    "path",
                    "size_bytes"
                ]
            },
            "ServerHealthLoad": {
                "type": "object",
                "description": "The server's load.",
                "properties": {
                    "cpu_pct": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "cpu_cores": {
                        "type": "integer",
                        "nullable": true
                    },
                    "ram_pct": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "ram_total_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "ram_used_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "bytes_in_total": {
                        "type": "integer",
                        "nullable": true
                    },
                    "bytes_out_total": {
                        "type": "integer",
                        "nullable": true
                    },
                    "bytes_in_rate_bps": {
                        "type": "integer",
                        "nullable": true
                    },
                    "bytes_out_rate_bps": {
                        "type": "integer",
                        "nullable": true
                    },
                    "uptime_seconds": {
                        "type": "integer",
                        "nullable": true
                    },
                    "pipeline_failures_last_5m": {
                        "type": "integer",
                        "nullable": true
                    },
                    "sweeper_last_pass_age_secs": {
                        "type": "integer",
                        "nullable": true
                    },
                    "engine_stops_in_flight": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "bytes_in_rate_bps",
                    "bytes_in_total",
                    "bytes_out_rate_bps",
                    "bytes_out_total",
                    "cpu_cores",
                    "cpu_pct",
                    "engine_stops_in_flight",
                    "pipeline_failures_last_5m",
                    "ram_pct",
                    "ram_total_bytes",
                    "ram_used_bytes",
                    "sweeper_last_pass_age_secs",
                    "uptime_seconds"
                ]
            },
            "ServerKindEnum": {
                "enum": [
                    "panel",
                    "streaming"
                ],
                "type": "string",
                "description": "* `panel` - Panel\n* `streaming` - Streaming node"
            },
            "ServerMetricPoint": {
                "type": "object",
                "description": "One bucket of load history.",
                "properties": {
                    "t": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Start of the bucket, UTC."
                    },
                    "cpu_pct": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "ram_pct": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "ram_used_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "ram_total_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "in_bps": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Inbound bits/sec."
                    },
                    "out_bps": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Outbound bits/sec."
                    },
                    "streams": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Peak running streams in the bucket."
                    },
                    "sessions": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Peak viewer sessions in the bucket."
                    }
                },
                "required": [
                    "cpu_pct",
                    "in_bps",
                    "out_bps",
                    "ram_pct",
                    "ram_total_bytes",
                    "ram_used_bytes",
                    "sessions",
                    "streams",
                    "t"
                ]
            },
            "ServerMetrics": {
                "type": "object",
                "description": "Load history of one server or of the fleet, bucketed by range.",
                "properties": {
                    "range": {
                        "$ref": "#/components/schemas/RangeEnum"
                    },
                    "bucket_seconds": {
                        "type": "integer"
                    },
                    "retention_days": {
                        "type": "integer",
                        "description": "How many days of history the panel keeps (Settings → Panel)."
                    },
                    "points": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ServerMetricPoint"
                        }
                    }
                },
                "required": [
                    "bucket_seconds",
                    "points",
                    "range",
                    "retention_days"
                ]
            },
            "ShowImportSourceEnum": {
                "enum": [
                    "node",
                    "s3",
                    "url",
                    "upload"
                ],
                "type": "string",
                "description": "* `node` - node\n* `s3` - s3\n* `url` - url\n* `upload` - upload"
            },
            "SortRuleMatchEnum": {
                "enum": [
                    "starts",
                    "contains",
                    "ends",
                    "pattern"
                ],
                "type": "string",
                "description": "* `starts` - starts\n* `contains` - contains\n* `ends` - ends\n* `pattern` - pattern"
            },
            "Source": {
                "type": "object",
                "description": "One address a stream is read from.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "title": "Source Name",
                        "maxLength": 255
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "title": "Source URL",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "quality": {
                        "type": "string",
                        "nullable": true,
                        "description": "e.g., 720p, 1080p, 4K",
                        "maxLength": 10
                    },
                    "bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648,
                        "nullable": true,
                        "description": "Bitrate in kbps"
                    },
                    "health": {
                        "type": "string",
                        "readOnly": true,
                        "description": "How the servers last found it: `online` while a server plays from it, `down` after one failed to, `unknown` until a server has tried."
                    },
                    "health_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Health Reported At",
                        "description": "When a server last said how it found it."
                    },
                    "probed_video_codec": {
                        "type": "string",
                        "readOnly": true,
                        "description": "e.g. h264, hevc. Empty until a server has read the source."
                    },
                    "probed_audio_codec": {
                        "type": "string",
                        "readOnly": true
                    },
                    "probed_fps": {
                        "type": "number",
                        "format": "double",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Null when the source declares a variable or unknown rate."
                    },
                    "probed_width": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "probed_height": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "probed_audio_tracks": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Number of audio streams — language alternatives."
                    },
                    "probed_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "description": "When a server last read these, as a stream started on it."
                    },
                    "streams_count": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "How many streams read from it."
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "health",
                    "health_at",
                    "id",
                    "name",
                    "probed_at",
                    "probed_audio_codec",
                    "probed_audio_tracks",
                    "probed_fps",
                    "probed_height",
                    "probed_video_codec",
                    "probed_width",
                    "streams_count",
                    "updated_at",
                    "url"
                ]
            },
            "SourceCounters": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "online": {
                        "type": "integer"
                    },
                    "down": {
                        "type": "integer"
                    },
                    "unknown": {
                        "type": "integer"
                    },
                    "inactive": {
                        "type": "integer"
                    },
                    "unused": {
                        "type": "integer",
                        "description": "Sources no stream reads from."
                    }
                },
                "required": [
                    "down",
                    "inactive",
                    "online",
                    "total",
                    "unknown",
                    "unused"
                ]
            },
            "SourceHostMove": {
                "type": "object",
                "properties": {
                    "from_host": {
                        "type": "string"
                    },
                    "to_base": {
                        "type": "string"
                    },
                    "sources": {
                        "type": "integer",
                        "description": "Sources that change."
                    },
                    "streams": {
                        "type": "integer",
                        "description": "Streams using them."
                    },
                    "running_restarted": {
                        "type": "integer",
                        "description": "Running always-on streams that restart on the new address."
                    },
                    "movies": {
                        "type": "integer"
                    },
                    "already_existing": {
                        "type": "integer",
                        "description": "New addresses another source already has."
                    },
                    "examples": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SourceHostMoveRow"
                        }
                    },
                    "updated_sources": {
                        "type": "integer",
                        "description": "Real run only."
                    },
                    "updated_movies": {
                        "type": "integer",
                        "description": "Real run only."
                    },
                    "restarted_streams": {
                        "type": "integer",
                        "description": "Real run only."
                    }
                },
                "required": [
                    "already_existing",
                    "examples",
                    "from_host",
                    "movies",
                    "running_restarted",
                    "sources",
                    "streams",
                    "to_base"
                ]
            },
            "SourceHostMoveRow": {
                "type": "object",
                "properties": {
                    "from": {
                        "type": "string"
                    },
                    "to": {
                        "type": "string"
                    }
                },
                "required": [
                    "from",
                    "to"
                ]
            },
            "SourceHostReplaceRequest": {
                "type": "object",
                "description": "Where the sources move from (`from_host`) and to (`to_base`).",
                "properties": {
                    "from_host": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Hostname the sources point at now, e.g. old-provider.example. Matches http and https and any port; subdomains are not included.",
                        "maxLength": 253
                    },
                    "to_base": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Scheme and host to use instead, e.g. https://new-provider.example. Each source keeps its own path.",
                        "maxLength": 300
                    },
                    "dry_run": {
                        "type": "boolean",
                        "default": true,
                        "description": "Report what would change and write nothing."
                    }
                },
                "required": [
                    "from_host",
                    "to_base"
                ]
            },
            "SourceRequest": {
                "type": "object",
                "description": "One address a stream is read from.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Source Name",
                        "maxLength": 255
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "minLength": 1,
                        "title": "Source URL",
                        "maxLength": 1000
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "quality": {
                        "type": "string",
                        "nullable": true,
                        "description": "e.g., 720p, 1080p, 4K",
                        "maxLength": 10
                    },
                    "bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648,
                        "nullable": true,
                        "description": "Bitrate in kbps"
                    }
                },
                "required": [
                    "name",
                    "url"
                ]
            },
            "SourcesChangeModeEnum": {
                "enum": [
                    "move",
                    "address",
                    "remove",
                    "check"
                ],
                "type": "string",
                "description": "* `move` - move\n* `address` - address\n* `remove` - remove\n* `check` - check"
            },
            "SourcesChangePlaceEnum": {
                "enum": [
                    "replace",
                    "primary",
                    "backup"
                ],
                "type": "string",
                "description": "* `replace` - replace\n* `primary` - primary\n* `backup` - backup"
            },
            "SourcesChangeRequest": {
                "type": "object",
                "description": "How the sources of the selected streams change. `move`: each stream\ngets the same channel on another `provider` (only when exactly one\nmatches), replacing its old source, as its main source or as its last\nbackup (`place`). `address`: part of each address changes (server,\nor the login in it). `remove`: the sources on a provider or line are\ntaken out; a stream is never left without one. `check`: the sources\nare read again.",
                "properties": {
                    "mode": {
                        "$ref": "#/components/schemas/SourcesChangeModeEnum"
                    },
                    "provider": {
                        "type": "integer",
                        "minimum": 1
                    },
                    "place": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SourcesChangePlaceEnum"
                            }
                        ],
                        "default": "replace"
                    },
                    "replace": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ReplaceEnum"
                            }
                        ],
                        "default": "old"
                    },
                    "follow": {
                        "type": "boolean",
                        "default": false
                    },
                    "old_provider": {
                        "type": "integer",
                        "minimum": 1,
                        "nullable": true
                    },
                    "old_host": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "old_user": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "from_host": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "to_base": {
                        "type": "string",
                        "maxLength": 300
                    },
                    "from_user": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "to_user": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "to_password": {
                        "type": "string",
                        "maxLength": 255
                    }
                },
                "required": [
                    "mode"
                ]
            },
            "StaffUserCreate": {
                "type": "object",
                "description": "A new account with dashboard access.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "id",
                    "username"
                ]
            },
            "StaffUserCreateRequest": {
                "type": "object",
                "description": "A new account with dashboard access.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "password_confirm": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "password",
                    "password_confirm",
                    "username"
                ]
            },
            "StaffUserList": {
                "type": "object",
                "description": "An account with dashboard access, as the staff list shows it.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "readOnly": true,
                        "nullable": true,
                        "title": "Email address"
                    },
                    "first_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "last_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "is_active": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "is_staff": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_superuser": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Superuser status",
                        "description": "Designates that this user has all permissions without explicitly assigning them."
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "owner": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "direct_permissions_count": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "last_login": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "direct_permissions_count",
                    "email",
                    "first_name",
                    "groups",
                    "id",
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "last_login",
                    "last_name",
                    "owner",
                    "username"
                ]
            },
            "StartBackupRequest": {
                "type": "object",
                "description": "A backup started by hand.",
                "properties": {
                    "scope": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScopeEnum"
                            }
                        ],
                        "default": "everything"
                    },
                    "components": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ComponentsEnum"
                        }
                    },
                    "destinations": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "compression": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CompressionEnum"
                            }
                        ],
                        "default": 6
                    },
                    "encrypt": {
                        "type": "boolean",
                        "default": false
                    },
                    "passphrase": {
                        "type": "string",
                        "writeOnly": true
                    }
                },
                "required": [
                    "destinations"
                ]
            },
            "StartIngestMethodEnum": {
                "enum": [
                    "url",
                    "s3"
                ],
                "type": "string",
                "description": "* `url` - url\n* `s3` - s3"
            },
            "StartIngestRequest": {
                "type": "object",
                "description": "Kick off an ingest by any of the transfer-based methods.",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Node that will hold the file."
                    },
                    "method": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StartIngestMethodEnum"
                            }
                        ],
                        "default": "url"
                    },
                    "url": {
                        "type": "string",
                        "description": "Direct HTTP(S) source. For object storage the panel presigns first.",
                        "maxLength": 2000
                    },
                    "s3_key": {
                        "type": "string",
                        "description": "Object key, when method is s3.",
                        "maxLength": 1024
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Bucket (Settings → Storage) for method s3; the VOD bucket when absent."
                    }
                },
                "required": [
                    "server"
                ]
            },
            "StorageBrowse": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "The folder listed."
                    },
                    "parent": {
                        "type": "string",
                        "nullable": true,
                        "description": "Its parent folder; null at the top."
                    },
                    "entries": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StorageBrowseEntry"
                        }
                    },
                    "truncated": {
                        "type": "boolean",
                        "description": "More entries follow: ask again with `token`."
                    },
                    "next_token": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "required": [
                    "entries",
                    "next_token",
                    "parent",
                    "path",
                    "truncated"
                ]
            },
            "StorageBrowseEntry": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "is_dir": {
                        "type": "boolean"
                    },
                    "size_bytes": {
                        "type": "integer"
                    },
                    "modified": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "required": [
                    "is_dir",
                    "modified",
                    "name",
                    "path",
                    "size_bytes"
                ]
            },
            "StorageCheckRequest": {
                "type": "object",
                "properties": {
                    "prefix": {
                        "type": "string",
                        "minLength": 1,
                        "description": "A folder of the bucket to test in."
                    }
                }
            },
            "StorageCheckResult": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean"
                    },
                    "detail": {
                        "type": "string",
                        "description": "What the test found, in plain words."
                    }
                },
                "required": [
                    "detail",
                    "ok"
                ]
            },
            "StorageConnection": {
                "type": "object",
                "description": "A bucket. The secret is write-only: `has_secret` says whether one is\nset, and leaving it out of an update keeps the stored one.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "description": "How this bucket is named wherever it can be picked, e.g. \"Movies (Wasabi)\".",
                        "maxLength": 100
                    },
                    "endpoint": {
                        "type": "string",
                        "title": "Endpoint URL",
                        "description": "e.g. https://s3.eu-west-1.amazonaws.com, or your MinIO / Wasabi / R2 / Backblaze endpoint.",
                        "maxLength": 255
                    },
                    "bucket": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "region": {
                        "type": "string",
                        "description": "Part of the request signature. MinIO accepts us-east-1 unless configured otherwise.",
                        "maxLength": 64
                    },
                    "access_key": {
                        "type": "string",
                        "title": "Access key ID",
                        "maxLength": 255
                    },
                    "has_secret": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "used_by": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "last_checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_check_ok": {
                        "type": "boolean",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_check_message": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "access_key",
                    "bucket",
                    "created_at",
                    "endpoint",
                    "has_secret",
                    "id",
                    "last_check_message",
                    "last_check_ok",
                    "last_checked_at",
                    "name",
                    "updated_at",
                    "used_by"
                ]
            },
            "StorageConnectionRequest": {
                "type": "object",
                "description": "A bucket. The secret is write-only: `has_secret` says whether one is\nset, and leaving it out of an update keeps the stored one.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "description": "How this bucket is named wherever it can be picked, e.g. \"Movies (Wasabi)\".",
                        "maxLength": 100
                    },
                    "endpoint": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Endpoint URL",
                        "description": "e.g. https://s3.eu-west-1.amazonaws.com, or your MinIO / Wasabi / R2 / Backblaze endpoint.",
                        "maxLength": 255
                    },
                    "bucket": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                    },
                    "region": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Part of the request signature. MinIO accepts us-east-1 unless configured otherwise.",
                        "maxLength": 64
                    },
                    "access_key": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Access key ID",
                        "maxLength": 255
                    },
                    "secret_key": {
                        "type": "string",
                        "writeOnly": true
                    }
                },
                "required": [
                    "access_key",
                    "bucket",
                    "endpoint",
                    "name"
                ]
            },
            "Stream": {
                "type": "object",
                "description": "A stream: what it plays from (`sources`), where it is listed\n(`categories`, `bouquets`) and how servers play it. A created channel\n(`plan`) plays movies and episodes on a schedule; a delayed stream\n(`delay`) plays a channel later.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "xtream_id": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "The stream's number in players' channel lists. Set when it is created, never changed or reused."
                    },
                    "name": {
                        "type": "string",
                        "title": "Stream Name",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "category_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category it is listed under; always holds `category`, its main one."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this stream belongs to"
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSource"
                        }
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "thumbnail": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 1000
                    },
                    "logo_auto": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "epg_channel_id": {
                        "type": "string",
                        "title": "EPG channel",
                        "description": "The guide channel players show for this stream. Blank: no guide.",
                        "maxLength": 255
                    },
                    "epg_auto": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "epg_channel": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/EpgChannelRef"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "tvg_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "streaming_engine": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamingEngineEnum"
                            }
                        ],
                        "description": "Engine used for video processing\n\n* `gstreamer` - GStreamer\n* `ffmpeg` - FFmpeg"
                    },
                    "engine_config": {
                        "title": "Engine Configuration",
                        "description": "JSON configuration for streaming engine parameters"
                    },
                    "transcoding_profile": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Optional: converts the stream's picture and sound this way."
                    },
                    "transcoding_profile_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "allow_passthrough": {
                        "type": "boolean",
                        "description": "On (the default): a source players can play is sent as it is, and one they cannot is converted. Off: the stream is always converted. A transcoding profile always converts."
                    },
                    "user_agent": {
                        "type": "string",
                        "description": "Sent to the source instead of the server's own. Leave empty unless the provider refuses other players.",
                        "maxLength": 512
                    },
                    "http_proxy": {
                        "type": "string",
                        "title": "Proxy",
                        "description": "Reach the source through this HTTP proxy, e.g. http://10.0.0.5:3128.",
                        "maxLength": 255
                    },
                    "http_headers": {
                        "type": "string",
                        "title": "Extra headers",
                        "description": "One \"Name: value\" per line, e.g. \"Referer: https://example.com\" or \"Cookie: session=abc\"."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "is_stopped": {
                        "type": "boolean",
                        "readOnly": true,
                        "title": "Stopped by operator",
                        "description": "Stopped with Stop: it stays stopped until Start or Restart."
                    },
                    "is_on_demand": {
                        "type": "boolean",
                        "description": "Started when someone watches and stopped once nobody does. Off: it runs all the time."
                    },
                    "is_direct": {
                        "type": "boolean",
                        "title": "Direct Mode",
                        "description": "Send viewers straight to the source instead of playing it through a server. The line and its rules are still checked, but the source address (and any login in it) is shown to the viewer, there is no connection limit, no live connection row and no backup source."
                    },
                    "routing_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RoutingModeEnum"
                            }
                        ],
                        "description": "`auto`: any streaming server with room plays it (never the panel's own); `pinned`: the servers of `pinned_servers` in order, the next taking over when one fails.\n\n* `auto` - Auto load-balance (excludes panel)\n* `pinned` - Pinned (ordered failover)"
                    },
                    "pinned_servers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamPinnedServer"
                        }
                    },
                    "auto_eligible_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "current_server": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "current_source": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CurrentSource"
                            }
                        ],
                        "readOnly": true
                    },
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamStatusEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "online_since": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true,
                        "description": "When the current run started: its uptime counts from here."
                    },
                    "live_stats": {
                        "readOnly": true,
                        "description": "What the server playing it last reported (fps, video_codec, audio_codec…)."
                    },
                    "check_state": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Check",
                        "description": "Whether the channel proved it plays since it was added. Read-only."
                    },
                    "check_detail": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Check result",
                        "description": "Why the check failed, in plain words, or what it waits for."
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "active_sessions_count": {
                        "type": "integer",
                        "readOnly": true,
                        "description": "People watching it now."
                    },
                    "restart_count": {
                        "type": "integer",
                        "readOnly": true,
                        "nullable": true
                    },
                    "stream_config": {
                        "type": "object",
                        "additionalProperties": {},
                        "readOnly": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "provider_link": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamFollowedChannel"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "archive_days": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": 0,
                        "title": "Catch-up days",
                        "description": "Record this channel so viewers can watch what aired in the last this many days (TV archive). 0 = off.\n\nWhat it costs: the channel runs all the time on the server that records it, so it holds one provider connection permanently, and it uses disk at its own bitrate (about 10.8 GB a day per Mb/s). Recordings are the channel as viewers get it, never re-encoded. Turning it off deletes the recordings."
                    },
                    "archive_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Catch-up server",
                        "description": "The server that records this channel and plays its catch-up. The channel runs there, so viewers of the live channel are sent there too: one provider connection, not two. If it goes down, the channel moves to another server and recording waits for it."
                    },
                    "catchup": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamCatchupStatus"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "created_channel": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamCreatedChannel"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "delayed": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamDelayed"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "feeds_delays": {
                        "type": "boolean",
                        "readOnly": true
                    }
                },
                "required": [
                    "active_sessions_count",
                    "catchup",
                    "category_name",
                    "check_detail",
                    "check_state",
                    "checked_at",
                    "created_at",
                    "created_by",
                    "created_by_username",
                    "created_channel",
                    "current_server",
                    "current_source",
                    "delayed",
                    "epg_auto",
                    "epg_channel",
                    "feeds_delays",
                    "id",
                    "is_stopped",
                    "live_stats",
                    "logo_auto",
                    "name",
                    "online_since",
                    "provider_link",
                    "restart_count",
                    "status",
                    "stream_config",
                    "transcoding_profile_name",
                    "tvg_id",
                    "updated_at",
                    "xtream_id"
                ]
            },
            "StreamBulkEditOptions": {
                "type": "object",
                "properties": {
                    "engines": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "routing_modes": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "pipeline_fields": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Changes that restart the streams."
                    },
                    "max_selection": {
                        "type": "integer"
                    },
                    "sync_rate": {
                        "$ref": "#/components/schemas/StreamBulkEditPace"
                    },
                    "epg_channels": {
                        "type": "integer",
                        "description": "Guide channels a name can be matched to."
                    }
                },
                "required": [
                    "engines",
                    "epg_channels",
                    "max_selection",
                    "pipeline_fields",
                    "routing_modes",
                    "sync_rate"
                ]
            },
            "StreamBulkEditPace": {
                "type": "object",
                "properties": {
                    "tick_seconds": {
                        "type": "integer"
                    },
                    "per_tick": {
                        "type": "integer"
                    }
                },
                "required": [
                    "per_tick",
                    "tick_seconds"
                ]
            },
            "StreamBulkEditRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    },
                    "changes": {
                        "$ref": "#/components/schemas/BulkEditChangesRequest"
                    }
                },
                "required": [
                    "changes",
                    "selection"
                ]
            },
            "StreamCatchup": {
                "type": "object",
                "properties": {
                    "status": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamCatchupStatus"
                            }
                        ],
                        "nullable": true
                    },
                    "days": {
                        "type": "integer"
                    },
                    "server": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamServerRef"
                            }
                        ],
                        "nullable": true
                    },
                    "has_guide": {
                        "type": "boolean"
                    },
                    "programmes": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamCatchupProgramme"
                        }
                    }
                },
                "required": [
                    "days",
                    "has_guide",
                    "programmes",
                    "server",
                    "status"
                ]
            },
            "StreamCatchupPreview": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string"
                    },
                    "hls_url": {
                        "type": "string"
                    },
                    "session_id": {
                        "type": "string"
                    },
                    "server": {
                        "type": "string"
                    }
                },
                "required": [
                    "hls_url",
                    "server",
                    "session_id",
                    "url"
                ]
            },
            "StreamCatchupProgramme": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "stop": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "title": {
                        "type": "string"
                    },
                    "recorded": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "recorded",
                    "start",
                    "stop",
                    "title"
                ]
            },
            "StreamCatchupStatus": {
                "type": "object",
                "properties": {
                    "recording": {
                        "type": "boolean"
                    },
                    "paused": {
                        "type": "boolean",
                        "description": "The server paused recording (its disk is full)."
                    },
                    "bytes": {
                        "type": "integer"
                    },
                    "from": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "to": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "recorded_seconds": {
                        "type": "integer"
                    },
                    "gaps": {
                        "type": "integer"
                    },
                    "bytes_per_day": {
                        "type": "integer",
                        "nullable": true,
                        "description": "Known after ten minutes of recording."
                    },
                    "disk_free_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "disk_total_bytes": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "bytes",
                    "bytes_per_day",
                    "disk_free_bytes",
                    "disk_total_bytes",
                    "from",
                    "gaps",
                    "paused",
                    "recorded_seconds",
                    "recording",
                    "to"
                ]
            },
            "StreamCatchupStretchRequest": {
                "type": "object",
                "properties": {
                    "start": {
                        "type": "string",
                        "format": "date-time",
                        "description": "With its time zone."
                    },
                    "minutes": {
                        "type": "integer",
                        "maximum": 1440,
                        "minimum": 1
                    }
                },
                "required": [
                    "minutes",
                    "start"
                ]
            },
            "StreamCounters": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "online": {
                        "type": "integer"
                    },
                    "offline": {
                        "type": "integer"
                    },
                    "starting": {
                        "type": "integer"
                    },
                    "error": {
                        "type": "integer"
                    },
                    "viewers": {
                        "type": "integer",
                        "description": "Connections watching them now."
                    }
                },
                "required": [
                    "error",
                    "offline",
                    "online",
                    "starting",
                    "total",
                    "viewers"
                ]
            },
            "StreamCreatedChannel": {
                "type": "object",
                "description": "Marks a created channel: when its plan changed, and when it ends.",
                "properties": {
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "ends_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "required": [
                    "ends_at",
                    "updated_at"
                ]
            },
            "StreamDelayCost": {
                "type": "object",
                "properties": {
                    "seconds": {
                        "type": "integer"
                    },
                    "bitrate_mbps": {
                        "type": "number",
                        "format": "double"
                    },
                    "measured": {
                        "type": "boolean",
                        "description": "The bitrate was measured (else estimated)."
                    },
                    "disk_bytes": {
                        "type": "integer"
                    },
                    "extra_disk_bytes": {
                        "type": "integer",
                        "description": "What is not recorded there already."
                    },
                    "server": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamServerRef"
                            }
                        ],
                        "nullable": true
                    },
                    "disk_free_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "disk_total_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "usable_bytes": {
                        "type": "integer",
                        "nullable": true
                    },
                    "fits": {
                        "type": "boolean",
                        "nullable": true,
                        "description": "Null while the server has not said."
                    },
                    "tight": {
                        "type": "boolean"
                    },
                    "always_on": {
                        "type": "boolean",
                        "description": "The channel must now run all the time."
                    },
                    "provider_connections": {
                        "type": "integer"
                    },
                    "converts": {
                        "type": "boolean"
                    },
                    "ready_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "required": [
                    "always_on",
                    "bitrate_mbps",
                    "converts",
                    "disk_bytes",
                    "disk_free_bytes",
                    "disk_total_bytes",
                    "extra_disk_bytes",
                    "fits",
                    "measured",
                    "provider_connections",
                    "ready_at",
                    "seconds",
                    "server",
                    "tight",
                    "usable_bytes"
                ]
            },
            "StreamDelaySettings": {
                "type": "object",
                "properties": {
                    "seconds": {
                        "type": "integer"
                    },
                    "own_source": {
                        "type": "boolean",
                        "description": "It records its own source rather than a channel."
                    },
                    "original": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamRef"
                            }
                        ],
                        "nullable": true
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "epg_channel_id": {
                        "type": "string"
                    },
                    "server": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamServerRef"
                            }
                        ],
                        "nullable": true
                    }
                },
                "required": [
                    "epg_channel_id",
                    "original",
                    "own_source",
                    "seconds",
                    "server",
                    "sources"
                ]
            },
            "StreamDelayed": {
                "type": "object",
                "description": "A delayed stream: its delay, what it plays later and its recording.",
                "properties": {
                    "seconds": {
                        "type": "integer"
                    },
                    "original": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamRef"
                            }
                        ],
                        "nullable": true,
                        "description": "Null when it records its own source."
                    },
                    "own_source": {
                        "type": "boolean"
                    },
                    "source_status": {
                        "type": "string",
                        "description": "The status of the channel it records."
                    },
                    "server": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamServerRef"
                            }
                        ],
                        "nullable": true
                    },
                    "recording": {
                        "type": "boolean"
                    },
                    "recorded_from": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "ready_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When the whole delay is recorded."
                    }
                },
                "required": [
                    "original",
                    "own_source",
                    "ready_at",
                    "recorded_from",
                    "recording",
                    "seconds",
                    "server",
                    "source_status"
                ]
            },
            "StreamDeletePlan": {
                "type": "object",
                "properties": {
                    "streams": {
                        "type": "integer"
                    },
                    "sessions": {
                        "type": "integer"
                    },
                    "sources_orphaned": {
                        "type": "integer",
                        "description": "Sources deleted with them."
                    },
                    "sources_kept": {
                        "type": "integer",
                        "description": "Sources other streams still use."
                    },
                    "playing": {
                        "type": "integer",
                        "description": "Streams stopped first."
                    },
                    "sample": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Up to 10 names."
                    }
                },
                "required": [
                    "playing",
                    "sample",
                    "sessions",
                    "sources_kept",
                    "sources_orphaned",
                    "streams"
                ]
            },
            "StreamDeleteRefused": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string"
                    },
                    "delayed_streams": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "delayed_streams",
                    "error"
                ]
            },
            "StreamDuplicateGroup": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "reasons": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keep": {
                        "type": "string",
                        "description": "The id of the stream it keeps."
                    },
                    "members": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "required": [
                    "id",
                    "keep",
                    "members",
                    "reasons"
                ]
            },
            "StreamDuplicateTotals": {
                "type": "object",
                "properties": {
                    "groups": {
                        "type": "integer"
                    },
                    "streams": {
                        "type": "integer"
                    },
                    "removable": {
                        "type": "integer",
                        "description": "Streams merging every group removes."
                    },
                    "by_source": {
                        "type": "integer"
                    },
                    "by_guide": {
                        "type": "integer"
                    }
                },
                "required": [
                    "by_guide",
                    "by_source",
                    "groups",
                    "removable",
                    "streams"
                ]
            },
            "StreamDuplicates": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamDuplicateGroup"
                        }
                    },
                    "totals": {
                        "$ref": "#/components/schemas/StreamDuplicateTotals"
                    }
                },
                "required": [
                    "count",
                    "results",
                    "totals"
                ]
            },
            "StreamDuplicatesMergeActionEnum": {
                "enum": [
                    "merge",
                    "delete"
                ],
                "type": "string",
                "description": "* `merge` - merge\n* `delete` - delete"
            },
            "StreamDuplicatesMergeRequest": {
                "type": "object",
                "properties": {
                    "action": {
                        "$ref": "#/components/schemas/StreamDuplicatesMergeActionEnum"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "all": {
                        "type": "boolean",
                        "default": false
                    },
                    "reason": {
                        "$ref": "#/components/schemas/ReasonEnum"
                    },
                    "search": {
                        "type": "string",
                        "minLength": 1
                    },
                    "exclude": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "keep": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string",
                            "minLength": 1
                        },
                        "description": "Group id → id of the stream to keep."
                    }
                },
                "required": [
                    "action"
                ]
            },
            "StreamDuplicatesMergeTask": {
                "type": "object",
                "description": "A background task, as the Background tasks list shows it.",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string",
                        "description": "The kind of task, e.g. `bulk_edit`, `bulk_delete`, `import`."
                    },
                    "kind_label": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "subtitle": {
                        "type": "string"
                    },
                    "state": {
                        "type": "string",
                        "description": "`queued`, `running`, `waiting`, `stalled`, `completed`, `failed` or `cancelled`."
                    },
                    "state_label": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "description": "The task's own status, before it is grouped into `state`."
                    },
                    "status_label": {
                        "type": "string"
                    },
                    "progress": {
                        "$ref": "#/components/schemas/_TaskProgressDoc"
                    },
                    "message": {
                        "type": "string"
                    },
                    "details": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "errors": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "link": {
                        "type": "object",
                        "additionalProperties": {},
                        "nullable": true,
                        "description": "The dashboard page about it: `{path, query, label}`, or null."
                    },
                    "actions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "What the caller may do with it now: `cancel`, `resume`, `retry`."
                    },
                    "created_by_username": {
                        "type": "string",
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "groups": {
                        "type": "integer",
                        "description": "Groups it acts on."
                    },
                    "gone": {
                        "type": "integer",
                        "description": "Groups no longer there, or with nothing left to remove."
                    }
                },
                "required": [
                    "actions",
                    "created_at",
                    "created_by_username",
                    "details",
                    "errors",
                    "finished_at",
                    "gone",
                    "groups",
                    "id",
                    "kind",
                    "kind_label",
                    "link",
                    "message",
                    "progress",
                    "started_at",
                    "state",
                    "state_label",
                    "status",
                    "status_label",
                    "subtitle",
                    "title",
                    "updated_at"
                ]
            },
            "StreamFollowedChannel": {
                "type": "object",
                "description": "The provider channel a stream follows.",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "provider_name": {
                        "type": "string"
                    },
                    "item_name": {
                        "type": "string",
                        "description": "The channel's name at the provider."
                    },
                    "gone": {
                        "type": "boolean",
                        "description": "The provider no longer lists it."
                    },
                    "spare_name": {
                        "type": "string",
                        "description": "The provider tried last when its sources fail; may be empty."
                    }
                },
                "required": [
                    "gone",
                    "item_name",
                    "provider",
                    "provider_name",
                    "spare_name"
                ]
            },
            "StreamFormatEnum": {
                "enum": [
                    "ts",
                    "live_ts",
                    "live_hls"
                ],
                "type": "string",
                "description": "* `ts` - MPEG-TS (no /live/)\n* `live_ts` - MPEG-TS with /live/\n* `live_hls` - HLS with /live/"
            },
            "StreamLogoCounters": {
                "type": "object",
                "properties": {
                    "missing": {
                        "type": "integer"
                    },
                    "found": {
                        "type": "integer"
                    },
                    "auto_fill": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "auto_fill",
                    "found",
                    "missing"
                ]
            },
            "StreamLogosChangeActionEnum": {
                "enum": [
                    "find",
                    "clear"
                ],
                "type": "string",
                "description": "* `find` - find\n* `clear` - clear"
            },
            "StreamLogosChangeRequest": {
                "type": "object",
                "properties": {
                    "action": {
                        "$ref": "#/components/schemas/StreamLogosChangeActionEnum"
                    },
                    "mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/LogoModeEnum"
                            }
                        ],
                        "default": "missing"
                    },
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    }
                },
                "required": [
                    "action"
                ]
            },
            "StreamPinnedServer": {
                "type": "object",
                "description": "A server the stream is pinned to: `position` 0 plays it, the others\ntake over in order when it fails.",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "server_instance_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "position": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "description": "Lower = higher priority. 0 is primary; 1, 2, … are failover targets in order."
                    }
                },
                "required": [
                    "position",
                    "server",
                    "server_instance_id",
                    "server_name"
                ]
            },
            "StreamPinnedServerRequest": {
                "type": "object",
                "description": "A server the stream is pinned to: `position` 0 plays it, the others\ntake over in order when it fails.",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "position": {
                        "type": "integer",
                        "maximum": 32767,
                        "minimum": 0,
                        "description": "Lower = higher priority. 0 is primary; 1, 2, … are failover targets in order."
                    }
                },
                "required": [
                    "position",
                    "server"
                ]
            },
            "StreamPreviewAddress": {
                "type": "object",
                "properties": {
                    "direct": {
                        "type": "boolean"
                    },
                    "url": {
                        "type": "string"
                    },
                    "session_id": {
                        "type": "string"
                    },
                    "video_codec": {
                        "type": "string"
                    },
                    "audio_codec": {
                        "type": "string"
                    },
                    "transcoded": {
                        "type": "boolean",
                        "description": "A transcoding profile changes the picture."
                    },
                    "convert": {
                        "type": "string",
                        "nullable": true
                    },
                    "convert_refused": {
                        "type": "string",
                        "description": "Why it cannot convert now."
                    },
                    "expires_in": {
                        "type": "integer",
                        "description": "Seconds the address works."
                    },
                    "server": {
                        "type": "string"
                    },
                    "starting": {
                        "type": "boolean",
                        "description": "Not running yet: allow for a start."
                    },
                    "stops_on_close": {
                        "type": "boolean"
                    },
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "direct",
                    "url"
                ]
            },
            "StreamPreviewOptionsRequest": {
                "type": "object",
                "properties": {
                    "convert": {
                        "$ref": "#/components/schemas/ConvertEnum"
                    },
                    "plays": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        },
                        "description": "Codec families the player handles, e.g. [\"h264\", \"aac\"]."
                    }
                }
            },
            "StreamProviderLink": {
                "type": "object",
                "description": "`GET/PUT streams/streams/{id}/provider-link/`.",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "item_id": {
                        "type": "string",
                        "maxLength": 64
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "sync_logo": {
                        "type": "boolean"
                    },
                    "sync_epg_id": {
                        "type": "boolean"
                    },
                    "provider_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "item_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "gone": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "gone_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "gone",
                    "gone_at",
                    "item_id",
                    "item_name",
                    "provider",
                    "provider_name",
                    "synced_at"
                ]
            },
            "StreamProviderLinkRequest": {
                "type": "object",
                "description": "`GET/PUT streams/streams/{id}/provider-link/`.",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "item_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "sync_logo": {
                        "type": "boolean"
                    },
                    "sync_epg_id": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "item_id",
                    "provider"
                ]
            },
            "StreamProviderLinkSaved": {
                "type": "object",
                "description": "A stream's link once saved, with the stream's name now.",
                "properties": {
                    "provider": {
                        "type": "integer"
                    },
                    "item_id": {
                        "type": "string",
                        "maxLength": 64
                    },
                    "sync_name": {
                        "type": "boolean"
                    },
                    "sync_logo": {
                        "type": "boolean"
                    },
                    "sync_epg_id": {
                        "type": "boolean"
                    },
                    "provider_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "item_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "gone": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "gone_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "synced_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "stream_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "renamed_from": {
                        "type": "string",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Its name before, when following renamed it."
                    }
                },
                "required": [
                    "gone",
                    "gone_at",
                    "item_id",
                    "item_name",
                    "provider",
                    "provider_name",
                    "renamed_from",
                    "stream_name",
                    "synced_at"
                ]
            },
            "StreamRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "StreamRefusal": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string"
                    }
                },
                "required": [
                    "error"
                ]
            },
            "StreamRenamePreviewRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    },
                    "rename": {
                        "$ref": "#/components/schemas/StreamRenameRuleRequest"
                    }
                },
                "required": [
                    "rename",
                    "selection"
                ]
            },
            "StreamRenamePreviewResult": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "changed": {
                        "type": "integer"
                    },
                    "unchanged": {
                        "type": "integer"
                    },
                    "refused": {
                        "type": "integer"
                    },
                    "following": {
                        "type": "integer",
                        "description": "Streams that follow a provider's names."
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "refused_rows": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "required": [
                    "changed",
                    "following",
                    "refused",
                    "refused_rows",
                    "rows",
                    "total",
                    "unchanged"
                ]
            },
            "StreamRenameReplace": {
                "type": "object",
                "properties": {
                    "find": {
                        "type": "string",
                        "maxLength": 100
                    },
                    "to": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "pattern": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "find"
                ]
            },
            "StreamRenameReplaceRequest": {
                "type": "object",
                "properties": {
                    "find": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "to": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "pattern": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "find"
                ]
            },
            "StreamRenameRule": {
                "type": "object",
                "description": "One renaming rule. Every key is optional; at least one must change\nsomething.",
                "properties": {
                    "remove_code": {
                        "type": "boolean",
                        "default": false
                    },
                    "remove_quality": {
                        "type": "boolean",
                        "default": false
                    },
                    "remove_prefix": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "maxLength": 100
                        },
                        "maxItems": 20
                    },
                    "remove_suffix": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "maxLength": 100
                        },
                        "maxItems": 20
                    },
                    "replace": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamRenameReplace"
                        }
                    },
                    "case": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CaseEnum"
                            }
                        ],
                        "default": "keep"
                    },
                    "tidy": {
                        "type": "boolean",
                        "default": true
                    },
                    "add_prefix": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "add_suffix": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "stop_name_sync": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "StreamRenameRuleRequest": {
                "type": "object",
                "description": "One renaming rule. Every key is optional; at least one must change\nsomething.",
                "properties": {
                    "remove_code": {
                        "type": "boolean",
                        "default": false
                    },
                    "remove_quality": {
                        "type": "boolean",
                        "default": false
                    },
                    "remove_prefix": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 100
                        },
                        "maxItems": 20
                    },
                    "remove_suffix": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 100
                        },
                        "maxItems": 20
                    },
                    "replace": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamRenameReplaceRequest"
                        }
                    },
                    "case": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CaseEnum"
                            }
                        ],
                        "default": "keep"
                    },
                    "tidy": {
                        "type": "boolean",
                        "default": true
                    },
                    "add_prefix": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "add_suffix": {
                        "type": "string",
                        "default": "",
                        "maxLength": 100
                    },
                    "stop_name_sync": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "StreamRequest": {
                "type": "object",
                "description": "A stream: what it plays from (`sources`), where it is listed\n(`categories`, `bouquets`) and how servers play it. A created channel\n(`plan`) plays movies and episodes on a schedule; a delayed stream\n(`delay`) plays a channel later.",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Stream Name",
                        "maxLength": 255
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Every category it is listed under; always holds `category`, its main one."
                    },
                    "bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "description": "Bouquets this stream belongs to"
                    },
                    "sources": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSourceRequest"
                        }
                    },
                    "description": {
                        "type": "string",
                        "nullable": true
                    },
                    "thumbnail": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 1000
                    },
                    "epg_channel_id": {
                        "type": "string",
                        "title": "EPG channel",
                        "description": "The guide channel players show for this stream. Blank: no guide.",
                        "maxLength": 255
                    },
                    "streaming_engine": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/StreamingEngineEnum"
                            }
                        ],
                        "description": "Engine used for video processing\n\n* `gstreamer` - GStreamer\n* `ffmpeg` - FFmpeg"
                    },
                    "engine_config": {
                        "title": "Engine Configuration",
                        "description": "JSON configuration for streaming engine parameters"
                    },
                    "transcoding_profile": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "description": "Optional: converts the stream's picture and sound this way."
                    },
                    "allow_passthrough": {
                        "type": "boolean",
                        "description": "On (the default): a source players can play is sent as it is, and one they cannot is converted. Off: the stream is always converted. A transcoding profile always converts."
                    },
                    "user_agent": {
                        "type": "string",
                        "description": "Sent to the source instead of the server's own. Leave empty unless the provider refuses other players.",
                        "maxLength": 512
                    },
                    "http_proxy": {
                        "type": "string",
                        "title": "Proxy",
                        "description": "Reach the source through this HTTP proxy, e.g. http://10.0.0.5:3128.",
                        "maxLength": 255
                    },
                    "http_headers": {
                        "type": "string",
                        "title": "Extra headers",
                        "description": "One \"Name: value\" per line, e.g. \"Referer: https://example.com\" or \"Cookie: session=abc\"."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "is_on_demand": {
                        "type": "boolean",
                        "description": "Started when someone watches and stopped once nobody does. Off: it runs all the time."
                    },
                    "is_direct": {
                        "type": "boolean",
                        "title": "Direct Mode",
                        "description": "Send viewers straight to the source instead of playing it through a server. The line and its rules are still checked, but the source address (and any login in it) is shown to the viewer, there is no connection limit, no live connection row and no backup source."
                    },
                    "routing_mode": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RoutingModeEnum"
                            }
                        ],
                        "description": "`auto`: any streaming server with room plays it (never the panel's own); `pinned`: the servers of `pinned_servers` in order, the next taking over when one fails.\n\n* `auto` - Auto load-balance (excludes panel)\n* `pinned` - Pinned (ordered failover)"
                    },
                    "pinned_servers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamPinnedServerRequest"
                        }
                    },
                    "auto_eligible_servers": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "sort_order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": -2147483648
                    },
                    "archive_days": {
                        "type": "integer",
                        "maximum": 30,
                        "minimum": 0,
                        "title": "Catch-up days",
                        "description": "Record this channel so viewers can watch what aired in the last this many days (TV archive). 0 = off.\n\nWhat it costs: the channel runs all the time on the server that records it, so it holds one provider connection permanently, and it uses disk at its own bitrate (about 10.8 GB a day per Mb/s). Recordings are the channel as viewers get it, never re-encoded. Turning it off deletes the recordings."
                    },
                    "archive_server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Catch-up server",
                        "description": "The server that records this channel and plays its catch-up. The channel runs there, so viewers of the live channel are sent there too: one provider connection, not two. If it goes down, the channel moves to another server and recording waits for it."
                    },
                    "plan": {
                        "writeOnly": true
                    },
                    "delay": {
                        "writeOnly": true
                    }
                },
                "required": [
                    "name"
                ]
            },
            "StreamRestart": {
                "type": "object",
                "description": "One restart: when it happened, and the source the stream was reading.",
                "properties": {
                    "at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "source_url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true,
                        "description": "The source it was reading. The same one again and again points at that source's login or allowance."
                    }
                },
                "required": [
                    "at",
                    "source_url"
                ]
            },
            "StreamRestarts": {
                "type": "object",
                "properties": {
                    "window_seconds": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamRestart"
                        }
                    }
                },
                "required": [
                    "results",
                    "window_seconds"
                ]
            },
            "StreamSelectionRequest": {
                "type": "object",
                "description": "The streams a bulk action applies to: the ones ticked (`ids`), or\nevery stream the list filters select (`all_matching: true` with\n`filters`, which take the list's query parameters), less `exclude`.",
                "properties": {
                    "ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    },
                    "all_matching": {
                        "type": "boolean",
                        "default": false
                    },
                    "filters": {
                        "type": "object",
                        "additionalProperties": {}
                    },
                    "exclude": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "maxItems": 1000000
                    }
                }
            },
            "StreamServerRef": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "StreamSortPreviewRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    },
                    "rules": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSortRuleRequest"
                        }
                    },
                    "unlist_old": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "rules",
                    "selection"
                ]
            },
            "StreamSortPreviewResult": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "moving": {
                        "type": "integer"
                    },
                    "staying": {
                        "type": "integer"
                    },
                    "unmatched": {
                        "type": "integer"
                    },
                    "refused": {
                        "type": "integer"
                    },
                    "by_category": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "refused_rows": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "required": [
                    "by_category",
                    "moving",
                    "refused",
                    "refused_rows",
                    "rows",
                    "staying",
                    "total",
                    "unmatched"
                ]
            },
            "StreamSortRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    },
                    "rules": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSortRuleRequest"
                        }
                    },
                    "unlist_old": {
                        "type": "boolean",
                        "default": true
                    },
                    "save": {
                        "type": "boolean",
                        "default": false
                    }
                },
                "required": [
                    "rules",
                    "selection"
                ]
            },
            "StreamSortRuleRequest": {
                "type": "object",
                "properties": {
                    "match": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/SortRuleMatchEnum"
                            }
                        ],
                        "default": "starts"
                    },
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "new_category": {
                        "type": "string",
                        "default": "",
                        "maxLength": 255
                    }
                },
                "required": [
                    "text"
                ]
            },
            "StreamSortRuleSavedRequest": {
                "type": "object",
                "properties": {
                    "match": {
                        "$ref": "#/components/schemas/SortRuleMatchEnum"
                    },
                    "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                    },
                    "category": {
                        "type": "string",
                        "format": "uuid"
                    }
                },
                "required": [
                    "category",
                    "match",
                    "text"
                ]
            },
            "StreamSortSavedRequest": {
                "type": "object",
                "description": "A sort into categories by name, every rule's `category` an existing\ncategory's id.",
                "properties": {
                    "rules": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSortRuleSavedRequest"
                        }
                    },
                    "unlist_old": {
                        "type": "boolean",
                        "default": true
                    }
                },
                "required": [
                    "rules"
                ]
            },
            "StreamSortSuggestions": {
                "type": "object",
                "properties": {
                    "suggestions": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "required": [
                    "suggestions"
                ]
            },
            "StreamSource": {
                "type": "object",
                "description": "One source of a stream. `order` 0 is the main one; the others are\nbackups, tried in order when it fails. Only `source` and `order` are\nwritten.",
                "properties": {
                    "source": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "source_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "source_url": {
                        "type": "string",
                        "format": "uri",
                        "readOnly": true
                    },
                    "source_health": {
                        "type": "string",
                        "readOnly": true
                    },
                    "source_health_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "source_is_active": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Priority. 0 = primary. Lower values are tried first."
                    }
                },
                "required": [
                    "source",
                    "source_health",
                    "source_health_at",
                    "source_is_active",
                    "source_name",
                    "source_url"
                ]
            },
            "StreamSourceLine": {
                "type": "object",
                "properties": {
                    "host": {
                        "type": "string"
                    },
                    "user": {
                        "type": "string"
                    },
                    "main": {
                        "type": "integer"
                    },
                    "backup": {
                        "type": "integer"
                    },
                    "streams": {
                        "type": "integer"
                    },
                    "provider": {
                        "type": "integer",
                        "nullable": true
                    },
                    "provider_name": {
                        "type": "string"
                    }
                },
                "required": [
                    "backup",
                    "host",
                    "main",
                    "provider",
                    "provider_name",
                    "streams",
                    "user"
                ]
            },
            "StreamSourceLines": {
                "type": "object",
                "properties": {
                    "streams": {
                        "type": "integer"
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamSourceLine"
                        }
                    }
                },
                "required": [
                    "lines",
                    "streams"
                ]
            },
            "StreamSourceRequest": {
                "type": "object",
                "description": "One source of a stream. `order` 0 is the main one; the others are\nbackups, tried in order when it fails. Only `source` and `order` are\nwritten.",
                "properties": {
                    "source": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "order": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Priority. 0 = primary. Lower values are tried first."
                    }
                },
                "required": [
                    "source"
                ]
            },
            "StreamSourcesChangeRequest": {
                "type": "object",
                "properties": {
                    "selection": {
                        "$ref": "#/components/schemas/StreamSelectionRequest"
                    },
                    "sources": {
                        "$ref": "#/components/schemas/SourcesChangeRequest"
                    }
                },
                "required": [
                    "selection",
                    "sources"
                ]
            },
            "StreamSourcesPreview": {
                "type": "object",
                "properties": {
                    "streams": {
                        "type": "integer"
                    },
                    "changed": {
                        "type": "integer"
                    },
                    "same": {
                        "type": "integer"
                    },
                    "unmatched": {
                        "type": "integer"
                    },
                    "skipped": {
                        "type": "integer"
                    },
                    "conflicts": {
                        "type": "integer"
                    },
                    "by": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "integer"
                        }
                    },
                    "sources_changed": {
                        "type": "integer"
                    },
                    "restarts": {
                        "type": "integer"
                    },
                    "follow": {
                        "type": "integer"
                    },
                    "unmatched_streams": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "skipped_streams": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "conflict_streams": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "sample": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    },
                    "check": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "With `mode: check` only."
                    }
                },
                "required": [
                    "changed",
                    "streams"
                ]
            },
            "StreamStatusEnum": {
                "enum": [
                    "online",
                    "offline",
                    "error",
                    "starting"
                ],
                "type": "string",
                "description": "* `online` - Online\n* `offline` - Offline\n* `error` - Error\n* `starting` - Starting"
            },
            "StreamTidyGroup": {
                "type": "object",
                "properties": {
                    "key": {
                        "$ref": "#/components/schemas/KeyEnum"
                    },
                    "count": {
                        "type": "integer"
                    },
                    "days": {
                        "type": "integer",
                        "nullable": true
                    },
                    "sample": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "required": [
                    "count",
                    "days",
                    "key",
                    "sample"
                ]
            },
            "StreamTidyGroups": {
                "type": "object",
                "properties": {
                    "groups": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StreamTidyGroup"
                        }
                    }
                },
                "required": [
                    "groups"
                ]
            },
            "StreamingAddressesRequest": {
                "type": "object",
                "description": "The names viewers reach the streaming servers by, and how each viewer gets one.",
                "properties": {
                    "addresses": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 253
                        },
                        "description": "The names viewers are sent to, the main one first.",
                        "maxItems": 10,
                        "minItems": 1
                    },
                    "rule": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/RuleEnum"
                            }
                        ],
                        "default": "turns",
                        "description": "How each new viewer gets one: take turns, least busy, same per viewer, at random.\n\n* `turns` - turns\n* `least_busy` - least_busy\n* `same_viewer` - same_viewer\n* `random` - random"
                    }
                },
                "required": [
                    "addresses"
                ]
            },
            "StreamingEngineEnum": {
                "enum": [
                    "gstreamer",
                    "ffmpeg"
                ],
                "type": "string",
                "description": "* `gstreamer` - GStreamer\n* `ffmpeg` - FFmpeg"
            },
            "StreamingSettings": {
                "type": "object",
                "description": "The streaming settings (Settings → Streaming). The channel-down video is uploaded on its own; this says whether there is one.",
                "properties": {
                    "down_video_enabled": {
                        "type": "boolean",
                        "title": "Show a video when a channel is down",
                        "description": "Viewers of a channel that cannot start watch it for a while, then their player tries the channel again. Off: the player gets an error at once."
                    },
                    "down_video_seconds": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Retry after (seconds)",
                        "description": "How long a viewer watches it before the player tries the channel again."
                    },
                    "down_video_name": {
                        "type": "string",
                        "readOnly": true,
                        "title": "Own video",
                        "description": "Empty: the Minimus \"No signal\" video."
                    },
                    "has_own_video": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "use_video_card": {
                        "type": "boolean",
                        "title": "Encode on the video card when a server has one",
                        "description": "NVIDIA (NVENC), Intel or AMD cards encode transcoded streams and the converted titles of created channels for a fraction of the processor. Off: the processor encodes."
                    }
                },
                "required": [
                    "down_video_name",
                    "has_own_video"
                ]
            },
            "StreamingSettingsRequest": {
                "type": "object",
                "description": "The streaming settings (Settings → Streaming). The channel-down video is uploaded on its own; this says whether there is one.",
                "properties": {
                    "down_video_enabled": {
                        "type": "boolean",
                        "title": "Show a video when a channel is down",
                        "description": "Viewers of a channel that cannot start watch it for a while, then their player tries the channel again. Off: the player gets an error at once."
                    },
                    "down_video_seconds": {
                        "type": "integer",
                        "maximum": 600,
                        "minimum": 5,
                        "title": "Retry after (seconds)",
                        "description": "How long a viewer watches it before the player tries the channel again."
                    },
                    "use_video_card": {
                        "type": "boolean",
                        "title": "Encode on the video card when a server has one",
                        "description": "NVIDIA (NVENC), Intel or AMD cards encode transcoded streams and the converted titles of created channels for a fraction of the processor. Off: the processor encodes."
                    }
                }
            },
            "SubtitleTrack": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "index": {
                        "type": "integer",
                        "readOnly": true,
                        "title": "Track Index",
                        "description": "Position within the stored container, 0-based."
                    },
                    "language": {
                        "type": "string",
                        "description": "ISO 639-2 code (eng, fra, ara). Required for operator-supplied files — an untagged subtitle shows up as \"Track 3\" on every player.",
                        "maxLength": 8
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "codec": {
                        "type": "string",
                        "readOnly": true,
                        "description": "subrip, ass, hdmv_pgs_subtitle, ..."
                    },
                    "is_default": {
                        "type": "boolean",
                        "title": "Default Track"
                    },
                    "is_forced": {
                        "type": "boolean",
                        "title": "Forced",
                        "description": "Shown automatically for foreign-language passages even when subtitles are off."
                    },
                    "is_sdh": {
                        "type": "boolean",
                        "title": "SDH / Hard of hearing"
                    },
                    "source_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Where an operator-supplied subtitle was fetched from. Empty for tracks that came out of the source media.",
                        "maxLength": 1000
                    }
                },
                "required": [
                    "codec",
                    "id",
                    "index"
                ]
            },
            "SubtitleTrackRequest": {
                "type": "object",
                "properties": {
                    "language": {
                        "type": "string",
                        "description": "ISO 639-2 code (eng, fra, ara). Required for operator-supplied files — an untagged subtitle shows up as \"Track 3\" on every player.",
                        "maxLength": 8
                    },
                    "title": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "is_default": {
                        "type": "boolean",
                        "title": "Default Track"
                    },
                    "is_forced": {
                        "type": "boolean",
                        "title": "Forced",
                        "description": "Shown automatically for foreign-language passages even when subtitles are off."
                    },
                    "is_sdh": {
                        "type": "boolean",
                        "title": "SDH / Hard of hearing"
                    },
                    "source_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Where an operator-supplied subtitle was fetched from. Empty for tracks that came out of the source media.",
                        "maxLength": 1000
                    }
                }
            },
            "SuggestedBouquets": {
                "type": "object",
                "properties": {
                    "movies": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "series": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                },
                "required": [
                    "movies",
                    "series"
                ]
            },
            "SyncEveryMinutesEnum": {
                "enum": [
                    0,
                    15,
                    30,
                    60,
                    360,
                    720,
                    1440
                ],
                "type": "integer",
                "description": "* `0` - Off\n* `15` - Every 15 minutes\n* `30` - Every 30 minutes\n* `60` - Every hour\n* `360` - Every 6 hours\n* `720` - Every 12 hours\n* `1440` - Every 24 hours"
            },
            "TEnum": {
                "enum": [
                    "entry",
                    "category",
                    "episode"
                ],
                "type": "string",
                "description": "* `entry` - entry\n* `category` - category\n* `episode` - episode"
            },
            "TitlePreview": {
                "type": "object",
                "properties": {
                    "url": {
                        "type": "string",
                        "description": "The link to open in a player. It works for a short while."
                    },
                    "session_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The viewing session it opened, to close with DELETE on the same address. Null for a title played by redirect."
                    },
                    "server": {
                        "type": "string",
                        "description": "The playing server's instance id."
                    },
                    "container": {
                        "type": "string"
                    },
                    "video_codec": {
                        "type": "string"
                    },
                    "audio_codec": {
                        "type": "string"
                    },
                    "duration_seconds": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "session_id",
                    "url"
                ]
            },
            "TitleUploadRequest": {
                "type": "object",
                "properties": {
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "description": "A server that keeps movies and episodes."
                    },
                    "filename": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512
                    },
                    "size_bytes": {
                        "type": "integer",
                        "minimum": 0
                    }
                },
                "required": [
                    "filename",
                    "server",
                    "size_bytes"
                ]
            },
            "TmdbGenres": {
                "type": "object",
                "properties": {
                    "movie": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "series": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "required": [
                    "movie",
                    "series"
                ]
            },
            "TmdbMatch": {
                "type": "object",
                "properties": {
                    "tmdb_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "original_name": {
                        "type": "string"
                    },
                    "year": {
                        "type": "string",
                        "description": "Empty when TMDB has no date."
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "backdrop_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "rating": {
                        "type": "number",
                        "format": "double"
                    }
                },
                "required": [
                    "backdrop_url",
                    "name",
                    "original_name",
                    "plot",
                    "poster_url",
                    "rating",
                    "tmdb_id",
                    "year"
                ]
            },
            "TmdbProblem": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    },
                    "configured": {
                        "type": "boolean",
                        "description": "False when no TMDB key is set (Settings → VOD)."
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "TmdbSearch": {
                "type": "object",
                "properties": {
                    "configured": {
                        "type": "boolean",
                        "description": "Always true here: a TMDB key is set."
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TmdbMatch"
                        }
                    }
                },
                "required": [
                    "configured",
                    "results"
                ]
            },
            "TmdbSeasonOutline": {
                "type": "object",
                "properties": {
                    "number": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "poster_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "air_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "episode_count": {
                        "type": "integer"
                    }
                },
                "required": [
                    "air_date",
                    "episode_count",
                    "name",
                    "number",
                    "plot",
                    "poster_url"
                ]
            },
            "TmdbSyncRequest": {
                "type": "object",
                "description": "Which seasons to bring in from TMDB; all of them when empty.",
                "properties": {
                    "seasons": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "maximum": 999,
                            "minimum": 0
                        },
                        "maxItems": 500
                    },
                    "include_specials": {
                        "type": "boolean",
                        "default": false
                    }
                }
            },
            "TmdbTitle": {
                "type": "object",
                "description": "What a form can fill in from one TMDB title.",
                "properties": {
                    "tmdb_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "year": {
                        "type": "integer",
                        "nullable": true
                    },
                    "rating": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "genre": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "director": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "cast": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "country": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "poster_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "backdrop_url": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "required": [
                    "backdrop_url",
                    "cast",
                    "country",
                    "director",
                    "genre",
                    "name",
                    "plot",
                    "poster_url",
                    "rating",
                    "release_date",
                    "tmdb_id",
                    "year"
                ]
            },
            "TmdbTvShow": {
                "type": "object",
                "description": "A TV show on TMDB, with an outline of its seasons.",
                "properties": {
                    "tmdb_id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "plot": {
                        "type": "string"
                    },
                    "release_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": true
                    },
                    "year": {
                        "type": "integer",
                        "nullable": true
                    },
                    "rating": {
                        "type": "number",
                        "format": "double",
                        "nullable": true
                    },
                    "genre": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "director": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "cast": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "country": {
                        "type": "string",
                        "description": "Comma-separated."
                    },
                    "poster_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "backdrop_url": {
                        "type": "string",
                        "nullable": true
                    },
                    "seasons": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/TmdbSeasonOutline"
                        }
                    }
                },
                "required": [
                    "backdrop_url",
                    "cast",
                    "country",
                    "director",
                    "genre",
                    "name",
                    "plot",
                    "poster_url",
                    "rating",
                    "release_date",
                    "seasons",
                    "tmdb_id",
                    "year"
                ]
            },
            "ToneEnum": {
                "enum": [
                    "down",
                    "warn"
                ],
                "type": "string",
                "description": "* `down` - down\n* `warn` - warn"
            },
            "ToolEnum": {
                "enum": [
                    "optimize",
                    "replace",
                    "dedupe",
                    "affix",
                    "case",
                    "url",
                    "format"
                ],
                "type": "string",
                "description": "* `optimize` - optimize\n* `replace` - replace\n* `dedupe` - dedupe\n* `affix` - affix\n* `case` - case\n* `url` - url\n* `format` - format"
            },
            "TranscodingProfile": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "title": "Profile Name",
                        "description": "Display name (e.g. SD, HD, FHD).",
                        "maxLength": 64
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "video_codec": {
                        "$ref": "#/components/schemas/VideoCodecEnum"
                    },
                    "audio_codec": {
                        "$ref": "#/components/schemas/AudioCodecEnum"
                    },
                    "width": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame width in pixels (e.g. 1280)."
                    },
                    "height": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame height in pixels (e.g. 720)."
                    },
                    "resolution": {
                        "type": "string",
                        "readOnly": true
                    },
                    "fps": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame rate. Use 30 for TV unless the source is 60fps."
                    },
                    "video_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Video bitrate ceiling in kbps (encoder uses less for quiet scenes)."
                    },
                    "audio_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Audio bitrate in kbps."
                    },
                    "keyframe_interval": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Keyframe interval in frames. 30 ≈ 1s at 30fps."
                    },
                    "preset": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PresetEnum"
                            }
                        ],
                        "description": "Encoder speed preset (only honoured by software x264enc).\n\n* `ultrafast` - Ultrafast\n* `superfast` - Superfast\n* `veryfast` - Veryfast\n* `faster` - Faster\n* `fast` - Fast\n* `medium` - Medium"
                    },
                    "quality": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Quantizer / CRF. 18-28 sane range; 22 ≈ transparent."
                    },
                    "is_system": {
                        "type": "boolean",
                        "readOnly": true,
                        "description": "System-seeded profile. Operators should clone instead of editing."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "height",
                    "id",
                    "is_system",
                    "name",
                    "resolution",
                    "updated_at",
                    "video_bitrate",
                    "width"
                ]
            },
            "TranscodingProfileRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "minLength": 1,
                        "title": "Profile Name",
                        "description": "Display name (e.g. SD, HD, FHD).",
                        "maxLength": 64
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "video_codec": {
                        "$ref": "#/components/schemas/VideoCodecEnum"
                    },
                    "audio_codec": {
                        "$ref": "#/components/schemas/AudioCodecEnum"
                    },
                    "width": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame width in pixels (e.g. 1280)."
                    },
                    "height": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame height in pixels (e.g. 720)."
                    },
                    "fps": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Output frame rate. Use 30 for TV unless the source is 60fps."
                    },
                    "video_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Video bitrate ceiling in kbps (encoder uses less for quiet scenes)."
                    },
                    "audio_bitrate": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Audio bitrate in kbps."
                    },
                    "keyframe_interval": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Keyframe interval in frames. 30 ≈ 1s at 30fps."
                    },
                    "preset": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PresetEnum"
                            }
                        ],
                        "description": "Encoder speed preset (only honoured by software x264enc).\n\n* `ultrafast` - Ultrafast\n* `superfast` - Superfast\n* `veryfast` - Veryfast\n* `faster` - Faster\n* `fast` - Fast\n* `medium` - Medium"
                    },
                    "quality": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "description": "Quantizer / CRF. 18-28 sane range; 22 ≈ transparent."
                    }
                },
                "required": [
                    "height",
                    "name",
                    "video_bitrate",
                    "width"
                ]
            },
            "TrialsPeriodEnum": {
                "enum": [
                    "day",
                    "week",
                    "month"
                ],
                "type": "string",
                "description": "* `day` - Per day\n* `week` - Per 7 days\n* `month` - Per 30 days"
            },
            "TvShowCounts": {
                "type": "object",
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "active": {
                        "type": "integer"
                    },
                    "episodes": {
                        "type": "integer"
                    },
                    "no_media": {
                        "type": "integer",
                        "description": "Episodes without a file."
                    },
                    "ingesting": {
                        "type": "integer",
                        "description": "Episodes whose file is on its way."
                    },
                    "failed": {
                        "type": "integer",
                        "description": "Episodes whose file failed."
                    },
                    "total_bytes": {
                        "type": "integer",
                        "description": "Size of the episodes' files."
                    }
                },
                "required": [
                    "active",
                    "episodes",
                    "failed",
                    "ingesting",
                    "no_media",
                    "total",
                    "total_bytes"
                ]
            },
            "UnderAttack": {
                "type": "object",
                "properties": {
                    "since": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "ends": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "running": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "ends",
                    "running",
                    "since"
                ]
            },
            "UpdatesOverview": {
                "type": "object",
                "description": "Everything Servers → Update shows.",
                "properties": {
                    "version": {
                        "type": "string",
                        "description": "The build the panel runs."
                    },
                    "release": {
                        "type": "string",
                        "nullable": true,
                        "description": "The release it is, or null."
                    },
                    "track": {
                        "type": "string",
                        "description": "The release track of this license."
                    },
                    "sandbox": {
                        "type": "boolean",
                        "description": "A test build: it is offered no release."
                    },
                    "latest": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PanelRelease"
                            }
                        ],
                        "nullable": true,
                        "description": "The newest release this license may have."
                    },
                    "security": {
                        "type": "string",
                        "nullable": true,
                        "description": "The newest security release, if any."
                    },
                    "must_update": {
                        "type": "boolean",
                        "description": "A security update is due: the panel installs it on its own."
                    },
                    "forced_current": {
                        "type": "boolean",
                        "description": "What runs is a security release: no rolling back."
                    },
                    "rollback": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelRelease"
                        },
                        "description": "The releases the panel may go back to."
                    },
                    "news": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelReleaseNews"
                        },
                        "description": "Notes of every newer release, newest first."
                    },
                    "releases": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/PanelRelease"
                        },
                        "description": "Every release, to tell which one each server runs."
                    },
                    "checked_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "error": {
                        "type": "string",
                        "description": "Why the releases could not be checked, or empty."
                    },
                    "panel": {
                        "$ref": "#/components/schemas/PanelUpdateState"
                    },
                    "streaming": {
                        "$ref": "#/components/schemas/PanelStreamingState"
                    },
                    "addresses": {
                        "$ref": "#/components/schemas/PanelAddressesState"
                    }
                },
                "required": [
                    "addresses",
                    "checked_at",
                    "error",
                    "forced_current",
                    "latest",
                    "must_update",
                    "news",
                    "panel",
                    "release",
                    "releases",
                    "rollback",
                    "sandbox",
                    "security",
                    "streaming",
                    "track",
                    "version"
                ]
            },
            "UploadTicket": {
                "type": "object",
                "properties": {
                    "job_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The transfer, as GET /vod/jobs/ lists it."
                    },
                    "upload_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "The server's address to send the file to."
                    },
                    "chunk_size": {
                        "type": "integer",
                        "description": "The most bytes one PUT may carry."
                    },
                    "expires_in": {
                        "type": "integer",
                        "description": "Seconds the address works for."
                    }
                },
                "required": [
                    "chunk_size",
                    "expires_in",
                    "job_id",
                    "upload_url"
                ]
            },
            "User": {
                "type": "object",
                "description": "An account: its details, status, groups, permissions and credits.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_superuser": {
                        "type": "boolean",
                        "title": "Superuser status",
                        "description": "Designates that this user has all permissions without explicitly assigning them."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "groups_display": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "can_customize_packages": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "can_customize_bouquets": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "administers_panel": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Every permission it holds, as `app.codename` (for example `streams.add_stream`).",
                        "readOnly": true
                    },
                    "credit_balance": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "credits_unlimited": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "administers_panel",
                    "can_customize_bouquets",
                    "can_customize_packages",
                    "created_at",
                    "credit_balance",
                    "credits_unlimited",
                    "groups_display",
                    "id",
                    "permissions",
                    "updated_at",
                    "username"
                ]
            },
            "UserCreate": {
                "type": "object",
                "description": "A new account. Its username can't be one a playlist editor login uses.",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "id",
                    "username"
                ]
            },
            "UserCreateRequest": {
                "type": "object",
                "description": "A new account. Its username can't be one a playlist editor login uses.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "password": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "password_confirm": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 1
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "password",
                    "password_confirm",
                    "username"
                ]
            },
            "UserList": {
                "type": "object",
                "description": "An account as the users list shows it. `credit_balance` is null for an account that holds no credits (anyone but a reseller).",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "username": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_superuser": {
                        "type": "boolean",
                        "title": "Superuser status",
                        "description": "Designates that this user has all permissions without explicitly assigning them."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "user_type": {
                        "type": "string",
                        "readOnly": true
                    },
                    "owner": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "last_login": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "credit_balance": {
                        "type": "string",
                        "nullable": true,
                        "readOnly": true
                    },
                    "credits_unlimited": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "two_step": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "passkeys": {
                        "type": "integer",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "credit_balance",
                    "credits_unlimited",
                    "groups",
                    "id",
                    "last_login",
                    "owner",
                    "passkeys",
                    "two_step",
                    "user_type",
                    "username"
                ]
            },
            "UserPackage": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "line_user": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Line user who received this package"
                    },
                    "line_user_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "package": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "package_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "assigned_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true,
                        "description": "Staff user who assigned this package"
                    },
                    "assigned_by_username": {
                        "type": "string",
                        "readOnly": true
                    },
                    "assigned_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When this package expires for the user"
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "is_expired_status": {
                        "type": "boolean",
                        "readOnly": true
                    }
                },
                "required": [
                    "assigned_at",
                    "assigned_by",
                    "assigned_by_username",
                    "expires_at",
                    "id",
                    "is_expired_status",
                    "line_user",
                    "line_user_username",
                    "package",
                    "package_name"
                ]
            },
            "UserPackageDeactivated": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string"
                    }
                },
                "required": [
                    "status"
                ]
            },
            "UserPackageRequest": {
                "type": "object",
                "properties": {
                    "line_user": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Line user who received this package"
                    },
                    "package": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When this package expires for the user"
                    },
                    "is_active": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "expires_at",
                    "line_user",
                    "package"
                ]
            },
            "UserPermission": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "codename": {
                        "type": "string"
                    },
                    "source": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/UserPermissionSourceEnum"
                            }
                        ],
                        "description": "Where the account gets it: only a `direct` one can be taken away here.\n\n* `group` - From a group\n* `direct` - Given to the account\n* `both` - Both"
                    }
                },
                "required": [
                    "codename",
                    "id",
                    "name",
                    "source"
                ]
            },
            "UserPermissionIdsRequest": {
                "type": "object",
                "properties": {
                    "permission_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        },
                        "description": "Every permission given to the account itself (not through a group). An empty list clears them."
                    }
                },
                "required": [
                    "permission_ids"
                ]
            },
            "UserPermissionSourceEnum": {
                "enum": [
                    "group",
                    "direct",
                    "both"
                ],
                "type": "string",
                "description": "* `group` - From a group\n* `direct` - Given to the account\n* `both` - Both"
            },
            "UserPermissionsResponseDoc": {
                "type": "object",
                "properties": {
                    "category": {
                        "type": "string",
                        "description": "The area the permission belongs to, as `app.model`."
                    },
                    "model": {
                        "type": "string"
                    },
                    "app": {
                        "type": "string"
                    },
                    "permissions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/UserPermission"
                        }
                    }
                },
                "required": [
                    "app",
                    "category",
                    "model",
                    "permissions"
                ]
            },
            "UserProfile": {
                "type": "object",
                "description": "The account's type.",
                "properties": {
                    "user_type": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/UserTypeEnum"
                            }
                        ],
                        "description": "Type of user - staff for dashboard access, line for stream access only\n\n* `staff` - Staff User\n* `line` - Line User\n* `service` - Service Account"
                    },
                    "user_type_display": {
                        "type": "string",
                        "readOnly": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "created_at",
                    "updated_at",
                    "user_type_display"
                ]
            },
            "UserRequest": {
                "type": "object",
                "description": "An account: its details, status, groups, permissions and credits.",
                "properties": {
                    "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 150
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "nullable": true,
                        "title": "Email address",
                        "maxLength": 254
                    },
                    "first_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "last_name": {
                        "type": "string",
                        "maxLength": 150
                    },
                    "phone_number": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 14
                    },
                    "phone_country_code": {
                        "type": "string",
                        "nullable": true,
                        "maxLength": 5
                    },
                    "is_staff": {
                        "type": "boolean",
                        "title": "Staff status",
                        "description": "Designates whether the user can log into this admin site."
                    },
                    "is_superuser": {
                        "type": "boolean",
                        "title": "Superuser status",
                        "description": "Designates that this user has all permissions without explicitly assigning them."
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    }
                },
                "required": [
                    "username"
                ]
            },
            "UserTypeEnum": {
                "enum": [
                    "staff",
                    "line",
                    "service"
                ],
                "type": "string",
                "description": "* `staff` - Staff User\n* `line` - Line User\n* `service` - Service Account"
            },
            "ValuesEnum": {
                "enum": [
                    "epg_id",
                    "epg_shift",
                    "number",
                    "logo",
                    "url",
                    "name"
                ],
                "type": "string",
                "description": "* `epg_id` - epg_id\n* `epg_shift` - epg_shift\n* `number` - number\n* `logo` - logo\n* `url` - url\n* `name` - name"
            },
            "VideoCodecEnum": {
                "enum": [
                    "h264"
                ],
                "type": "string",
                "description": "* `h264` - H.264"
            },
            "VodCategoriesEnum": {
                "enum": [
                    "playlist",
                    "tmdb",
                    "custom"
                ],
                "type": "string",
                "description": "* `playlist` - The provider's categories\n* `tmdb` - TMDB genres\n* `custom` - My own mapping"
            },
            "VodDeliveryEnum": {
                "enum": [
                    "redirect",
                    "proxy",
                    "balanced"
                ],
                "type": "string",
                "description": "* `redirect` - Straight from the provider\n* `proxy` - Through one streaming server\n* `balanced` - Through any streaming server (load balanced)"
            },
            "VodSettings": {
                "type": "object",
                "description": "The movie and TV show settings (Settings → VOD). The API key is write-only: it is never sent back.",
                "properties": {
                    "tmdb_configured": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "tmdb_language": {
                        "type": "string",
                        "description": "Language for plots and titles, e.g. en-US, fr-FR, ar-SA.",
                        "maxLength": 16
                    },
                    "tmdb_image_base": {
                        "type": "string",
                        "title": "TMDB image base URL",
                        "description": "Prefix for poster and backdrop paths. The trailing size segment (w500, original, ...) decides how large the stored artwork URLs are.",
                        "maxLength": 255
                    },
                    "s3_storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Movie storage",
                        "description": "The bucket movies are browsed and read from. Empty turns the object-storage source off. Buckets are added under Settings → Storage."
                    },
                    "s3_storage_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "s3_configured": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "s3_presign_ttl": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Signed link lifetime (seconds)",
                        "description": "How long a signed download link stays valid. It must outlast the transfer itself: if it expires mid-download, a node resuming a large file is refused partway through. Default 6 hours."
                    },
                    "ticket_expiration": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Playback ticket lifetime (seconds)",
                        "description": "How long a movie link stays valid once a viewer opens it. Longer than a live token by necessity — a seeking player reopens the connection on every scrub, so the link has to survive a whole film. This is the blast-radius control: shorten it if a shared link matters more than a viewer having to reopen a long movie. Default 4 hours."
                    },
                    "upload_chunk_mb": {
                        "type": "integer",
                        "maximum": 16,
                        "minimum": 1,
                        "title": "Upload chunk size (MB)",
                        "description": "How much of a file the browser sends per request when you upload a movie. Smaller loses less to a dropped connection; larger means fewer round trips. Streaming servers refuse chunks above their own limit (16 MB unless changed on the server). Default 8 MB."
                    },
                    "upload_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Upload permission lifetime (seconds)",
                        "description": "How long a browser may keep sending one upload. It has to outlast the upload itself — a 40 GB file on a slow line takes hours — but it authorises writes, so not much longer. Default 6 hours."
                    },
                    "replica_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Server-to-server copy lifetime (seconds)",
                        "description": "How long one streaming server may pull a movie from another when copying it. Fast links, but a large library copied one file at a time can take a while. Default 24 hours."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "s3_configured",
                    "s3_storage_name",
                    "tmdb_configured",
                    "updated_at"
                ]
            },
            "VodSettingsRequest": {
                "type": "object",
                "description": "The movie and TV show settings (Settings → VOD). The API key is write-only: it is never sent back.",
                "properties": {
                    "tmdb_api_key": {
                        "type": "string",
                        "writeOnly": true
                    },
                    "tmdb_language": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Language for plots and titles, e.g. en-US, fr-FR, ar-SA.",
                        "maxLength": 16
                    },
                    "tmdb_image_base": {
                        "type": "string",
                        "minLength": 1,
                        "title": "TMDB image base URL",
                        "description": "Prefix for poster and backdrop paths. The trailing size segment (w500, original, ...) decides how large the stored artwork URLs are.",
                        "maxLength": 255
                    },
                    "s3_storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true,
                        "title": "Movie storage",
                        "description": "The bucket movies are browsed and read from. Empty turns the object-storage source off. Buckets are added under Settings → Storage."
                    },
                    "s3_presign_ttl": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Signed link lifetime (seconds)",
                        "description": "How long a signed download link stays valid. It must outlast the transfer itself: if it expires mid-download, a node resuming a large file is refused partway through. Default 6 hours."
                    },
                    "ticket_expiration": {
                        "type": "integer",
                        "maximum": 2147483647,
                        "minimum": 0,
                        "title": "Playback ticket lifetime (seconds)",
                        "description": "How long a movie link stays valid once a viewer opens it. Longer than a live token by necessity — a seeking player reopens the connection on every scrub, so the link has to survive a whole film. This is the blast-radius control: shorten it if a shared link matters more than a viewer having to reopen a long movie. Default 4 hours."
                    },
                    "upload_chunk_mb": {
                        "type": "integer",
                        "maximum": 16,
                        "minimum": 1,
                        "title": "Upload chunk size (MB)",
                        "description": "How much of a file the browser sends per request when you upload a movie. Smaller loses less to a dropped connection; larger means fewer round trips. Streaming servers refuse chunks above their own limit (16 MB unless changed on the server). Default 8 MB."
                    },
                    "upload_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Upload permission lifetime (seconds)",
                        "description": "How long a browser may keep sending one upload. It has to outlast the upload itself — a 40 GB file on a slow line takes hours — but it authorises writes, so not much longer. Default 6 hours."
                    },
                    "replica_ticket_expiration": {
                        "type": "integer",
                        "maximum": 604800,
                        "minimum": 600,
                        "title": "Server-to-server copy lifetime (seconds)",
                        "description": "How long one streaming server may pull a movie from another when copying it. Fast links, but a large library copied one file at a time can take a while. Default 24 hours."
                    }
                }
            },
            "WatchFile": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "ref": {
                        "type": "string",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "size_bytes": {
                        "type": "integer",
                        "readOnly": true
                    },
                    "modified": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "state": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFileStateEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFileKindEnum"
                            }
                        ],
                        "readOnly": true
                    },
                    "note": {
                        "type": "string",
                        "readOnly": true
                    },
                    "title": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFileTitle"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "without_details": {
                        "type": "boolean",
                        "description": "In the panel under a title TMDB gave nothing for (\"Find on TMDB\" fills it).",
                        "readOnly": true
                    },
                    "missing": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "tmdb_id": {
                        "type": "string",
                        "readOnly": true
                    },
                    "as_is": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "seen_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    }
                },
                "required": [
                    "as_is",
                    "id",
                    "kind",
                    "missing",
                    "modified",
                    "name",
                    "note",
                    "ref",
                    "seen_at",
                    "size_bytes",
                    "state",
                    "title",
                    "tmdb_id",
                    "updated_at",
                    "without_details"
                ]
            },
            "WatchFileKindEnum": {
                "enum": [
                    "movie",
                    "episode"
                ],
                "type": "string",
                "description": "* `movie` - Movie\n* `episode` - TV episode"
            },
            "WatchFileStateEnum": {
                "enum": [
                    "new",
                    "waiting",
                    "added",
                    "linked",
                    "no_match",
                    "skipped",
                    "failed"
                ],
                "type": "string",
                "description": "* `new` - New\n* `waiting` - Still being copied\n* `added` - Added\n* `linked` - Already in the panel\n* `no_match` - Not found on TMDB\n* `skipped` - Skipped\n* `failed` - Failed"
            },
            "WatchFileTitle": {
                "type": "object",
                "properties": {
                    "kind": {
                        "$ref": "#/components/schemas/MovieOrSeriesEnum"
                    },
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "kind",
                    "name"
                ]
            },
            "WatchFolder": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "name": {
                        "type": "string",
                        "description": "Empty: the folder's own name.",
                        "maxLength": 120
                    },
                    "display_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Watching",
                        "description": "Off: paused, the folder is scanned only when asked."
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFolderKindEnum"
                            }
                        ],
                        "description": "What the folder holds. A file that looks like the other kind is skipped, and says so.\n\n* `movies` - Movies\n* `series` - TV shows\n* `both` - Movies and TV shows"
                    },
                    "source": {
                        "$ref": "#/components/schemas/WatchFolderSourceEnum"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "server_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "root": {
                        "description": "Incoming folder: files are moved into the server's storage. Media folder: files stay where they are.\n\n* `incoming` - Incoming folder\n* `media` - Media folder",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/RootEnum"
                            },
                            {
                                "$ref": "#/components/schemas/BlankEnum"
                            }
                        ]
                    },
                    "path": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "storage_name": {
                        "type": "string",
                        "readOnly": true
                    },
                    "delivery": {
                        "$ref": "#/components/schemas/WatchFolderDeliveryEnum"
                    },
                    "scan_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScanEveryMinutesEnum"
                            }
                        ],
                        "title": "Scan",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CategoriesEnum"
                            }
                        ],
                        "description": "Folder names: \"Action/Heat (1995).mkv\" goes under Action (a file in no such folder goes under its TMDB genres). TMDB genres. One category for movies and one for TV shows. Or your own mapping of folder names (else genres) to categories.\n\n* `folder` - Folder names\n* `tmdb` - TMDB genres\n* `fixed` - One category\n* `custom` - My own mapping"
                    },
                    "movie_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "series_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "category_map": {},
                    "movie_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "use_tmdb": {
                        "type": "boolean",
                        "title": "Details from TMDB",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "add_unmatched": {
                        "type": "boolean",
                        "description": "A title TMDB does not know is added with its file name. Off: it waits for you."
                    },
                    "tmdb_language": {
                        "type": "string",
                        "description": "Language of titles and plots from TMDB, e.g. fr-FR. Empty: the one in Settings → VOD.",
                        "maxLength": 16
                    },
                    "extensions": {
                        "type": "string",
                        "description": "Only files with these extensions are read, e.g. mkv,mp4.",
                        "maxLength": 255
                    },
                    "next_scan_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "last_scan_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_by": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true,
                        "nullable": true
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "readOnly": true
                    },
                    "counts": {
                        "type": "object",
                        "additionalProperties": {},
                        "readOnly": true
                    },
                    "last_scan": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Scan"
                            }
                        ],
                        "nullable": true,
                        "readOnly": true
                    },
                    "scanning": {
                        "type": "boolean",
                        "readOnly": true
                    },
                    "problem": {
                        "type": "string",
                        "nullable": true,
                        "description": "Why the last scan that ended failed, in a sentence; None when it\ndid not (kept while the folder is paused).",
                        "readOnly": true
                    }
                },
                "required": [
                    "counts",
                    "created_at",
                    "created_by",
                    "display_name",
                    "id",
                    "last_scan",
                    "last_scan_at",
                    "next_scan_at",
                    "problem",
                    "scanning",
                    "server_name",
                    "storage_name",
                    "updated_at"
                ]
            },
            "WatchFolderBulkResult": {
                "type": "object",
                "properties": {
                    "done": {
                        "type": "integer"
                    },
                    "refused": {
                        "type": "integer",
                        "description": "Files the action did not apply to."
                    }
                },
                "required": [
                    "done",
                    "refused"
                ]
            },
            "WatchFolderDefaults": {
                "type": "object",
                "properties": {
                    "suggested_bouquets": {
                        "$ref": "#/components/schemas/SuggestedBouquets"
                    }
                },
                "required": [
                    "suggested_bouquets"
                ]
            },
            "WatchFolderDeliveryEnum": {
                "enum": [
                    "adopt",
                    "link",
                    "download",
                    "proxy",
                    "redirect"
                ],
                "type": "string",
                "description": "* `adopt` - Moved into the server's storage\n* `link` - Served where it is\n* `download` - Downloaded to a server\n* `proxy` - Played through a server\n* `redirect` - Played straight from the bucket"
            },
            "WatchFolderExample": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The file name."
                    },
                    "kind": {
                        "type": "string",
                        "description": "`movie` or `episode`."
                    },
                    "title": {
                        "type": "string"
                    },
                    "year": {
                        "type": "integer",
                        "nullable": true
                    },
                    "show": {
                        "type": "string",
                        "nullable": true
                    },
                    "season": {
                        "type": "integer",
                        "nullable": true
                    },
                    "episode": {
                        "type": "integer",
                        "nullable": true
                    }
                },
                "required": [
                    "episode",
                    "kind",
                    "name",
                    "season",
                    "show",
                    "title",
                    "year"
                ]
            },
            "WatchFolderKindEnum": {
                "enum": [
                    "movies",
                    "series",
                    "both"
                ],
                "type": "string",
                "description": "* `movies` - Movies\n* `series` - TV shows\n* `both` - Movies and TV shows"
            },
            "WatchFolderMappingChoices": {
                "type": "object",
                "properties": {
                    "categories": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/WatchFolderName"
                        },
                        "description": "The folder names it has seen."
                    },
                    "genres": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "TMDB's genres."
                    }
                },
                "required": [
                    "categories",
                    "genres"
                ]
            },
            "WatchFolderName": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "count": {
                        "type": "integer",
                        "description": "Files under it."
                    }
                },
                "required": [
                    "count",
                    "name"
                ]
            },
            "WatchFolderPreview": {
                "type": "object",
                "properties": {
                    "files": {
                        "type": "integer"
                    },
                    "movies": {
                        "type": "integer"
                    },
                    "episodes": {
                        "type": "integer"
                    },
                    "shows": {
                        "type": "integer"
                    },
                    "ignored": {
                        "type": "integer",
                        "description": "Files that are not video files."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Files the folder's kind would leave out."
                    },
                    "in_panel": {
                        "type": "integer",
                        "description": "Files whose title the panel has already."
                    },
                    "watched_by": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchedBy"
                            }
                        ],
                        "nullable": true,
                        "description": "A watch folder already watching this place."
                    },
                    "truncated": {
                        "type": "boolean"
                    },
                    "note": {
                        "type": "string",
                        "nullable": true
                    },
                    "examples": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/WatchFolderExample"
                        },
                        "description": "Up to 8 files and how they are read."
                    }
                },
                "required": [
                    "episodes",
                    "examples",
                    "files",
                    "ignored",
                    "in_panel",
                    "movies",
                    "note",
                    "shows",
                    "skipped",
                    "truncated",
                    "watched_by"
                ]
            },
            "WatchFolderRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Empty: the folder's own name.",
                        "maxLength": 120
                    },
                    "is_enabled": {
                        "type": "boolean",
                        "title": "Watching",
                        "description": "Off: paused, the folder is scanned only when asked."
                    },
                    "kind": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WatchFolderKindEnum"
                            }
                        ],
                        "description": "What the folder holds. A file that looks like the other kind is skipped, and says so.\n\n* `movies` - Movies\n* `series` - TV shows\n* `both` - Movies and TV shows"
                    },
                    "source": {
                        "$ref": "#/components/schemas/WatchFolderSourceEnum"
                    },
                    "server": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "root": {
                        "description": "Incoming folder: files are moved into the server's storage. Media folder: files stay where they are.\n\n* `incoming` - Incoming folder\n* `media` - Media folder",
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/RootEnum"
                            },
                            {
                                "$ref": "#/components/schemas/BlankEnum"
                            }
                        ]
                    },
                    "path": {
                        "type": "string",
                        "maxLength": 1000
                    },
                    "storage": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "delivery": {
                        "$ref": "#/components/schemas/WatchFolderDeliveryEnum"
                    },
                    "scan_every_minutes": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/ScanEveryMinutesEnum"
                            }
                        ],
                        "title": "Scan",
                        "minimum": 0,
                        "maximum": 2147483647
                    },
                    "categories": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/CategoriesEnum"
                            }
                        ],
                        "description": "Folder names: \"Action/Heat (1995).mkv\" goes under Action (a file in no such folder goes under its TMDB genres). TMDB genres. One category for movies and one for TV shows. Or your own mapping of folder names (else genres) to categories.\n\n* `folder` - Folder names\n* `tmdb` - TMDB genres\n* `fixed` - One category\n* `custom` - My own mapping"
                    },
                    "movie_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "series_category": {
                        "type": "string",
                        "format": "uuid",
                        "nullable": true
                    },
                    "category_map": {},
                    "movie_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "series_bouquets": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    "use_tmdb": {
                        "type": "boolean",
                        "title": "Details from TMDB",
                        "description": "Fill posters, plots, cast and ratings from TMDB (the key in Settings → VOD)."
                    },
                    "add_unmatched": {
                        "type": "boolean",
                        "description": "A title TMDB does not know is added with its file name. Off: it waits for you."
                    },
                    "tmdb_language": {
                        "type": "string",
                        "description": "Language of titles and plots from TMDB, e.g. fr-FR. Empty: the one in Settings → VOD.",
                        "maxLength": 16
                    },
                    "extensions": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Only files with these extensions are read, e.g. mkv,mp4.",
                        "maxLength": 255
                    }
                }
            },
            "WatchFolderScanStarted": {
                "type": "object",
                "properties": {
                    "scan": {
                        "$ref": "#/components/schemas/Scan"
                    }
                },
                "required": [
                    "scan"
                ]
            },
            "WatchFolderSourceEnum": {
                "enum": [
                    "node",
                    "s3"
                ],
                "type": "string",
                "description": "* `node` - A server\n* `s3` - A bucket"
            },
            "WatchFolderStopped": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string",
                        "description": "What became of the folder, in a sentence."
                    }
                },
                "required": [
                    "detail"
                ]
            },
            "WatchedBy": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            },
            "_TaskProgressDoc": {
                "type": "object",
                "properties": {
                    "done": {
                        "type": "integer",
                        "nullable": true
                    },
                    "total": {
                        "type": "integer",
                        "nullable": true
                    },
                    "percent": {
                        "type": "integer",
                        "nullable": true,
                        "description": "0 to 100, null while unknown."
                    },
                    "phase": {
                        "type": "string",
                        "description": "What it is doing now, in words; may be empty."
                    }
                },
                "required": [
                    "done",
                    "percent",
                    "phase",
                    "total"
                ]
            },
            "Error": {
                "type": "object",
                "properties": {
                    "detail": {
                        "type": "string"
                    }
                },
                "required": [
                    "detail"
                ],
                "example": {
                    "detail": "You do not have permission to perform this action."
                }
            }
        },
        "securitySchemes": {
            "apiKey": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "mk_live_…",
                "description": "An API key made in the dashboard (API keys → New key), sent as `Authorization: Bearer mk_live_…` (or `X-API-Key: mk_live_…`). It acts as its account, never beyond it, narrowed by its scopes: read, write, manage."
            },
            "editorToken": {
                "type": "http",
                "scheme": "bearer",
                "description": "A playlist editor API token (Playlist editor → API tokens), sent as `Authorization: Bearer mnm_…` or `X-API-Key: mnm_…`."
            }
        },
        "responses": {
            "Invalid": {
                "description": "Something sent is not valid. Each field that is wrong is named with what is wrong.",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "array",
                                "items": {
                                    "type": "string"
                                }
                            },
                            "example": {
                                "max_connections": [
                                    "Ensure this value is less than or equal to 10."
                                ]
                            }
                        }
                    }
                }
            },
            "Notsignedin": {
                "description": "No credential, or one that is wrong, expired or revoked.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Notallowed": {
                "description": "The account, or the key's or app's scopes, may not do this.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Notfound": {
                "description": "Nothing with this id, or nothing the account can see.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Toomanyrequests": {
                "description": "Slow down: wait the seconds in the Retry-After header, then try again.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            }
        }
    },
    "tags": [
        {
            "name": "Lines",
            "description": "A line is one customer's subscription: the username and password their player signs in with, its package, expiry and connections."
        },
        {
            "name": "Packages",
            "description": "What a line gets (bouquets, length, connections, price), and the packages each line holds."
        },
        {
            "name": "Bouquets",
            "description": "Groups of streams, movies and TV shows that packages give."
        },
        {
            "name": "Users",
            "description": "Dashboard accounts: staff and resellers."
        },
        {
            "name": "Groups and permissions",
            "description": "Groups (roles such as Reseller) and the permissions they give."
        },
        {
            "name": "Resellers",
            "description": "Resellers' sub-accounts and their own domains in customers' links."
        },
        {
            "name": "Credits",
            "description": "Resellers' credit balances, prices and every change to them."
        },
        {
            "name": "Streams",
            "description": "Live streams and created channels: add, edit, start, stop, sort and change many at once."
        },
        {
            "name": "Sources",
            "description": "The addresses a stream is read from: main and backups, and their health."
        },
        {
            "name": "Providers",
            "description": "Where your streams, movies and TV shows come from, kept in sync."
        },
        {
            "name": "Playlist imports",
            "description": "Streams added from a playlist file or link, and the import history."
        },
        {
            "name": "Transcoding profiles",
            "description": "How a stream's video is converted when it is not sent as it is."
        },
        {
            "name": "Categories",
            "description": "Categories that group and order streams, movies and TV shows."
        },
        {
            "name": "Connections",
            "description": "Who is watching now, past activity, and blocked addresses."
        },
        {
            "name": "Movies",
            "description": "The movie library."
        },
        {
            "name": "TV shows",
            "description": "TV shows, their seasons and episodes."
        },
        {
            "name": "Watch folders",
            "description": "Folders on a server whose new files are added on their own."
        },
        {
            "name": "Video files",
            "description": "Video files on servers, copies between servers, and their transfers."
        },
        {
            "name": "TV guide",
            "description": "Guide sources, matching channels to the guide, and the programmes."
        },
        {
            "name": "Playlist editor",
            "description": "Playlists you edit from any provider and hand out, with their guide."
        },
        {
            "name": "Playlist editor API",
            "description": "The playlist editor's own API, called with an editor API token instead of an account."
        },
        {
            "name": "Servers",
            "description": "Streaming servers: add, edit, update, move and watch them."
        },
        {
            "name": "Settings",
            "description": "Panel-wide settings: panel, security, streaming, VOD, storage and database."
        },
        {
            "name": "Backups",
            "description": "Backups, their schedules, storage and restores."
        },
        {
            "name": "Background tasks",
            "description": "Long work that runs in the background: imports, mass edits, syncs."
        },
        {
            "name": "License",
            "description": "The panel's license."
        },
        {
            "name": "System",
            "description": "Check that the panel answers."
        }
    ],
    "servers": [
        {
            "url": "https://{panel}",
            "description": "Your panel",
            "variables": {
                "panel": {
                    "default": "panel.example.com",
                    "description": "Your panel's address, as in its install."
                }
            }
        }
    ]
}