{
  "openapi": "3.1.0",
  "info": {
    "title": "PinePods API",
    "description": "HTTP API for the PinePods podcast server. Most endpoints require an `Api-Key` header tied to a user account; admin-only endpoints additionally require an admin (or web) key. This reference is generated directly from the backend source, so it stays in sync with the running code.",
    "license": {
      "name": "GPL-3.0-or-later"
    },
    "version": "0.9.0"
  },
  "servers": [
    {
      "url": "/",
      "description": "This PinePods server (same origin as the API)"
    }
  ],
  "paths": {
    "/api/auth/callback": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Oidc callback",
        "operationId": "oidc_callback",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "error",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "error_description",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect back to the application after OIDC login"
          }
        }
      }
    },
    "/api/auth/store_state": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Store oidc state",
        "operationId": "store_oidc_state",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StoreStateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/data/add_category": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add category",
        "operationId": "add_category",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddCategoryData"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_custom_podcast": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add custom podcast",
        "operationId": "add_custom_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_gpodder_server": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add gpodder server",
        "operationId": "add_gpodder_server",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddGpodderServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_local_podcast": {
      "post": {
        "tags": [
          "local"
        ],
        "summary": "Add local podcast",
        "operationId": "add_local_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddLocalPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_local_podcast_artwork": {
      "post": {
        "tags": [
          "local"
        ],
        "summary": "Add local podcast artwork",
        "operationId": "add_local_podcast_artwork",
        "requestBody": {
          "description": "Uploaded file",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "string"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_login_user": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add login user",
        "operationId": "add_login_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddUserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_nextcloud_server": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add nextcloud server",
        "operationId": "add_nextcloud_server",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddNextcloudServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_oidc_provider": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add oidc provider",
        "operationId": "add_oidc_provider",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcProviderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_podcast": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Add podcast",
        "operationId": "add_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/add_user": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Add user",
        "operationId": "add_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddUserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_ad_segment_review": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Confirm or deny a detected ad segment (per-user)",
        "operationId": "adjust_ad_segment_review",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdSegmentReviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_ad_skip_auto_activate": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set per-podcast ad-skip auto-activate",
        "operationId": "adjust_ad_skip_auto_activate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdSkipAutoActivateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_auto_ad_detect": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set per-podcast auto-ad-detect",
        "operationId": "adjust_auto_ad_detect",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoAdDetectRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_auto_transcribe": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set per-podcast auto-transcribe",
        "operationId": "adjust_auto_transcribe",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoTranscribeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_silence_trim": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set per-podcast silence-trim (enable + threshold)",
        "operationId": "adjust_silence_trim",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SilenceTrimRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/adjust_skip_times": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Adjust skip times",
        "operationId": "adjust_skip_times",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SkipTimesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/admin_self_service_status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Self service status",
        "operationId": "self_service_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ai_models": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "List models installed in the AI sidecar (admin)",
        "operationId": "get_ai_models",
        "parameters": [
          {
            "name": "remote_url",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          },
          "503": {
            "description": "AI service unavailable"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ai_pull_model": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Pull a model into the AI sidecar (admin)",
        "operationId": "ai_pull_model",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AiPullModelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          },
          "503": {
            "description": "AI service unavailable"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ai_settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get global AI settings (admin)",
        "operationId": "get_ai_settings",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Update global AI settings (admin)",
        "operationId": "update_ai_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AiSettingsUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ai_status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Whether the optional AI sidecar is available",
        "operationId": "ai_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/auto_complete_episodes": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Auto complete episodes",
        "operationId": "auto_complete_episodes",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/backup_server": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Backup server",
        "operationId": "backup_server",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackupServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Backup file download",
            "content": {
              "application/octet-stream": {}
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/backup_user": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Backup user",
        "operationId": "backup_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackupUserRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/bulk_delete_downloaded_episodes": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Bulk delete downloaded episodes",
        "operationId": "bulk_delete_downloaded_episodes",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEpisodeActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEpisodeActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/bulk_download_episodes": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Bulk download episodes",
        "operationId": "bulk_download_episodes",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEpisodeActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEpisodeActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/bulk_mark_episodes_completed": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Bulk mark episodes completed",
        "operationId": "bulk_mark_episodes_completed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEpisodeActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEpisodeActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/bulk_queue_episodes": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Bulk queue episodes",
        "operationId": "bulk_queue_episodes",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEpisodeActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEpisodeActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/bulk_save_episodes": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Bulk save episodes",
        "operationId": "bulk_save_episodes",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkEpisodeActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEpisodeActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/check_episode_in_db/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Check episode in db",
        "operationId": "check_episode_in_db",
        "parameters": [
          {
            "name": "episode_title",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "episode_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EpisodeInDbResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/check_gpodder_settings/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Check gpodder settings",
        "operationId": "check_gpodder_settings",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/check_mfa_enabled/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Check mfa enabled",
        "operationId": "check_mfa_enabled",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/check_podcast": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Check podcast",
        "operationId": "check_podcast",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_name",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "podcast_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckPodcastResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/check_youtube_channel": {
      "get": {
        "tags": [
          "youtube"
        ],
        "summary": "Check youtube channel",
        "operationId": "check_youtube_channel",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "channel_name",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/cleanup_tasks": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Cleanup tasks",
        "operationId": "cleanup_tasks",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/clear_podcast_auto_download_delete_days": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Clear podcast auto-delete downloads days",
        "operationId": "clear_podcast_auto_download_delete_days",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClearAutoDownloadDeleteDaysPodcast"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/clear_podcast_playback_speed": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Clear podcast playback speed",
        "operationId": "clear_podcast_playback_speed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClearPlaybackSpeedPodcast"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/clear_queue": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Clear all queue",
        "operationId": "clear_all_queue",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClearQueueRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collection_add_ui": {
      "get": {
        "tags": [
          "collections"
        ],
        "summary": "Get the collection add-UI preference",
        "operationId": "get_collection_add_ui",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preference",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionAddUiResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "collections"
        ],
        "summary": "Set the collection add-UI preference",
        "operationId": "set_collection_add_ui",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetCollectionAddUiRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot set another user's setting"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/bulk_add": {
      "post": {
        "tags": [
          "collections"
        ],
        "summary": "Add multiple episodes to a collection",
        "operationId": "bulk_add_collection",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkAddCollectionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Episodes added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot modify another user's collection"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/categories/{user_id}": {
      "get": {
        "tags": [
          "collections"
        ],
        "summary": "List the distinct podcast categories across a user's subscriptions",
        "operationId": "get_user_categories",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Categories",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserCategoriesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot list another user's categories"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/create": {
      "post": {
        "tags": [
          "collections"
        ],
        "summary": "Create a collection",
        "operationId": "create_collection",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCollectionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Collection created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateCollectionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot create a collection for another user"
          },
          "409": {
            "description": "A collection with that name already exists"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/user/{user_id}": {
      "get": {
        "tags": [
          "collections"
        ],
        "summary": "List a user's collections",
        "operationId": "list_collections",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collections",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot list another user's collections"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/{collection_id}": {
      "delete": {
        "tags": [
          "collections"
        ],
        "summary": "Delete a collection",
        "operationId": "delete_collection",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Cannot delete the default collection"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot delete another user's collection"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "patch": {
        "tags": [
          "collections"
        ],
        "summary": "Update a collection",
        "operationId": "update_collection",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCollectionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Collection updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Cannot edit the default collection"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot edit another user's collection"
          },
          "409": {
            "description": "A collection with that name already exists"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/{collection_id}/add_episode": {
      "post": {
        "tags": [
          "collections"
        ],
        "summary": "Add an episode to a collection",
        "operationId": "add_episode_to_collection",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Episode added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot modify another user's collection"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/{collection_id}/episodes": {
      "get": {
        "tags": [
          "collections"
        ],
        "summary": "Get a collection's episodes (paginated)",
        "operationId": "get_collection_episodes",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Episodes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedEpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot view another user's collection"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/collections/{collection_id}/remove_episode": {
      "post": {
        "tags": [
          "collections"
        ],
        "summary": "Remove an episode from a collection",
        "operationId": "remove_episode_from_collection",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Episode removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot modify another user's collection"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/config": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get config",
        "operationId": "get_config",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfigResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/create_api_key": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Create api key",
        "operationId": "create_api_key",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/create_first": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Create first admin",
        "operationId": "create_first_admin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFirstAdminRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateFirstAdminResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/create_playlist": {
      "post": {
        "tags": [
          "playlists"
        ],
        "summary": "Create a playlist",
        "operationId": "create_playlist",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlaylistRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Playlist created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePlaylistResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot create a playlist for another user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_api_key": {
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Delete api key",
        "operationId": "delete_api_key",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteApiKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_backup_file": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Delete backup file",
        "operationId": "delete_backup_file",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteBackupFileRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_episode": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Delete episode",
        "operationId": "delete_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_mfa": {
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Delete mfa",
        "operationId": "delete_mfa",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_playlist": {
      "delete": {
        "tags": [
          "playlists"
        ],
        "summary": "Delete a playlist",
        "operationId": "delete_playlist",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeletePlaylistRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Playlist deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletePlaylistResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot delete another user's playlist"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/delete_shared_link": {
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Delete shared link",
        "operationId": "delete_shared_link",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteSharedLinkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/detect_ads": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Detect ads for an episode (AI sidecar)",
        "operationId": "detect_ads",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DetectAdsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "503": {
            "description": "AI service unavailable"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/detect_local_cover": {
      "get": {
        "tags": [
          "local"
        ],
        "summary": "Detect local cover",
        "operationId": "detect_local_cover",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/detect_silence": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Run silence detection for an episode",
        "operationId": "detect_silence",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DetectSilenceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_all_podcast": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Download all podcast",
        "operationId": "download_all_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DownloadAllPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_episode_list": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Download episode list",
        "operationId": "download_episode_list",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadedEpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_metadata_settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get download metadata settings",
        "operationId": "get_download_metadata_settings",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadMetadataSettings"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set download metadata settings",
        "operationId": "set_download_metadata_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DownloadMetadataSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_podcast": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Download podcast",
        "operationId": "download_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DownloadPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Download status",
        "operationId": "download_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "boolean"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/download_status/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Download status",
        "operationId": "podcast_download_status",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/enable_auto_download": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Enable auto download",
        "operationId": "enable_auto_download",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoDownloadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/enable_auto_play_next": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Enable auto play next",
        "operationId": "enable_auto_play_next",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoPlayNextRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/enable_auto_queue": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Enable auto queue",
        "operationId": "enable_auto_queue",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoQueueRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/enable_disable_downloads": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Enable disable downloads",
        "operationId": "enable_disable_downloads",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/enable_disable_self_service": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Enable disable self service",
        "operationId": "enable_disable_self_service",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/episode_by_url/{url_key}": {
      "get": {
        "tags": [
          "episodes"
        ],
        "summary": "Get episode by url key",
        "operationId": "get_episode_by_url_key",
        "parameters": [
          {
            "name": "url_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/data/episode_collections/{user_id}/{episode_id}": {
      "get": {
        "tags": [
          "collections"
        ],
        "summary": "Which collections contain this episode",
        "operationId": "get_episode_collections",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "episode_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "is_youtube",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection IDs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EpisodeCollectionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot access another user's collections"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/episode_skip_segments": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get auto-skip segments for an episode",
        "operationId": "get_episode_skip_segments",
        "parameters": [
          {
            "name": "episode_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/episode_transcript": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get the stored (generated) transcript for an episode",
        "operationId": "get_episode_transcript",
        "parameters": [
          {
            "name": "episode_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/extend_shared_link": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Extend shared link",
        "operationId": "extend_shared_link",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtendSharedLinkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/feed_problems": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Feeds that keep failing",
        "description": "The caller's podcasts whose last refresh failed (with the kind of error) and feeds a sync app subscribed to that couldn't be added.",
        "operationId": "get_feed_problems",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedProblems"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/feed_problems/imports/{id}": {
      "delete": {
        "tags": [
          "podcasts"
        ],
        "summary": "Dismiss a failed sync import",
        "description": "Forgets the failed import without unsubscribing: the feed stays subscribed in the sync apps.",
        "operationId": "dismiss_import",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such failed import"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/feed_problems/imports/{id}/remove": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Unsubscribe from a feed that couldn't be added",
        "description": "Forgets the failed import and records an unsubscribe, so sync apps and the external sync server drop the feed too.",
        "operationId": "remove_import",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such failed import"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/feed_problems/imports/{id}/retry": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Try adding a failed sync import again",
        "description": "Starts the import now (also after Pinepods stopped retrying). It shows in the activity panel.",
        "operationId": "retry_import",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such failed import"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/feed_problems/{podcast_id}/refresh": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Refresh a failing podcast now",
        "description": "Refreshes one of the caller's podcasts straight away and returns its state afterwards: absent from `feeds` when it worked.",
        "operationId": "refresh_failing_feed",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedProblems"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such podcast"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/fetch_podcast_feed": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Fetch podcast feed",
        "operationId": "fetch_podcast_feed",
        "parameters": [
          {
            "name": "podcast_feed",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/fetch_podcasting_2_data": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Fetch podcasting 2 data",
        "operationId": "fetch_podcasting_2_data",
        "parameters": [
          {
            "name": "episode_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/fetch_podcasting_2_pod_data": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Fetch podcasting 2 pod data",
        "operationId": "fetch_podcasting_2_pod_data",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/fetch_transcript": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Fetch transcript",
        "operationId": "fetch_transcript",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FetchTranscriptRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/first_login_done/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "First login done",
        "operationId": "first_login_done",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/generate_mfa_secret/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Generate mfa secret",
        "operationId": "generate_mfa_secret",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_ad_skip_auto_activate": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get per-podcast ad-skip auto-activate setting",
        "operationId": "get_ad_skip_auto_activate",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_api_info/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get api info",
        "operationId": "get_api_info",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_ad_detect": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get per-podcast auto-ad-detect setting",
        "operationId": "get_auto_ad_detect",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_complete_seconds/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get auto complete seconds",
        "operationId": "get_auto_complete_seconds",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_download_delete_days": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get auto-delete downloads days",
        "operationId": "get_auto_download_delete_days",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetAutoDownloadDeleteDaysRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_download_status": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get auto download status",
        "operationId": "get_auto_download_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoDownloadStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoDownloadStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_play_next_status": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get auto play next status",
        "operationId": "get_auto_play_next_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoPlayNextStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoPlayNextStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_queue_status": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get auto queue status",
        "operationId": "get_auto_queue_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoQueueStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoQueueStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_auto_transcribe": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get per-podcast auto-transcribe setting",
        "operationId": "get_auto_transcribe",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_available_languages": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get available languages",
        "operationId": "get_available_languages",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailableLanguagesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/get_default_volume": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get default volume",
        "operationId": "get_default_volume",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetDefaultVolumeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_email_settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get email settings",
        "operationId": "get_email_settings",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailSettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_episode_id_ep_name": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get episode id ep name",
        "operationId": "get_episode_id_ep_name",
        "parameters": [
          {
            "name": "episode_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_episode_metadata": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get episode metadata",
        "operationId": "get_episode_metadata",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EpisodeMetadataRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_extended_stats": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get extended stats",
        "operationId": "get_extended_stats",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_feed_cutoff_days": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get feed cutoff days",
        "operationId": "get_feed_cutoff_days",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedCutoffDaysResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_gpodder_settings/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get gpodder settings",
        "operationId": "get_gpodder_settings",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_ignored_podcasts": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Get ignored podcasts",
        "operationId": "get_ignored_podcasts",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetIgnoredPodcastsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_key": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get key",
        "operationId": "get_key",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/get_next_playlist_episode": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get next playlist episode",
        "operationId": "get_next_playlist_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NextPlaylistEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedEpisode"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_next_podcast_episode": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get next podcast episode",
        "operationId": "get_next_podcast_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NextPodcastEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedEpisode"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_pinepods_version": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get pinepods version",
        "operationId": "get_pinepods_version",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_play_episode_details": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get play episode details",
        "operationId": "get_play_episode_details",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlayEpisodeDetailsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlayEpisodeDetailsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_playback_speed": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get playback speed",
        "operationId": "get_playback_speed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetPlaybackSpeedRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_playlist_episodes": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get playlist episodes",
        "operationId": "get_playlist_episodes",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "playlist_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_playlists": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get playlists",
        "operationId": "get_playlists",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_podcast_details": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast details",
        "operationId": "get_podcast_details",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_podcast_details_dynamic": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast details dynamic",
        "operationId": "get_podcast_details_dynamic",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_title",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "podcast_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "podcast_index_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "added",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "display_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClickedFeedURLResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_podcast_id": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast id",
        "operationId": "get_podcast_id",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_feed",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "podcast_title",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_podcast_id_from_ep_id": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast id from ep id",
        "operationId": "get_podcast_id_from_ep_id",
        "parameters": [
          {
            "name": "episode_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "is_youtube",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_podcast_id_from_ep_name": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast id from ep name",
        "operationId": "get_podcast_id_from_ep_name",
        "parameters": [
          {
            "name": "episode_name",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "episode_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_queued_episodes": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get queued episodes",
        "operationId": "get_queued_episodes",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedEpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_rss_key": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get rss key",
        "operationId": "get_rss_key",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_scheduled_backup": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Get scheduled backup",
        "operationId": "get_scheduled_backup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetScheduledBackupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_server_default_language": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get server default language",
        "operationId": "get_server_default_language",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/data/get_silence_trim": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get per-podcast silence-trim settings",
        "operationId": "get_silence_trim",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_stats": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get stats",
        "operationId": "get_stats",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_theme/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get theme",
        "operationId": "get_theme",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_time_info": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get time info",
        "operationId": "get_time_info",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimeInfoResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_unmatched_podcasts": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Get unmatched podcasts",
        "operationId": "get_unmatched_podcasts",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GetUnmatchedPodcastsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_user": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get user",
        "operationId": "get_user",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetUserResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_user_info": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get user info",
        "operationId": "get_user_info",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserInfo"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_user_language": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get user language",
        "operationId": "get_user_language",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserLanguageResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/get_user_shared_links/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get user shared links",
        "operationId": "get_user_shared_links",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/gpodder/status": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder status",
        "operationId": "gpodder_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/gpodder/toggle": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder toggle",
        "operationId": "gpodder_toggle",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateGpodderSyncRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/home_overview": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Home overview",
        "operationId": "home_overview",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ignore_podcast_index_id": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Ignore podcast index id",
        "operationId": "ignore_podcast_index_id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IgnorePodcastIndexIdRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/import_opml": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Import opml",
        "operationId": "import_opml",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OPMLImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/import_progress/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Import progress",
        "operationId": "import_progress",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/increment_listen_time/{user_id}": {
      "put": {
        "tags": [
          "podcasts"
        ],
        "summary": "Increment listen time",
        "operationId": "increment_listen_time",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/increment_played/{user_id}": {
      "put": {
        "tags": [
          "podcasts"
        ],
        "summary": "Increment played",
        "operationId": "increment_played",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/initiate_nextcloud_login": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Initiate nextcloud login",
        "operationId": "initiate_nextcloud_login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiateNextcloudLoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/list_backup_files": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "List backup files",
        "operationId": "list_backup_files",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ListBackupFilesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/list_local_directories": {
      "get": {
        "tags": [
          "local"
        ],
        "summary": "List local directories",
        "operationId": "list_local_directories",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/list_oidc_providers": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "List oidc providers",
        "operationId": "list_oidc_providers",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/manual_backup_to_directory": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Manual backup to directory",
        "operationId": "manual_backup_to_directory",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualBackupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/mark_episode_completed": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Mark episode completed",
        "operationId": "mark_episode_completed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarkEpisodeCompletedRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/mark_episode_uncompleted": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Mark episode uncompleted",
        "operationId": "mark_episode_uncompleted",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarkEpisodeUncompletedRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/my_user_info/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get my user info",
        "operationId": "get_my_user_info",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/notifications": {
      "get": {
        "tags": [
          "notifications"
        ],
        "summary": "List the user's live durable notifications (messages/alerts). Expired ones are\ndropped server-side. Powers the Activity center on load and as a WS fallback.",
        "operationId": "list_notifications",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The user's notifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InAppNotification"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not authorized for this user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/notifications/clear": {
      "post": {
        "tags": [
          "notifications"
        ],
        "summary": "Clear all (or all read) notifications for the user.",
        "operationId": "clear_notifications",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "read_only",
            "in": "query",
            "description": "When true, only already-read notifications are removed.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cleared"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not authorized for this user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/notifications/{id}/dismiss": {
      "post": {
        "tags": [
          "notifications"
        ],
        "summary": "Dismiss (delete) one notification.",
        "operationId": "dismiss_notification",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dismissed"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not authorized for this user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/notifications/{id}/read": {
      "post": {
        "tags": [
          "notifications"
        ],
        "summary": "Mark one notification read.",
        "operationId": "mark_notification_read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Marked read"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not authorized for this user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/now_playing_devices": {
      "get": {
        "tags": [
          "nowplaying"
        ],
        "summary": "List the user's active devices and what each is currently playing. Backed by\nephemeral Valkey snapshots with a TTL, so a device that stops reporting drops\noff automatically. Powers the \"see / control my other devices\" UI for clients\nthat aren't holding a live socket.",
        "operationId": "now_playing_devices",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active devices and their now-playing state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NowPlayingDevicesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not authorized for this user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/contribute": {
      "post": {
        "tags": [
          "people"
        ],
        "summary": "Add people to a podcast or episode",
        "operationId": "contribute_people",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Everyone on the podcast or episode afterwards",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CreditedPerson"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected (PodPeopleDB's reason is in the message)"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "Not one of your podcasts"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/episode/{episode_id}": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "People on an episode",
        "operationId": "episode_people",
        "parameters": [
          {
            "name": "episode_id",
            "in": "path",
            "description": "Your episode id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The episode's own credits plus the show's regulars",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CreditedPerson"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "Not one of your episodes"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/followed": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "Followed people",
        "operationId": "followed_people",
        "responses": {
          "200": {
            "description": "People",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Person"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/lookup": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "Find a person id",
        "operationId": "lookup_person",
        "parameters": [
          {
            "name": "podpeople_id",
            "in": "query",
            "description": "A PodPeopleDB person id (from search results).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Or a name.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`{ \"person_id\": 12 }`",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such person"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/podcast/{podcast_id}": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "People on a podcast",
        "operationId": "podcast_people",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "path",
            "description": "Your podcast id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Regulars in `people`, episode-only credits in `guests`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastCredits"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "Not one of your podcasts"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/search": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "Search people",
        "operationId": "search_people",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matches",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PersonHit"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/{person_id}": {
      "get": {
        "tags": [
          "people"
        ],
        "summary": "Person profile",
        "operationId": "person_profile",
        "parameters": [
          {
            "name": "person_id",
            "in": "path",
            "description": "PinePods person id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Library episodes per page (default 50, max 200).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonProfile"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "Unknown person"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/people/{person_id}/follow": {
      "post": {
        "tags": [
          "people"
        ],
        "summary": "Follow a person",
        "operationId": "follow_person",
        "parameters": [
          {
            "name": "person_id",
            "in": "path",
            "description": "PinePods person id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Following",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "Unknown person"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "delete": {
        "tags": [
          "people"
        ],
        "summary": "Unfollow a person",
        "operationId": "unfollow_person",
        "parameters": [
          {
            "name": "person_id",
            "in": "path",
            "description": "PinePods person id",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Not following",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/clear_cover_preference": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Clear podcast cover preference",
        "operationId": "clear_podcast_cover_preference",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClearPodcastCoverPreference"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/favorite_status": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast favorite status",
        "operationId": "get_podcast_favorite_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PodcastFavoriteStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FavoriteStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/notification_status": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get notification status",
        "operationId": "get_notification_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PodcastNotificationStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/set_auto_download_delete_days": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set podcast auto-delete downloads days",
        "operationId": "set_podcast_auto_download_delete_days",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetAutoDownloadDeleteDaysPodcast"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/set_cover_preference": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set podcast cover preference",
        "operationId": "set_podcast_cover_preference",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetPodcastCoverPreference"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/set_playback_speed": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set podcast playback speed",
        "operationId": "set_podcast_playback_speed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetPlaybackSpeedPodcast"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/toggle_favorite": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Toggle podcast favorite",
        "operationId": "toggle_podcast_favorite",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TogglePodcastFavoriteData"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast/toggle_notifications": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Toggle podcast notifications",
        "operationId": "toggle_podcast_notifications",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TogglePodcastNotificationData"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast_download_summary/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast download summary",
        "operationId": "get_podcast_download_summary",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastDownloadSummaryResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast_downloads_paged/{user_id}/{podcast_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podcast downloads paged",
        "operationId": "get_podcast_downloads_paged",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadedEpisodesPage"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podcast_episodes": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Podcast episodes",
        "operationId": "podcast_episodes",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastEpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/podpeople/discover": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get podpeople discover",
        "operationId": "get_podpeople_discover",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/proxy_categories": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Proxy podcast categories",
        "operationId": "proxy_categories",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/proxy_search": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Proxy search",
        "operationId": "proxy_search",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "index",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Empty search"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "503": {
            "description": "The search service isn't reachable or answered with an error"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/proxy_trending": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Proxy trending podcasts",
        "operationId": "proxy_trending",
        "parameters": [
          {
            "name": "cat",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "notcat",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "max",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/public_oidc_providers": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get public oidc providers",
        "operationId": "get_public_oidc_providers",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOidcProvidersResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/queue_bump": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Move an episode to the top of the queue",
        "operationId": "queue_episode_to_top",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueuePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/queue_pod": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Queue episode",
        "operationId": "queue_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueuePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/recommendations": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Personalized podcast recommendations",
        "operationId": "get_recommendations",
        "parameters": [
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "null"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecommendedPodcast"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/record_listen_duration": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Record listen duration",
        "operationId": "record_listen_duration",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordListenDurationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/record_podcast_history": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Add history",
        "operationId": "add_history",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HistoryAddRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoryResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/refresh_gpodder_subscriptions": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Refresh gpodder subscriptions",
        "operationId": "refresh_gpodder_subscriptions_admin",
        "responses": {
          "200": {
            "description": "Refresh triggered",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/refresh_hosts": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Refresh hosts",
        "operationId": "refresh_hosts",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/refresh_local_podcast": {
      "post": {
        "tags": [
          "local"
        ],
        "summary": "Refresh local podcast",
        "operationId": "refresh_local_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshLocalPodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/refresh_nextcloud_subscriptions": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Refresh Nextcloud subscriptions",
        "operationId": "refresh_nextcloud_subscriptions_admin",
        "responses": {
          "200": {
            "description": "Refresh triggered",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/refresh_pods": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Refresh all podcasts",
        "operationId": "refresh_pods_admin",
        "responses": {
          "200": {
            "description": "Refresh triggered",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_category": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Remove category",
        "operationId": "remove_category",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveCategoryData"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_oidc_provider": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Remove oidc provider",
        "operationId": "remove_oidc_provider",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "integer",
                "format": "int32"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_podcast": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Remove podcast",
        "operationId": "remove_podcast",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemovePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemovePodcastResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_podcast_id": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Remove podcast id",
        "operationId": "remove_podcast_id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemovePodcastIdRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemovePodcastResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_podcast_sync": {
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Remove podcast sync",
        "operationId": "remove_podcast_sync",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveSyncRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_queued_pod": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Remove queued episode",
        "operationId": "remove_queued_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueuePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_saved_episode": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Remove saved episode",
        "operationId": "remove_saved_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaveEpisodeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/remove_youtube_channel": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Remove youtube channel",
        "operationId": "remove_youtube_channel",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveYouTubeChannelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/reorder_queue": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Reorder queue",
        "operationId": "reorder_queue",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderQueueRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReorderQueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/reset_password_create_code": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Reset password create code",
        "operationId": "reset_password_create_code",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetCodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResetCodeResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/restore_backup_file": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Restore from backup file",
        "operationId": "restore_from_backup_file",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreBackupFileRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/restore_server": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Restore server",
        "operationId": "restore_server",
        "requestBody": {
          "description": "Uploaded file",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "string"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/restore_status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Restore status",
        "operationId": "restore_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/data/return_episodes/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Return episodes",
        "operationId": "return_episodes",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/return_pods/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Return pods",
        "operationId": "return_pods",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/return_pods_extra/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Return pods extra",
        "operationId": "return_pods_extra",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PodcastExtraListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/rss_feed_status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Rss feed status",
        "operationId": "rss_feed_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "boolean"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/rss_key": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get user rss key",
        "operationId": "get_user_rss_key",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/save_email_settings": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Save email settings",
        "operationId": "save_email_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveEmailSettingsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/save_episode": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Save episode",
        "operationId": "save_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavePodcastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaveEpisodeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/save_mfa_secret": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Save mfa secret",
        "operationId": "save_mfa_secret",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveMfaSecretRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/saved_episode_list/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get saved episodes",
        "operationId": "get_saved_episodes",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedEpisodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/schedule_backup": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Schedule backup",
        "operationId": "schedule_backup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleBackupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/search_data": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Search data",
        "operationId": "search_data",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchDataRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchDataResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/search_youtube_channels": {
      "get": {
        "tags": [
          "youtube"
        ],
        "summary": "Search youtube channels",
        "operationId": "search_youtube_channels",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_results",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/self_service_status": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get self service status",
        "operationId": "get_self_service_status",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfServiceStatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/send_email": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Send email",
        "operationId": "send_email",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/send_test_email": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Send test email",
        "operationId": "send_test_email",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendTestEmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/set_fullname/{user_id}": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set fullname",
        "operationId": "set_fullname",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/set_password/{user_id}": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set password",
        "operationId": "set_password",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/setup_time_info": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Setup time info",
        "operationId": "setup_time_info",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TimeZoneInfo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/share_episode/{episode_id}": {
      "post": {
        "tags": [
          "episodes"
        ],
        "summary": "Share episode",
        "operationId": "share_episode",
        "parameters": [
          {
            "name": "episode_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/startpage": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get startpage",
        "operationId": "get_startpage",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Update startpage",
        "operationId": "update_startpage",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "startpage",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/stream/{episode_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Stream episode",
        "operationId": "stream_episode",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "episode_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audio/media stream",
            "content": {
              "application/octet-stream": {}
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/toggle_rss_feeds": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Toggle rss feeds",
        "operationId": "toggle_rss_feeds",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/transcribe_episode": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Transcribe an episode (AI sidecar)",
        "operationId": "transcribe_episode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscribeEpisodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "503": {
            "description": "AI service unavailable"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_auto_complete_seconds": {
      "put": {
        "tags": [
          "auth"
        ],
        "summary": "Update auto complete seconds",
        "operationId": "update_auto_complete_seconds",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutoCompleteSecondsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_date_format": {
      "put": {
        "tags": [
          "auth"
        ],
        "summary": "Update date format",
        "operationId": "update_date_format",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDateFormatRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_episode_duration": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Update episode duration",
        "operationId": "update_episode_duration",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateEpisodeDurationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_feed_cutoff_days": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Update feed cutoff days",
        "operationId": "update_feed_cutoff_days",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFeedCutoffDaysData"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_oidc_provider/{provider_id}": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Update oidc provider",
        "operationId": "update_oidc_provider",
        "parameters": [
          {
            "name": "provider_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcProviderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_playlist": {
      "patch": {
        "tags": [
          "playlists"
        ],
        "summary": "Update a playlist",
        "operationId": "update_playlist",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePlaylistRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Playlist updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdatePlaylistResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Cannot edit another user's playlist"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_playlists": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Update playlists",
        "operationId": "update_playlists",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_podcast_index_id": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Update podcast index id",
        "operationId": "update_podcast_index_id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePodcastIndexIdRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_podcast_info": {
      "put": {
        "tags": [
          "podcasts"
        ],
        "summary": "Update podcast info",
        "operationId": "update_podcast_info",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePodcastInfoRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdatePodcastInfoResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_services": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Search service and Podping status",
        "description": "Admin only. Checks that the search service answers and reports Podping: whether it's on, the relay's state and what this server did with its announcements.",
        "operationId": "get_update_services",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateServices"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not an admin"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_services/podping": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Turn Podping on or off",
        "description": "Admin only. When on, Pinepods reads which feeds Podping announced from the relay and refreshes the ones it has right away. Only announcements are fetched; what this server subscribes to is never sent.",
        "operationId": "set_podping",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetPodping"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateServices"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not an admin"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_time_format": {
      "put": {
        "tags": [
          "auth"
        ],
        "summary": "Update time format",
        "operationId": "update_time_format",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTimeFormatRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_timezone": {
      "put": {
        "tags": [
          "auth"
        ],
        "summary": "Update timezone",
        "operationId": "update_timezone",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTimezoneRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_user_language": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Update user language",
        "operationId": "update_user_language",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LanguageUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/update_youtube_video_filter": {
      "post": {
        "tags": [
          "youtube"
        ],
        "summary": "Set a channel's video filter",
        "operationId": "update_youtube_video_filter",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateYouTubeVideoFilterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The filter as stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/YouTubeVideoFilter"
                }
              }
            }
          },
          "400": {
            "description": "Negative lengths, shortest longer than longest, or title filter too long"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not your podcast"
          },
          "404": {
            "description": "No such YouTube channel"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/custom_themes": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Create custom theme",
        "operationId": "create_custom_theme",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomThemeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Delete custom theme",
        "operationId": "delete_custom_theme",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteCustomThemeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/custom_themes/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get custom themes",
        "operationId": "get_custom_themes",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/delete/{user_id}": {
      "delete": {
        "tags": [
          "settings"
        ],
        "summary": "Delete user",
        "operationId": "delete_user",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/final_admin/{user_id}": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Final admin",
        "operationId": "final_admin",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/get_podcast_cover_preference": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get global podcast cover preference",
        "operationId": "get_global_podcast_cover_preference",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/notification_settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get notification settings",
        "operationId": "get_notification_settings",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Update notification settings",
        "operationId": "update_notification_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NotificationSettingsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_auto_download_delete_days": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set auto-delete downloads days (user default)",
        "operationId": "set_auto_download_delete_days_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetAutoDownloadDeleteDaysUser"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_default_volume": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set default volume (user default)",
        "operationId": "set_default_volume_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetDefaultVolumeUser"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_email": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set email",
        "operationId": "set_email",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetEmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_global_podcast_cover_preference": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set global podcast cover preference",
        "operationId": "set_global_podcast_cover_preference",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetGlobalPodcastCoverPreference"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_isadmin": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set isadmin",
        "operationId": "set_isadmin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetIsAdminRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_playback_speed": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Set playback speed user",
        "operationId": "set_playback_speed_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetPlaybackSpeedUser"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_theme": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set theme",
        "operationId": "set_theme",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetThemeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/set_username": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Set username",
        "operationId": "set_username",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetUsernameRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user/test_notification": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Test notification",
        "operationId": "test_notification",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NotificationTestRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user_admin_check/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "User admin check",
        "operationId": "user_admin_check",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user_details_id/{user_id}": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Get user details by id",
        "operationId": "get_user_details_by_id",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetails"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/user_history/{user_id}": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "User history",
        "operationId": "user_history",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/verify_and_reset_password": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Verify and reset password",
        "operationId": "verify_and_reset_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyAndResetPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyAndResetPasswordResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/verify_gpodder_auth": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Verify gpodder auth",
        "operationId": "verify_gpodder_auth",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyGpodderAuthRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/verify_key": {
      "get": {
        "tags": [
          "auth"
        ],
        "summary": "Verify api key endpoint",
        "operationId": "verify_api_key_endpoint",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyKeyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/verify_mfa": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Verify mfa",
        "operationId": "verify_mfa",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyMfaRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/verify_mfa_and_get_key": {
      "post": {
        "tags": [
          "auth"
        ],
        "summary": "Verify mfa and get key",
        "operationId": "verify_mfa_and_get_key",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyMfaLoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyMfaLoginResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/data/verify_temp_mfa": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Verify temp mfa",
        "operationId": "verify_temp_mfa",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyTempMfaRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/youtube/subscribe": {
      "post": {
        "tags": [
          "youtube"
        ],
        "summary": "Subscribe to youtube channel",
        "operationId": "subscribe_to_youtube_channel",
        "parameters": [
          {
            "name": "channel_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "feed_cutoff",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/youtube_episodes": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Youtube episodes",
        "operationId": "youtube_episodes",
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/youtube_video_filter": {
      "get": {
        "tags": [
          "youtube"
        ],
        "summary": "Get a channel's video filter",
        "operationId": "get_youtube_video_filter",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The filter; unset fields mean no limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/YouTubeVideoFilter"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Not your podcast"
          },
          "404": {
            "description": "No such YouTube channel"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ytdlp_settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get yt-dlp management settings + current version (admin)",
        "operationId": "get_ytdlp_settings",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Update yt-dlp management settings (admin)",
        "operationId": "update_ytdlp_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/YtDlpSettingsUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/ytdlp_update": {
      "post": {
        "tags": [
          "settings"
        ],
        "summary": "Trigger an immediate yt-dlp self-update (admin)",
        "operationId": "trigger_ytdlp_update",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Admin access required"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/{podcast_id}/merge": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Merge podcasts",
        "operationId": "merge_podcasts",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MergePodcastsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MergePodcastsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/{podcast_id}/merged": {
      "get": {
        "tags": [
          "podcasts"
        ],
        "summary": "Get merged podcasts",
        "operationId": "get_merged_podcasts",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MergedPodcastsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/data/{podcast_id}/unmerge/{target_podcast_id}": {
      "post": {
        "tags": [
          "podcasts"
        ],
        "summary": "Unmerge podcast",
        "operationId": "unmerge_podcast",
        "parameters": [
          {
            "name": "podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "target_podcast_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnmergePodcastResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/episodes/{episode_id}/download": {
      "get": {
        "tags": [
          "episodes"
        ],
        "summary": "Download an episode media file",
        "operationId": "download_episode_file",
        "parameters": [
          {
            "name": "episode_id",
            "in": "path",
            "description": "Episode ID to download",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "api_key",
            "in": "query",
            "description": "API key (alternative to the Api-Key header)",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Episode media file stream",
            "content": {
              "application/octet-stream": {}
            }
          },
          "401": {
            "description": "API key is required or invalid"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/feed/{user_id}": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "Get user feed",
        "operationId": "get_user_feed",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          },
          {
            "name": "podcast_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "source",
            "in": "query",
            "description": "Which collection to build the feed from. Absent = all subscriptions (default).\nOne of: saved, queue, playlist, collection, downloads, history.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "description": "Playlist or collection id (required when `source` is `playlist` or `collection`).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int32"
            }
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "RSS feed XML",
            "content": {
              "application/rss+xml": {}
            }
          }
        }
      }
    },
    "/api/gpodder/default_device": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder get default device",
        "operationId": "gpodder_get_default_device",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/devices": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder get all devices",
        "operationId": "gpodder_get_all_devices",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder create device",
        "operationId": "gpodder_create_device",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDeviceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/devices/{user_id}": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder get user devices",
        "operationId": "gpodder_get_user_devices",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/gpodder_statistics": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder get statistics",
        "operationId": "gpodder_get_statistics",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GpodderStatistics"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/set_default/{device_id}": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder set default (no longer has an effect)",
        "operationId": "gpodder_set_default",
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/sync": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder sync",
        "operationId": "gpodder_sync",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/sync/force": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder force sync",
        "operationId": "gpodder_force_sync",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/gpodder/test-connection": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Gpodder test connection",
        "operationId": "gpodder_test_connection",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Health check endpoint with database and Redis status\nGET /api/health",
        "operationId": "health_check",
        "responses": {
          "200": {
            "description": "Database and Redis connectivity status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "500": {
            "description": "Service is unhealthy"
          }
        }
      }
    },
    "/api/init/startup_tasks": {
      "post": {
        "tags": [
          "tasks"
        ],
        "summary": "Startup tasks",
        "operationId": "startup_tasks",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/pinepods_check": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "PinePods instance check endpoint - matches Python API exactly\nGET /api/pinepods_check",
        "operationId": "pinepods_check",
        "responses": {
          "200": {
            "description": "Confirms this is a PinePods instance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PinepodsCheckResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/proxy/image": {
      "get": {
        "tags": [
          "proxy"
        ],
        "summary": "Proxy image",
        "operationId": "proxy_image",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Proxied image bytes",
            "content": {
              "application/octet-stream": {}
            }
          }
        }
      }
    },
    "/api/sync/devices": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Devices on the PinePods gpodder server",
        "operationId": "list_devices",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SyncDeviceEntry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/devices/{device_id}": {
      "put": {
        "tags": [
          "sync"
        ],
        "summary": "Rename a device",
        "operationId": "rename_device",
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameDeviceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Empty or too long name"
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "PinePods' own device"
          },
          "404": {
            "description": "No such device"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "delete": {
        "tags": [
          "sync"
        ],
        "summary": "Remove a device",
        "description": "Removes an app's device. Its history stays; the app gets a new device the next time it syncs.",
        "operationId": "remove_device",
        "parameters": [
          {
            "name": "device_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "PinePods' own device"
          },
          "404": {
            "description": "No such device"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/notice": {
      "delete": {
        "tags": [
          "sync"
        ],
        "summary": "Dismiss the sync settings notice",
        "operationId": "dismiss_notice",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/run": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Sync with the external server now",
        "operationId": "run_sync",
        "parameters": [
          {
            "name": "full",
            "in": "query",
            "description": "Full sync: pull everything again and send the whole library and listening state.",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The run finished (see success)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunResponse"
                }
              }
            }
          },
          "400": {
            "description": "No external sync server is set up"
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/server": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "PinePods gpodder server settings",
        "operationId": "get_server",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncServerInfo"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "put": {
        "tags": [
          "sync"
        ],
        "summary": "Turn the PinePods gpodder server on or off",
        "operationId": "put_server",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncServerInfo"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/server/app-passwords": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "List app passwords",
        "operationId": "list_app_passwords",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AppPasswordEntry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Create an app password",
        "description": "Creates a password for a gpodder app. The password is in this response only.",
        "operationId": "create_app_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAppPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedAppPassword"
                }
              }
            }
          },
          "400": {
            "description": "Label too long"
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/server/app-passwords/{app_password_id}": {
      "delete": {
        "tags": [
          "sync"
        ],
        "summary": "Revoke an app password",
        "operationId": "revoke_app_password",
        "parameters": [
          {
            "name": "app_password_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "404": {
            "description": "No such app password"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/stats": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "Sync statistics",
        "description": "Read from the sync log; no server is contacted.",
        "operationId": "sync_stats",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncStats"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/target": {
      "get": {
        "tags": [
          "sync"
        ],
        "summary": "External sync server and its status",
        "operationId": "get_target",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncTargetResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "put": {
        "tags": [
          "sync"
        ],
        "summary": "Set up the external sync server",
        "operationId": "put_target",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TargetCredentials"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Saved; the first sync is running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaveTargetResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid fields, or the server refused the credentials"
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "delete": {
        "tags": [
          "sync"
        ],
        "summary": "Remove the external sync server",
        "operationId": "delete_target",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/sync/target/test": {
      "post": {
        "tags": [
          "sync"
        ],
        "summary": "Test an external sync server",
        "description": "Signs in with the given credentials (gpodder: and lists the devices) without saving anything or creating a device.",
        "operationId": "test_target",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TargetCredentials"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Result of the test",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestTargetResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid fields"
          },
          "401": {
            "description": "Invalid or missing API key"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/tasks/active": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Get active tasks",
        "operationId": "get_active_tasks",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TaskInfo"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "API key does not belong to the requested user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/tasks/user/{user_id}": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Get user tasks",
        "operationId": "get_user_tasks",
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TaskInfo"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "API key does not belong to the requested user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/api/tasks/{task_id}": {
      "get": {
        "tags": [
          "tasks"
        ],
        "summary": "Get task status",
        "operationId": "get_task_status",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskInfo"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key"
          },
          "403": {
            "description": "Task does not belong to the requesting user"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AdSegmentReviewRequest": {
        "type": "object",
        "required": [
          "segment_id",
          "user_id",
          "status"
        ],
        "properties": {
          "segment_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "AdSkipAutoActivateRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "AddCategoryData": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id",
          "category"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "AddGpodderServerRequest": {
        "type": "object",
        "required": [
          "gpodder_url",
          "gpodder_username",
          "gpodder_password"
        ],
        "properties": {
          "gpodder_url": {
            "type": "string"
          },
          "gpodder_username": {
            "type": "string"
          },
          "gpodder_password": {
            "type": "string"
          }
        }
      },
      "AddLocalPodcastRequest": {
        "type": "object",
        "required": [
          "user_id",
          "directory_path",
          "podcast_name"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "directory_path": {
            "type": "string"
          },
          "podcast_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "explicit": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "AddNextcloudServerRequest": {
        "type": "object",
        "required": [
          "user_id",
          "token",
          "poll_endpoint",
          "nextcloud_url"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "token": {
            "type": "string"
          },
          "poll_endpoint": {
            "type": "string"
          },
          "nextcloud_url": {
            "type": "string"
          }
        }
      },
      "AddPodcastRequest": {
        "type": "object",
        "required": [
          "podcast_values"
        ],
        "properties": {
          "podcast_values": {
            "$ref": "#/components/schemas/PodcastValues"
          },
          "podcast_index_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "AddUserRequest": {
        "type": "object",
        "required": [
          "fullname",
          "username",
          "email",
          "hash_pw"
        ],
        "properties": {
          "fullname": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "hash_pw": {
            "type": "string"
          }
        }
      },
      "AiPullModelRequest": {
        "type": "object",
        "required": [
          "kind",
          "model"
        ],
        "properties": {
          "kind": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "repo": {
            "type": [
              "string",
              "null"
            ]
          },
          "filename": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AiSettingsUpdate": {
        "type": "object",
        "description": "Update payload from the settings page. `llm_api_key` is only written when `Some(non-empty)`,\nso leaving the field blank preserves the stored key; `clear_api_key` removes it.",
        "required": [
          "transcription_model",
          "llm_backend"
        ],
        "properties": {
          "transcription_model": {
            "type": "string"
          },
          "llm_backend": {
            "type": "string"
          },
          "llm_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "llm_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "llm_api_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "clear_api_key": {
            "type": "boolean"
          },
          "whisper_device": {
            "type": [
              "string",
              "null"
            ]
          },
          "whisper_compute_type": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AppPasswordEntry": {
        "type": "object",
        "required": [
          "id",
          "label"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "label": {
            "type": "string"
          },
          "created_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_used_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds; null if never used."
          }
        }
      },
      "AutoAdDetectRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "AutoDownloadRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "auto_download",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "auto_download": {
            "type": "boolean"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoDownloadStatusRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoDownloadStatusResponse": {
        "type": "object",
        "required": [
          "auto_download"
        ],
        "properties": {
          "auto_download": {
            "type": "boolean"
          }
        }
      },
      "AutoPlayNextRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "auto_play_next",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "auto_play_next": {
            "type": "boolean"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoPlayNextStatusRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoPlayNextStatusResponse": {
        "type": "object",
        "required": [
          "auto_play_next"
        ],
        "properties": {
          "auto_play_next": {
            "type": "boolean"
          }
        }
      },
      "AutoQueueRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "auto_queue",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "auto_queue": {
            "type": "boolean"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoQueueStatusRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AutoQueueStatusResponse": {
        "type": "object",
        "required": [
          "auto_queue"
        ],
        "properties": {
          "auto_queue": {
            "type": "boolean"
          }
        }
      },
      "AutoTranscribeRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "AvailableLanguage": {
        "type": "object",
        "required": [
          "code",
          "name"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "AvailableLanguagesResponse": {
        "type": "object",
        "required": [
          "languages"
        ],
        "properties": {
          "languages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AvailableLanguage"
            }
          }
        }
      },
      "BackupServerRequest": {
        "type": "object",
        "required": [
          "database_pass"
        ],
        "properties": {
          "database_pass": {
            "type": "string"
          }
        }
      },
      "BackupUserRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "BulkAddCollectionRequest": {
        "type": "object",
        "required": [
          "user_id",
          "collection_id",
          "episodes"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "collection_id": {
            "type": "integer",
            "format": "int32"
          },
          "episodes": {
            "type": "array",
            "items": {
              "type": "array",
              "items": false,
              "prefixItems": [
                {
                  "type": "integer",
                  "format": "int32"
                },
                {
                  "type": "boolean"
                }
              ]
            },
            "description": "Each entry is (episode_id, is_youtube)"
          }
        }
      },
      "BulkEpisodeActionRequest": {
        "type": "object",
        "required": [
          "episode_ids",
          "user_id"
        ],
        "properties": {
          "episode_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "BulkEpisodeActionResponse": {
        "type": "object",
        "required": [
          "message",
          "processed_count"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "processed_count": {
            "type": "integer",
            "format": "int32"
          },
          "failed_count": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "CheckPodcastResponse": {
        "type": "object",
        "required": [
          "exists"
        ],
        "properties": {
          "exists": {
            "type": "boolean"
          }
        }
      },
      "ClearAutoDownloadDeleteDaysPodcast": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ClearPlaybackSpeedPodcast": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ClearPodcastCoverPreference": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ClearQueueRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ClickedFeedURLResponse": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "feedurl",
          "description",
          "author",
          "artworkurl",
          "explicit",
          "episodecount",
          "categories",
          "websiteurl",
          "podcastindexid"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "feedurl": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "artworkurl": {
            "type": "string"
          },
          "explicit": {
            "type": "boolean"
          },
          "episodecount": {
            "type": "integer",
            "format": "int32"
          },
          "categories": {},
          "websiteurl": {
            "type": "string"
          },
          "podcastindexid": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "ClientStatus": {
        "type": "object",
        "description": "What this server's Podping client has done, for the admin settings.",
        "required": [
          "pings_seen",
          "feeds_refreshed"
        ],
        "properties": {
          "last_poll_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_success_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "pings_seen": {
            "type": "integer",
            "format": "int64",
            "description": "Announcements seen since this server started.",
            "minimum": 0
          },
          "feeds_refreshed": {
            "type": "integer",
            "format": "int64",
            "description": "Feeds refreshed because of one.",
            "minimum": 0
          },
          "last_refresh_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "Collection": {
        "type": "object",
        "required": [
          "collection_id",
          "user_id",
          "name",
          "is_default",
          "icon",
          "created_at",
          "last_updated",
          "episode_count"
        ],
        "properties": {
          "collection_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_default": {
            "type": "boolean"
          },
          "icon": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "last_updated": {
            "type": "string"
          },
          "episode_count": {
            "type": "integer",
            "format": "int64"
          },
          "auto_add_categories": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Podcast categories whose episodes are auto-added to this collection (None = disabled)."
          }
        }
      },
      "CollectionAddUiResponse": {
        "type": "object",
        "required": [
          "collection_add_ui"
        ],
        "properties": {
          "collection_add_ui": {
            "type": "string"
          }
        }
      },
      "CollectionDetailResponse": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          }
        }
      },
      "CollectionEpisodeRequest": {
        "type": "object",
        "required": [
          "user_id",
          "episode_id",
          "is_youtube"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "CollectionsResponse": {
        "type": "object",
        "required": [
          "collections"
        ],
        "properties": {
          "collections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Collection"
            }
          }
        }
      },
      "ConfigResponse": {
        "type": "object",
        "required": [
          "api_url",
          "proxy_url",
          "proxy_host",
          "proxy_port",
          "proxy_protocol",
          "reverse_proxy",
          "people_url"
        ],
        "properties": {
          "api_url": {
            "type": "string"
          },
          "proxy_url": {
            "type": "string"
          },
          "proxy_host": {
            "type": "string"
          },
          "proxy_port": {
            "type": "string"
          },
          "proxy_protocol": {
            "type": "string"
          },
          "reverse_proxy": {
            "type": "string"
          },
          "people_url": {
            "type": "string"
          }
        }
      },
      "ContributePerson": {
        "type": "object",
        "properties": {
          "person_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "A person PinePods already knows (from a credit or search result)."
          },
          "podpeople_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "A PodPeopleDB person (from search results)."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Or just a name."
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "Defaults to \"host\" on a podcast and \"guest\" on an episode."
          }
        }
      },
      "ContributeRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "people"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "episode_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Credit these people on one episode instead of the whole show."
          },
          "people": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContributePerson"
            }
          }
        }
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "required": [
          "user_id",
          "rssonly"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "rssonly": {
            "type": "boolean"
          },
          "podcast_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "CreateAppPasswordRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "What it's for, e.g. \"AntennaPod on my phone\"."
          }
        }
      },
      "CreateCollectionRequest": {
        "type": "object",
        "required": [
          "user_id",
          "name"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          },
          "auto_add_categories": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Podcast categories to auto-add episodes from (None/empty = disabled)."
          },
          "backfill": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "When true, immediately backfill existing matching episodes after saving."
          }
        }
      },
      "CreateCollectionResponse": {
        "type": "object",
        "required": [
          "detail",
          "collection_id"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "collection_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CreateCustomThemeRequest": {
        "type": "object",
        "required": [
          "user_id",
          "name",
          "background_color",
          "button_color",
          "container_button_color",
          "button_text_color",
          "text_color",
          "text_secondary_color",
          "border_color",
          "accent_color",
          "prog_bar_color",
          "error_color",
          "bonus_color",
          "secondary_background",
          "container_background",
          "standout_color",
          "hover_color",
          "link_color",
          "thumb_color",
          "unfilled_color",
          "check_box_color"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "background_color": {
            "type": "string"
          },
          "button_color": {
            "type": "string"
          },
          "container_button_color": {
            "type": "string"
          },
          "button_text_color": {
            "type": "string"
          },
          "text_color": {
            "type": "string"
          },
          "text_secondary_color": {
            "type": "string"
          },
          "border_color": {
            "type": "string"
          },
          "accent_color": {
            "type": "string"
          },
          "prog_bar_color": {
            "type": "string"
          },
          "error_color": {
            "type": "string"
          },
          "bonus_color": {
            "type": "string"
          },
          "secondary_background": {
            "type": "string"
          },
          "container_background": {
            "type": "string"
          },
          "standout_color": {
            "type": "string"
          },
          "hover_color": {
            "type": "string"
          },
          "link_color": {
            "type": "string"
          },
          "thumb_color": {
            "type": "string"
          },
          "unfilled_color": {
            "type": "string"
          },
          "check_box_color": {
            "type": "string"
          }
        }
      },
      "CreateDeviceRequest": {
        "type": "object",
        "required": [
          "device_name",
          "device_type"
        ],
        "properties": {
          "device_name": {
            "type": "string"
          },
          "device_type": {
            "type": "string"
          },
          "device_caption": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateFirstAdminRequest": {
        "type": "object",
        "required": [
          "username",
          "password",
          "email",
          "fullname"
        ],
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "fullname": {
            "type": "string"
          }
        }
      },
      "CreateFirstAdminResponse": {
        "type": "object",
        "required": [
          "message",
          "user_id"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CreatePlaylistRequest": {
        "type": "object",
        "required": [
          "user_id",
          "name",
          "include_unplayed",
          "include_partially_played",
          "include_played",
          "sort_order",
          "group_by_podcast",
          "icon_name"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "include_unplayed": {
            "type": "boolean"
          },
          "include_partially_played": {
            "type": "boolean"
          },
          "include_played": {
            "type": "boolean"
          },
          "play_progress_min": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "play_progress_max": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "time_filter_hours": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "min_duration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Minimum episode length in **minutes** (stored, and returned by get_playlists, in seconds)."
          },
          "max_duration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Maximum episode length in **minutes** (stored, and returned by get_playlists, in seconds)."
          },
          "sort_order": {
            "type": "string",
            "description": "One of date_asc, date_desc, duration_asc, duration_desc, listen_progress, completion.",
            "example": "date_desc"
          },
          "group_by_podcast": {
            "type": "boolean"
          },
          "max_episodes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "icon_name": {
            "type": "string"
          }
        }
      },
      "CreatePlaylistResponse": {
        "type": "object",
        "required": [
          "detail",
          "playlist_id"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "playlist_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "CreatedAppPassword": {
        "type": "object",
        "required": [
          "id",
          "label",
          "password"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "label": {
            "type": "string"
          },
          "password": {
            "type": "string",
            "description": "Shown this once; only a hash is stored."
          }
        }
      },
      "CreditedPerson": {
        "type": "object",
        "description": "A person as shown on a podcast or episode page.",
        "required": [
          "id",
          "name",
          "role",
          "roles",
          "scope",
          "episode_count",
          "sources",
          "verified",
          "followed"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "PinePods person id (`Persons.PersonID`); use it for the person page and follows."
          },
          "podpeople_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "img": {
            "type": [
              "string",
              "null"
            ]
          },
          "href": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "description": "Most significant role (\"host\", \"co-host\", \"guest\", ...)."
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every role this person has here, most significant first."
          },
          "group": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope": {
            "type": "string",
            "description": "\"podcast\": credited on the show itself or a regular across its episodes.\n\"episodes\": credited only on some episodes. \"episode\": credited on this episode."
          },
          "episode_count": {
            "type": "integer",
            "format": "int64",
            "description": "Episodes of this podcast the person is credited on."
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "\"feed\" and/or \"podpeople\"."
          },
          "verified": {
            "type": "boolean",
            "description": "False when every credit is an unreviewed community submission."
          },
          "followed": {
            "type": "boolean"
          }
        }
      },
      "CustomPodcastRequest": {
        "type": "object",
        "required": [
          "feed_url",
          "user_id"
        ],
        "properties": {
          "feed_url": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          },
          "password": {
            "type": [
              "string",
              "null"
            ]
          },
          "youtube_channel": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "feed_cutoff": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "DeleteApiKeyRequest": {
        "type": "object",
        "required": [
          "api_id"
        ],
        "properties": {
          "api_id": {
            "type": "string"
          }
        }
      },
      "DeleteBackupFileRequest": {
        "type": "object",
        "required": [
          "backup_filename"
        ],
        "properties": {
          "backup_filename": {
            "type": "string"
          }
        }
      },
      "DeleteCustomThemeRequest": {
        "type": "object",
        "required": [
          "user_id",
          "theme_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "theme_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DeleteEpisodeRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "DeletePlaylistRequest": {
        "type": "object",
        "required": [
          "user_id",
          "playlist_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "playlist_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DeletePlaylistResponse": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          }
        }
      },
      "DeleteSharedLinkRequest": {
        "type": "object",
        "required": [
          "share_code"
        ],
        "properties": {
          "share_code": {
            "type": "string"
          }
        }
      },
      "DetectAdsRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "force": {
            "type": "boolean"
          }
        }
      },
      "DetectSilenceRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "force": {
            "type": "boolean"
          }
        }
      },
      "DownloadAllPodcastRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "DownloadMetadataSettings": {
        "type": "object",
        "required": [
          "folder_cover",
          "episode_cover",
          "metadata_sidecar",
          "metadata_format",
          "metadata_subfolder"
        ],
        "properties": {
          "folder_cover": {
            "type": "boolean"
          },
          "episode_cover": {
            "type": "boolean"
          },
          "metadata_sidecar": {
            "type": "boolean"
          },
          "metadata_format": {
            "type": "string"
          },
          "metadata_subfolder": {
            "type": "boolean"
          }
        }
      },
      "DownloadPodcastRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "DownloadedEpisode": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "episodeid",
          "episodetitle",
          "episodepubdate",
          "episodedescription",
          "episodeurl",
          "episodeduration",
          "downloadedlocation",
          "completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube",
          "is_video"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "artworkurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "episodetitle": {
            "type": "string"
          },
          "episodepubdate": {
            "type": "string"
          },
          "episodedescription": {
            "type": "string"
          },
          "episodeartwork": {
            "type": [
              "string",
              "null"
            ]
          },
          "episodeurl": {
            "type": "string"
          },
          "episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "websiteurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "downloadedlocation": {
            "type": "string"
          },
          "listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          }
        }
      },
      "DownloadedEpisodesPage": {
        "type": "object",
        "required": [
          "episodes",
          "total"
        ],
        "properties": {
          "episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DownloadedEpisode"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "DownloadedEpisodesResponse": {
        "type": "object",
        "required": [
          "downloaded_episodes"
        ],
        "properties": {
          "downloaded_episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DownloadedEpisode"
            }
          }
        }
      },
      "EmailSettings": {
        "type": "object",
        "required": [
          "server_name",
          "server_port",
          "from_email",
          "send_mode",
          "encryption",
          "auth_required",
          "email_username",
          "email_password"
        ],
        "properties": {
          "server_name": {
            "type": "string"
          },
          "server_port": {
            "type": "string",
            "example": "587"
          },
          "from_email": {
            "type": "string"
          },
          "send_mode": {
            "type": "string"
          },
          "encryption": {
            "type": "string"
          },
          "auth_required": {
            "type": "boolean"
          },
          "email_username": {
            "type": "string"
          },
          "email_password": {
            "type": "string"
          }
        }
      },
      "EmailSettingsResponse": {
        "type": "object",
        "required": [
          "Emailsettingsid",
          "ServerName",
          "ServerPort",
          "FromEmail",
          "SendMode",
          "Encryption",
          "AuthRequired",
          "Username",
          "Password"
        ],
        "properties": {
          "Emailsettingsid": {
            "type": "integer",
            "format": "int32"
          },
          "ServerName": {
            "type": "string"
          },
          "ServerPort": {
            "type": "integer",
            "format": "int32"
          },
          "FromEmail": {
            "type": "string"
          },
          "SendMode": {
            "type": "string"
          },
          "Encryption": {
            "type": "string"
          },
          "AuthRequired": {
            "type": "integer",
            "format": "int32"
          },
          "Username": {
            "type": "string"
          },
          "Password": {
            "type": "string"
          }
        }
      },
      "EndpointTest": {
        "type": "object",
        "required": [
          "endpoint",
          "status"
        ],
        "properties": {
          "endpoint": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "response_time_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Episode": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "episodetitle",
          "episodepubdate",
          "episodedescription",
          "episodeartwork",
          "episodeurl",
          "episodeduration",
          "episodeid",
          "completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube",
          "is_video"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "episodetitle": {
            "type": "string"
          },
          "episodepubdate": {
            "type": "string"
          },
          "episodedescription": {
            "type": "string"
          },
          "episodeartwork": {
            "type": "string"
          },
          "episodeurl": {
            "type": "string"
          },
          "episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          }
        }
      },
      "EpisodeCollectionsResponse": {
        "type": "object",
        "required": [
          "collection_ids"
        ],
        "properties": {
          "collection_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "EpisodeInDbResponse": {
        "type": "object",
        "required": [
          "episode_in_db"
        ],
        "properties": {
          "episode_in_db": {
            "type": "boolean"
          }
        }
      },
      "EpisodeMetadataRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "person_episode": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "EpisodesResponse": {
        "type": "object",
        "required": [
          "episodes",
          "total"
        ],
        "properties": {
          "episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Episode"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ExtendSharedLinkRequest": {
        "type": "object",
        "required": [
          "share_code",
          "days"
        ],
        "properties": {
          "share_code": {
            "type": "string"
          },
          "days": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ExternalEpisode": {
        "type": "object",
        "description": "An episode from a show outside the user's library.",
        "required": [
          "episodeid",
          "podcastid",
          "podcastname",
          "feedurl",
          "episodetitle",
          "episodepubdate",
          "episodedescription",
          "episodeartwork",
          "episodeurl",
          "episodeduration",
          "completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube",
          "is_video"
        ],
        "properties": {
          "episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "feedurl": {
            "type": "string"
          },
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "episodetitle": {
            "type": "string"
          },
          "episodepubdate": {
            "type": "string"
          },
          "episodedescription": {
            "type": "string"
          },
          "episodeartwork": {
            "type": "string"
          },
          "episodeurl": {
            "type": "string"
          },
          "episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "FailingFeed": {
        "type": "object",
        "description": "One of the user's podcasts that's failing right now.",
        "required": [
          "podcast_id",
          "name",
          "feed_url",
          "kind",
          "failures",
          "reported"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "feed_url": {
            "type": "string"
          },
          "artwork": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "$ref": "#/components/schemas/FeedErrorKind"
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "The last error, as the host or the parser reported it."
          },
          "failures": {
            "type": "integer",
            "format": "int32"
          },
          "failing_since": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_attempt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "reported": {
            "type": "boolean",
            "description": "Over the reporting threshold (and so reported)."
          }
        }
      },
      "FavoriteStatusResponse": {
        "type": "object",
        "required": [
          "is_favorite"
        ],
        "properties": {
          "is_favorite": {
            "type": "boolean"
          }
        }
      },
      "FeedCutoffDaysResponse": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id",
          "feed_cutoff_days"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "feed_cutoff_days": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "FeedErrorKind": {
        "type": "string",
        "enum": [
          "gone",
          "auth",
          "not_feed",
          "unreachable",
          "server",
          "throttled",
          "other"
        ]
      },
      "FeedProblems": {
        "type": "object",
        "required": [
          "feeds",
          "imports"
        ],
        "properties": {
          "feeds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FailingFeed"
            },
            "description": "Podcasts whose last refresh failed, longest-failing first."
          },
          "imports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportFailure"
            },
            "description": "Feeds from sync apps that couldn't be added, oldest first."
          }
        }
      },
      "FetchTranscriptRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string"
          }
        }
      },
      "GetAutoDownloadDeleteDaysRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "GetDefaultVolumeRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "GetIgnoredPodcastsRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "GetPlaybackSpeedRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "GetScheduledBackupRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "GetUnmatchedPodcastsRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "GetUserResponse": {
        "type": "object",
        "required": [
          "status",
          "retrieved_id"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "retrieved_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "GpodderStatistics": {
        "type": "object",
        "required": [
          "server_url",
          "sync_type",
          "sync_enabled",
          "server_devices",
          "total_devices",
          "server_subscriptions",
          "total_subscriptions",
          "recent_episode_actions",
          "total_episode_actions",
          "connection_status",
          "api_endpoints_tested"
        ],
        "properties": {
          "server_url": {
            "type": "string"
          },
          "sync_type": {
            "type": "string"
          },
          "sync_enabled": {
            "type": "boolean"
          },
          "server_devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServerDevice"
            }
          },
          "total_devices": {
            "type": "integer",
            "format": "int32"
          },
          "server_subscriptions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServerSubscription"
            }
          },
          "total_subscriptions": {
            "type": "integer",
            "format": "int32"
          },
          "recent_episode_actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServerEpisodeAction"
            }
          },
          "total_episode_actions": {
            "type": "integer",
            "format": "int32"
          },
          "connection_status": {
            "type": "string"
          },
          "last_sync_timestamp": {
            "type": [
              "string",
              "null"
            ]
          },
          "api_endpoints_tested": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EndpointTest"
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "database",
          "redis",
          "timestamp"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "database": {
            "type": "boolean"
          },
          "redis": {
            "type": "boolean"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "HistoryAddRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "episode_pos",
          "user_id",
          "is_youtube"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "episode_pos": {
            "type": "number",
            "format": "float"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "HistoryResponse": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          }
        }
      },
      "IgnorePodcastIndexIdRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "ignore"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "ignore": {
            "type": "boolean"
          }
        }
      },
      "ImportFailure": {
        "type": "object",
        "required": [
          "id",
          "feed_url",
          "source",
          "kind",
          "attempts",
          "first_failed_at",
          "last_attempt_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "feed_url": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "description": "Where the subscription came from: `client` (an app on the PinePods gpodder server) or\n`target` (the external sync server)."
          },
          "kind": {
            "$ref": "#/components/schemas/FeedErrorKind"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "attempts": {
            "type": "integer",
            "format": "int32"
          },
          "first_failed_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_attempt_at": {
            "type": "integer",
            "format": "int64"
          },
          "next_attempt_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`None`: Pinepods stopped retrying."
          }
        }
      },
      "InAppNotification": {
        "type": "object",
        "description": "A durable, no-progress notification (\"message\"/\"alert\") shown in the Activity\ncenter's Messages / \"Needs attention\" sections. Distinct from a `TaskInfo`\n(which has progress and a lifecycle). Persisted per-user in Redis and streamed\nover the same task WebSocket. See the notification redesign plan.",
        "required": [
          "id",
          "user_id",
          "category",
          "severity",
          "title",
          "created_at",
          "expires_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "category": {
            "type": "string",
            "description": "Free-form category tag (e.g. \"feed_refresh\", \"ai\", \"new_episode\")."
          },
          "severity": {
            "$ref": "#/components/schemas/MsgSeverity"
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": [
              "string",
              "null"
            ]
          },
          "episode_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "podcast_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "art_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "link": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional in-app link the message can deep-link to."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "read": {
            "type": "boolean"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Server-authoritative expiry. List reads drop anything past this instant."
          }
        }
      },
      "InitRequest": {
        "type": "object",
        "required": [
          "api_key"
        ],
        "properties": {
          "api_key": {
            "type": "string"
          }
        }
      },
      "InitiateNextcloudLoginRequest": {
        "type": "object",
        "required": [
          "user_id",
          "nextcloud_url"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "nextcloud_url": {
            "type": "string"
          }
        }
      },
      "LanguageUpdateRequest": {
        "type": "object",
        "required": [
          "user_id",
          "language"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "language": {
            "type": "string"
          }
        }
      },
      "ListBackupFilesRequest": {
        "type": "object"
      },
      "LoginResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "retrieved_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "mfa_required": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "user_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "mfa_session_token": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ManualBackupRequest": {
        "type": "object"
      },
      "MarkEpisodeCompletedRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "MarkEpisodeUncompletedRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "MergePodcastsRequest": {
        "type": "object",
        "required": [
          "secondary_podcast_ids"
        ],
        "properties": {
          "secondary_podcast_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "MergePodcastsResponse": {
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "MergedPodcastsResponse": {
        "type": "object",
        "required": [
          "merged_podcast_ids"
        ],
        "properties": {
          "merged_podcast_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "MsgSeverity": {
        "type": "string",
        "description": "Durable in-app notification severity. Mirrored on the frontend\n(`web/src/components/context.rs`). `warning`/`error` count toward the bell\nbadge; `info`/`success` do not.",
        "enum": [
          "info",
          "success",
          "warning",
          "error"
        ]
      },
      "NextPlaylistEpisodeRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "playlist_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "playlist_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "NextPodcastEpisodeRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "NotificationSettingsRequest": {
        "type": "object",
        "required": [
          "user_id",
          "platform",
          "enabled"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "platform": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "ntfy_topic": {
            "type": [
              "string",
              "null"
            ]
          },
          "ntfy_server_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "ntfy_username": {
            "type": [
              "string",
              "null"
            ]
          },
          "ntfy_password": {
            "type": [
              "string",
              "null"
            ]
          },
          "ntfy_access_token": {
            "type": [
              "string",
              "null"
            ]
          },
          "gotify_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "gotify_token": {
            "type": [
              "string",
              "null"
            ]
          },
          "http_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "http_token": {
            "type": [
              "string",
              "null"
            ]
          },
          "http_method": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NotificationStatusResponse": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "NotificationTestRequest": {
        "type": "object",
        "required": [
          "user_id",
          "platform"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "platform": {
            "type": "string"
          }
        }
      },
      "NowPlayingDevicesResponse": {
        "type": "object",
        "required": [
          "devices"
        ],
        "properties": {
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NowPlayingSnapshot"
            }
          }
        }
      },
      "NowPlayingSnapshot": {
        "type": "object",
        "description": "An ephemeral snapshot of what one device is playing, mirrored into Valkey with\na TTL so other devices can see it and send remote-control commands. This is a\nbest-effort mirror, never the source of truth for playback (see the\n\"aware, not owns\" principle) — the device's local player stays authoritative.",
        "required": [
          "device_id",
          "device_name",
          "device_type",
          "episode_id"
        ],
        "properties": {
          "device_id": {
            "type": "string"
          },
          "device_name": {
            "type": "string"
          },
          "device_type": {
            "type": "string"
          },
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "title": {
            "type": "string"
          },
          "artwork_url": {
            "type": "string"
          },
          "position_sec": {
            "type": "number",
            "format": "double"
          },
          "duration_sec": {
            "type": "number",
            "format": "double"
          },
          "playing": {
            "type": "boolean"
          },
          "speed": {
            "type": "number",
            "format": "double"
          },
          "updated_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix seconds when this snapshot was last updated (server-stamped on write)."
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Actions the device says it applies (from its `capabilities` connect\nparameter). Empty means it didn't say: assume the original action set."
          }
        }
      },
      "OPMLImportRequest": {
        "type": "object",
        "required": [
          "podcasts",
          "user_id"
        ],
        "properties": {
          "podcasts": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "OidcProviderRequest": {
        "type": "object",
        "required": [
          "provider_name",
          "client_id",
          "client_secret",
          "authorization_url",
          "token_url",
          "user_info_url",
          "button_text",
          "scope",
          "button_color",
          "button_text_color"
        ],
        "properties": {
          "provider_name": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string"
          },
          "authorization_url": {
            "type": "string"
          },
          "token_url": {
            "type": "string"
          },
          "user_info_url": {
            "type": "string"
          },
          "button_text": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "button_color": {
            "type": "string"
          },
          "button_text_color": {
            "type": "string"
          },
          "icon_svg": {
            "type": [
              "string",
              "null"
            ]
          },
          "name_claim": {
            "type": [
              "string",
              "null"
            ]
          },
          "email_claim": {
            "type": [
              "string",
              "null"
            ]
          },
          "username_claim": {
            "type": [
              "string",
              "null"
            ]
          },
          "roles_claim": {
            "type": [
              "string",
              "null"
            ]
          },
          "user_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "admin_role": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PasswordUpdateRequest": {
        "type": "object",
        "required": [
          "hash_pw"
        ],
        "properties": {
          "hash_pw": {
            "type": "string"
          }
        }
      },
      "Person": {
        "type": "object",
        "required": [
          "id",
          "name",
          "followed"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "podpeople_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "img": {
            "type": [
              "string",
              "null"
            ]
          },
          "href": {
            "type": [
              "string",
              "null"
            ]
          },
          "followed": {
            "type": "boolean"
          }
        }
      },
      "PersonHit": {
        "type": "object",
        "required": [
          "name",
          "followed"
        ],
        "properties": {
          "person_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "PinePods person id, when this server already knows them."
          },
          "podpeople_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "img": {
            "type": [
              "string",
              "null"
            ]
          },
          "known_for": {
            "type": [
              "string",
              "null"
            ],
            "description": "A few podcasts they're known for, to tell namesakes apart."
          },
          "followed": {
            "type": "boolean"
          }
        }
      },
      "PersonPodcast": {
        "type": "object",
        "description": "A podcast a person is credited on.",
        "required": [
          "podcastname",
          "feedurl",
          "roles",
          "podcast_level",
          "episode_count"
        ],
        "properties": {
          "podcastid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The user's podcast id, or None for a show outside their library."
          },
          "podcastname": {
            "type": "string"
          },
          "artworkurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "feedurl": {
            "type": "string"
          },
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "podcast_level": {
            "type": "boolean"
          },
          "episode_count": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PersonProfile": {
        "type": "object",
        "required": [
          "person",
          "podcasts",
          "episodes",
          "external_episodes",
          "refreshing"
        ],
        "properties": {
          "person": {
            "$ref": "#/components/schemas/Person"
          },
          "podcasts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PersonPodcast"
            }
          },
          "episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Episode"
            },
            "description": "Library episodes the person is credited on (directly, or as a podcast's host), newest first."
          },
          "external_episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalEpisode"
            },
            "description": "Recent episodes from shows outside the library."
          },
          "refreshing": {
            "type": "boolean",
            "description": "True while the external episode list is being refreshed in the background."
          }
        }
      },
      "PinepodsCheckResponse": {
        "type": "object",
        "required": [
          "status_code",
          "pinepods_instance"
        ],
        "properties": {
          "status_code": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "pinepods_instance": {
            "type": "boolean"
          }
        }
      },
      "PlayEpisodeDetailsRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "PlayEpisodeDetailsResponse": {
        "type": "object",
        "required": [
          "playback_speed",
          "start_skip",
          "end_skip",
          "playback_speed_customized"
        ],
        "properties": {
          "playback_speed": {
            "type": "number",
            "format": "double"
          },
          "start_skip": {
            "type": "integer",
            "format": "int32"
          },
          "end_skip": {
            "type": "integer",
            "format": "int32"
          },
          "playback_speed_customized": {
            "type": "boolean"
          }
        }
      },
      "PodcastCredits": {
        "type": "object",
        "required": [
          "people",
          "guests"
        ],
        "properties": {
          "people": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditedPerson"
            },
            "description": "Hosts, co-hosts and anyone else credited on the show or appearing as a regular."
          },
          "guests": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditedPerson"
            },
            "description": "Guests and other episode-only credits, most frequent first."
          }
        }
      },
      "PodcastDownloadSummary": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "episode_count"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "artworkurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "episode_count": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PodcastDownloadSummaryResponse": {
        "type": "object",
        "required": [
          "podcasts"
        ],
        "properties": {
          "podcasts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PodcastDownloadSummary"
            }
          }
        }
      },
      "PodcastEpisode": {
        "type": "object",
        "required": [
          "podcastname",
          "Episodetitle",
          "Episodepubdate",
          "Episodedescription",
          "Episodeartwork",
          "Episodeurl",
          "Episodeduration",
          "Episodeid",
          "Completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube",
          "is_video"
        ],
        "properties": {
          "podcastname": {
            "type": "string"
          },
          "Episodetitle": {
            "type": "string"
          },
          "Episodepubdate": {
            "type": "string"
          },
          "Episodedescription": {
            "type": "string"
          },
          "Episodeartwork": {
            "type": "string"
          },
          "Episodeurl": {
            "type": "string"
          },
          "Episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "Listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "Episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "Completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          }
        }
      },
      "PodcastEpisodesResponse": {
        "type": "object",
        "required": [
          "episodes",
          "total"
        ],
        "properties": {
          "episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PodcastEpisode"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PodcastExtraListResponse": {
        "type": "object",
        "required": [
          "pods"
        ],
        "properties": {
          "pods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PodcastExtraResponse"
            }
          }
        }
      },
      "PodcastExtraResponse": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "feedurl",
          "explicit",
          "play_count",
          "episodes_played",
          "is_youtube",
          "is_video",
          "is_favorite"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "artworkurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "episodecount": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "websiteurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "feedurl": {
            "type": "string"
          },
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "explicit": {
            "type": "boolean"
          },
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "play_count": {
            "type": "integer",
            "format": "int64"
          },
          "episodes_played": {
            "type": "integer",
            "format": "int32"
          },
          "oldest_episode_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          },
          "is_favorite": {
            "type": "boolean"
          }
        }
      },
      "PodcastFavoriteStatusRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PodcastListResponse": {
        "type": "object",
        "required": [
          "pods"
        ],
        "properties": {
          "pods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PodcastResponse"
            }
          }
        }
      },
      "PodcastNotificationStatusRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PodcastResponse": {
        "type": "object",
        "required": [
          "podcastid",
          "podcastname",
          "feedurl",
          "explicit",
          "is_favorite",
          "is_video"
        ],
        "properties": {
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "podcastname": {
            "type": "string"
          },
          "artworkurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "episodecount": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "websiteurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "feedurl": {
            "type": "string"
          },
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "explicit": {
            "type": "boolean"
          },
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "is_favorite": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          }
        }
      },
      "PodcastStatusResponse": {
        "type": "object",
        "required": [
          "success",
          "podcast_id",
          "first_episode_id"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "first_episode_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PodcastValues": {
        "type": "object",
        "required": [
          "pod_title",
          "pod_artwork",
          "pod_author",
          "categories",
          "pod_description",
          "pod_episode_count",
          "pod_feed_url",
          "pod_website",
          "pod_explicit",
          "user_id"
        ],
        "properties": {
          "pod_title": {
            "type": "string"
          },
          "pod_artwork": {
            "type": "string"
          },
          "pod_author": {
            "type": "string"
          },
          "categories": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "pod_description": {
            "type": "string"
          },
          "pod_episode_count": {
            "type": "integer",
            "format": "int32"
          },
          "pod_feed_url": {
            "type": "string"
          },
          "pod_website": {
            "type": "string"
          },
          "pod_explicit": {
            "type": "boolean"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "PodpingInfo": {
        "type": "object",
        "required": [
          "enabled",
          "relay_url",
          "client"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "relay_url": {
            "type": "string",
            "description": "Where announcements are read from (`PINEPODS_PODPING_URL`, else the search service)."
          },
          "relay": {
            "type": [
              "object",
              "null"
            ],
            "description": "The relay's own status (`following`: it keeps up with Hive), when it answered."
          },
          "relay_error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the relay's status couldn't be read (e.g. a search service without the relay)."
          },
          "client": {
            "$ref": "#/components/schemas/ClientStatus"
          }
        }
      },
      "PublicOidcProviderResponse": {
        "type": "object",
        "required": [
          "provider_id",
          "provider_name",
          "client_id",
          "authorization_url",
          "scope",
          "button_color",
          "button_text",
          "button_text_color"
        ],
        "properties": {
          "provider_id": {
            "type": "integer",
            "format": "int32"
          },
          "provider_name": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "authorization_url": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "button_color": {
            "type": "string"
          },
          "button_text": {
            "type": "string"
          },
          "button_text_color": {
            "type": "string"
          },
          "icon_svg": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PublicOidcProvidersResponse": {
        "type": "object",
        "required": [
          "providers",
          "disable_standard_login"
        ],
        "properties": {
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicOidcProviderResponse"
            }
          },
          "disable_standard_login": {
            "type": "boolean"
          }
        }
      },
      "QueuePodcastRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id",
          "is_youtube"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "playing_episode_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Optional hint: the episode currently playing on the caller's device, so the\nserver can insert the new episode directly *under* it (\"play next\"). When\nabsent the episode is inserted at the top of the queue. Ignored by\nremove_queued_pod. The anchor may itself be a YouTube video, hence the\ncompanion `playing_is_youtube` flag for an unambiguous lookup."
          },
          "playing_is_youtube": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "QueueResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "string"
          }
        }
      },
      "QueuedEpisode": {
        "type": "object",
        "required": [
          "episodetitle",
          "podcastname",
          "podcastid",
          "episodepubdate",
          "episodedescription",
          "episodeartwork",
          "episodeurl",
          "episodeduration",
          "queuedate",
          "episodeid",
          "completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube",
          "is_video"
        ],
        "properties": {
          "episodetitle": {
            "type": "string"
          },
          "podcastname": {
            "type": "string"
          },
          "podcastid": {
            "type": "integer",
            "format": "int32"
          },
          "episodepubdate": {
            "type": "string"
          },
          "episodedescription": {
            "type": "string"
          },
          "episodeartwork": {
            "type": "string"
          },
          "episodeurl": {
            "type": "string"
          },
          "queueposition": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "queuedate": {
            "type": "string"
          },
          "listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          }
        }
      },
      "QueuedEpisodesResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QueuedEpisode"
            }
          }
        }
      },
      "RecommendedPodcast": {
        "type": "object",
        "required": [
          "title",
          "categories",
          "score",
          "reason"
        ],
        "properties": {
          "podcastindexid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "title": {
            "type": "string"
          },
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "feedurl": {
            "type": [
              "string",
              "null"
            ]
          },
          "categories": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "score": {
            "type": "number",
            "format": "double"
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "RecordListenDurationRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id",
          "listen_duration"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "listen_duration": {
            "type": "number",
            "format": "double"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "episode_duration": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "The player's duration for the episode in seconds, if it knows it. Stored when the feed\ngave none (new episodes beyond the newest few are inserted with duration 0)."
          }
        }
      },
      "RefreshLocalPodcastRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RemoteDeviceEntry": {
        "type": "object",
        "required": [
          "id",
          "caption",
          "type",
          "subscriptions"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "caption": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "subscriptions": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "RemoveCategoryData": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id",
          "category"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "RemovePodcastIdRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RemovePodcastRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_name",
          "podcast_url"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_name": {
            "type": "string"
          },
          "podcast_url": {
            "type": "string"
          }
        }
      },
      "RemovePodcastResponse": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          }
        }
      },
      "RemoveSyncRequest": {
        "type": "object",
        "required": [
          "user_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "RemoveYouTubeChannelRequest": {
        "type": "object",
        "required": [
          "user_id",
          "channel_name",
          "channel_url"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "channel_name": {
            "type": "string"
          },
          "channel_url": {
            "type": "string"
          }
        }
      },
      "RenameDeviceRequest": {
        "type": "object",
        "required": [
          "caption"
        ],
        "properties": {
          "caption": {
            "type": "string"
          }
        }
      },
      "ReorderQueueItem": {
        "type": "object",
        "description": "A single queue entry in a reorder request. Carries `is_youtube` so the server\ncan disambiguate a podcast `EpisodeID` from a YouTube `VideoID` that happen to\nshare the same integer (they come from independent autoincrement sequences).",
        "required": [
          "episode_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "ReorderQueueRequest": {
        "type": "object",
        "properties": {
          "episodes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/ReorderQueueItem"
            },
            "description": "Preferred, type-aware ordering. Element 0 becomes queue position 1 (top)."
          },
          "episode_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "Legacy id-only ordering, kept for backward compatibility with older clients.\nUsed only when `episodes` is absent."
          }
        }
      },
      "ReorderQueueResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        }
      },
      "ResetCodeRequest": {
        "type": "object",
        "required": [
          "email",
          "username"
        ],
        "properties": {
          "email": {
            "type": "string"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "ResetCodeResponse": {
        "type": "object",
        "required": [
          "code_created"
        ],
        "properties": {
          "code_created": {
            "type": "boolean"
          }
        }
      },
      "RestoreBackupFileRequest": {
        "type": "object",
        "required": [
          "backup_filename"
        ],
        "properties": {
          "backup_filename": {
            "type": "string"
          }
        }
      },
      "RunResponse": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "The error, when the run failed (also stored on the target)."
          },
          "summary": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/RunSummaryInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "target": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SyncTargetInfo"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "RunSummaryInfo": {
        "type": "object",
        "required": [
          "full",
          "subscriptions_queued",
          "subscriptions_removed",
          "subscriptions_pushed",
          "actions_pulled",
          "actions_applied",
          "actions_pushed"
        ],
        "properties": {
          "full": {
            "type": "boolean"
          },
          "subscriptions_queued": {
            "type": "integer",
            "minimum": 0
          },
          "subscriptions_removed": {
            "type": "integer",
            "minimum": 0
          },
          "subscriptions_pushed": {
            "type": "integer",
            "minimum": 0
          },
          "actions_pulled": {
            "type": "integer",
            "minimum": 0
          },
          "actions_applied": {
            "type": "integer",
            "minimum": 0
          },
          "actions_pushed": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "SaveEmailSettingsRequest": {
        "type": "object",
        "required": [
          "email_settings"
        ],
        "properties": {
          "email_settings": {
            "$ref": "#/components/schemas/EmailSettings"
          }
        }
      },
      "SaveEpisodeResponse": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          }
        }
      },
      "SaveMfaSecretRequest": {
        "type": "object",
        "required": [
          "user_id",
          "mfa_secret"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "mfa_secret": {
            "type": "string"
          }
        }
      },
      "SavePodcastRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id",
          "is_youtube"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "SaveTargetResponse": {
        "type": "object",
        "required": [
          "target"
        ],
        "properties": {
          "target": {
            "$ref": "#/components/schemas/SyncTargetInfo"
          },
          "task_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The background task running the first (full) sync."
          }
        }
      },
      "SavedEpisode": {
        "type": "object",
        "required": [
          "episodetitle",
          "podcastname",
          "episodepubdate",
          "episodedescription",
          "episodeartwork",
          "episodeurl",
          "episodeduration",
          "episodeid",
          "websiteurl",
          "completed",
          "saved",
          "queued",
          "downloaded",
          "is_youtube"
        ],
        "properties": {
          "episodetitle": {
            "type": "string"
          },
          "podcastname": {
            "type": "string"
          },
          "episodepubdate": {
            "type": "string"
          },
          "episodedescription": {
            "type": "string"
          },
          "episodeartwork": {
            "type": "string"
          },
          "episodeurl": {
            "type": "string"
          },
          "episodeduration": {
            "type": "integer",
            "format": "int32"
          },
          "listenduration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "episodeid": {
            "type": "integer",
            "format": "int32"
          },
          "websiteurl": {
            "type": "string"
          },
          "completed": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "queued": {
            "type": "boolean"
          },
          "downloaded": {
            "type": "boolean"
          },
          "is_youtube": {
            "type": "boolean"
          },
          "podcastid": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "savedate": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SavedEpisodesResponse": {
        "type": "object",
        "required": [
          "saved_episodes",
          "total"
        ],
        "properties": {
          "saved_episodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SavedEpisode"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ScheduleBackupRequest": {
        "type": "object",
        "required": [
          "user_id",
          "cron_schedule",
          "enabled"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "cron_schedule": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "retention_count": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "SearchDataRequest": {
        "type": "object",
        "required": [
          "search_term",
          "user_id"
        ],
        "properties": {
          "search_term": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "categories": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "SearchDataResponse": {
        "type": "object",
        "required": [
          "data",
          "total"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "SearchServiceStatus": {
        "type": "object",
        "required": [
          "url",
          "reachable"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "The search service's address (`SEARCH_API_URL` without its path)."
          },
          "reachable": {
            "type": "boolean"
          },
          "latency_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SelfServiceStatusResponse": {
        "type": "object",
        "required": [
          "status",
          "first_admin_created"
        ],
        "properties": {
          "status": {
            "type": "boolean"
          },
          "first_admin_created": {
            "type": "boolean"
          }
        }
      },
      "SendEmailRequest": {
        "type": "object",
        "required": [
          "to_email",
          "subject",
          "message"
        ],
        "properties": {
          "to_email": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "SendTestEmailRequest": {
        "type": "object",
        "required": [
          "server_name",
          "server_port",
          "from_email",
          "encryption",
          "auth_required",
          "email_username",
          "email_password",
          "to_email",
          "message"
        ],
        "properties": {
          "server_name": {
            "type": "string"
          },
          "server_port": {
            "type": "string"
          },
          "from_email": {
            "type": "string"
          },
          "encryption": {
            "type": "string"
          },
          "auth_required": {
            "type": "boolean"
          },
          "email_username": {
            "type": "string"
          },
          "email_password": {
            "type": "string"
          },
          "to_email": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ServerDevice": {
        "type": "object",
        "required": [
          "id",
          "caption",
          "device_type",
          "subscriptions"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "caption": {
            "type": "string"
          },
          "device_type": {
            "type": "string"
          },
          "subscriptions": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ServerEpisodeAction": {
        "type": "object",
        "required": [
          "podcast",
          "episode",
          "action",
          "timestamp"
        ],
        "properties": {
          "podcast": {
            "type": "string"
          },
          "episode": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "timestamp": {
            "type": "string"
          },
          "position": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "device": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ServerSubscription": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SetAutoDownloadDeleteDaysPodcast": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "days"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "days": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SetAutoDownloadDeleteDaysUser": {
        "type": "object",
        "required": [
          "user_id",
          "days"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "days": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SetCollectionAddUiRequest": {
        "type": "object",
        "required": [
          "user_id",
          "mode"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "mode": {
            "type": "string"
          }
        }
      },
      "SetDefaultVolumeUser": {
        "type": "object",
        "required": [
          "user_id",
          "volume"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "volume": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SetEmailRequest": {
        "type": "object",
        "required": [
          "user_id",
          "new_email"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "new_email": {
            "type": "string"
          }
        }
      },
      "SetGlobalPodcastCoverPreference": {
        "type": "object",
        "required": [
          "user_id",
          "use_podcast_covers"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "use_podcast_covers": {
            "type": "boolean"
          },
          "podcast_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "SetIsAdminRequest": {
        "type": "object",
        "required": [
          "user_id",
          "isadmin"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "isadmin": {
            "type": "boolean"
          }
        }
      },
      "SetPlaybackSpeedPodcast": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "playback_speed"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "playback_speed": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "SetPlaybackSpeedUser": {
        "type": "object",
        "required": [
          "user_id",
          "playback_speed"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "playback_speed": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "SetPodcastCoverPreference": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "use_podcast_covers"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "use_podcast_covers": {
            "type": "boolean"
          }
        }
      },
      "SetPodping": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "SetServerRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "SetThemeRequest": {
        "type": "object",
        "required": [
          "user_id",
          "new_theme"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "new_theme": {
            "type": "string"
          }
        }
      },
      "SetUsernameRequest": {
        "type": "object",
        "required": [
          "user_id",
          "new_username"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "new_username": {
            "type": "string"
          }
        }
      },
      "SilenceTrimRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          },
          "threshold": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "SkipTimesRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "start_skip": {
            "type": "integer",
            "format": "int32"
          },
          "end_skip": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "StoreStateRequest": {
        "type": "object",
        "required": [
          "state",
          "client_id"
        ],
        "properties": {
          "state": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "origin_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "code_verifier": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SuccessResponse": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          }
        }
      },
      "SyncActionEntry": {
        "type": "object",
        "required": [
          "podcast",
          "episode",
          "action",
          "timestamp",
          "origin"
        ],
        "properties": {
          "podcast": {
            "type": "string"
          },
          "episode": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Unix seconds (the action's own time)."
          },
          "position": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "device": {
            "type": [
              "string",
              "null"
            ]
          },
          "origin": {
            "type": "string",
            "description": "`pinepods`, `client` (an app on the PinePods server) or `target` (the external server)."
          }
        }
      },
      "SyncDeviceEntry": {
        "type": "object",
        "required": [
          "id",
          "name",
          "caption",
          "type",
          "protected"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string",
            "description": "The id the app registered (what it addresses the device by)."
          },
          "caption": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "last_seen": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "protected": {
            "type": "boolean",
            "description": "Pinepods' own device: can't be renamed or removed."
          }
        }
      },
      "SyncServerInfo": {
        "type": "object",
        "required": [
          "enabled",
          "username",
          "server_url",
          "server_url_configured"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "username": {
            "type": "string",
            "description": "The username to enter in apps."
          },
          "server_url": {
            "type": "string",
            "description": "The server URL to enter in apps."
          },
          "server_url_configured": {
            "type": "boolean",
            "description": "`server_url` comes from `PINEPODS_PUBLIC_URL`; otherwise it was guessed from the request\nand a client may prefer the URL it reached Pinepods at."
          },
          "notice": {
            "type": [
              "string",
              "null"
            ],
            "description": "A notice for the settings page, e.g. `reenter_external`: the external sync server has to\nbe entered again."
          }
        }
      },
      "SyncStats": {
        "type": "object",
        "required": [
          "server_enabled",
          "subscriptions",
          "devices",
          "total_episode_actions",
          "recent_episode_actions"
        ],
        "properties": {
          "server_enabled": {
            "type": "boolean"
          },
          "subscriptions": {
            "type": "integer",
            "description": "Podcasts shared with apps and the external server.",
            "minimum": 0
          },
          "devices": {
            "type": "integer",
            "description": "Apps on the PinePods server (not counting Pinepods itself).",
            "minimum": 0
          },
          "total_episode_actions": {
            "type": "integer",
            "format": "int64"
          },
          "last_change": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds: when the newest episode action was received."
          },
          "recent_episode_actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SyncActionEntry"
            }
          },
          "target": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SyncTargetQueue"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "SyncTargetInfo": {
        "type": "object",
        "required": [
          "kind",
          "url",
          "username",
          "enabled",
          "needs_full_sync",
          "consecutive_failures",
          "in_backoff"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "description": "`gpodder` or `nextcloud`."
          },
          "url": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "device_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pinepods' device on a gpodder server."
          },
          "enabled": {
            "type": "boolean"
          },
          "needs_full_sync": {
            "type": "boolean",
            "description": "The next run is a full sync (new server, or a full sync that hasn't succeeded yet)."
          },
          "last_attempt_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_success_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "consecutive_failures": {
            "type": "integer",
            "format": "int32"
          },
          "in_backoff": {
            "type": "boolean",
            "description": "Automatic syncs are paused after failures until `retry_at`; \"Sync now\" still runs."
          },
          "retry_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          }
        }
      },
      "SyncTargetQueue": {
        "type": "object",
        "required": [
          "kind",
          "url"
        ],
        "properties": {
          "kind": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "last_success_at": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix seconds."
          },
          "pending_subscriptions": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Changes waiting to be sent; null until the first sync has succeeded."
          },
          "pending_actions": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "SyncTargetResponse": {
        "type": "object",
        "properties": {
          "target": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SyncTargetInfo",
                "description": "Null when no external sync server is set up."
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TargetCredentials": {
        "type": "object",
        "required": [
          "kind",
          "url",
          "username"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "description": "`gpodder` or `nextcloud`."
          },
          "url": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": [
              "string",
              "null"
            ],
            "description": "Leave out to reuse the stored password of the same server and account."
          },
          "device_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "gpodder only: the device Pinepods syncs as. Left out: keep the current one, or pick one."
          }
        }
      },
      "TaskInfo": {
        "type": "object",
        "required": [
          "id",
          "task_type",
          "user_id",
          "status",
          "progress",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "task_type": {
            "type": "string"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "$ref": "#/components/schemas/TaskStatus"
          },
          "progress": {
            "type": "number",
            "format": "double"
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "result": {},
          "episode_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the task reached SUCCESS/FAILED — drives \"Done\" ordering + relative time."
          },
          "art_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cover art for the card thumbnail."
          },
          "detail": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sub-line detail (e.g. \"72 of 128 feeds\"; on failure, the reason)."
          },
          "group": {
            "type": [
              "string",
              "null"
            ],
            "description": "Shared key folding sibling tasks into one collapsible group."
          },
          "group_label": {
            "type": [
              "string",
              "null"
            ]
          },
          "total": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Total item count a grouped run is working through (for \"x of N\")."
          }
        }
      },
      "TaskStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "DOWNLOADING",
          "SUCCESS",
          "FAILED"
        ]
      },
      "TestTargetResponse": {
        "type": "object",
        "required": [
          "success",
          "message",
          "devices"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RemoteDeviceEntry"
            },
            "description": "gpodder only: the account's devices."
          },
          "device_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "gpodder only: the device Pinepods would sync as."
          }
        }
      },
      "TimeInfoResponse": {
        "type": "object",
        "required": [
          "timezone",
          "hour_pref"
        ],
        "properties": {
          "timezone": {
            "type": "string"
          },
          "hour_pref": {
            "type": "integer",
            "format": "int32"
          },
          "date_format": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "TimeZoneInfo": {
        "type": "object",
        "required": [
          "user_id",
          "timezone",
          "hour_pref",
          "date_format"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "timezone": {
            "type": "string"
          },
          "hour_pref": {
            "type": "integer",
            "format": "int32"
          },
          "date_format": {
            "type": "string"
          }
        }
      },
      "TogglePodcastFavoriteData": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "is_favorite"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "is_favorite": {
            "type": "boolean"
          }
        }
      },
      "TogglePodcastNotificationData": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "enabled"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "TranscribeEpisodeRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "user_id"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "force": {
            "type": "boolean"
          }
        }
      },
      "UnmergePodcastResponse": {
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "UpdateAutoCompleteSecondsRequest": {
        "type": "object",
        "required": [
          "user_id",
          "seconds"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "seconds": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "UpdateCollectionRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          },
          "auto_add_categories": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Podcast categories to auto-add episodes from (empty vec clears the rule)."
          },
          "backfill": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "When true, immediately backfill existing matching episodes after saving."
          }
        }
      },
      "UpdateDateFormatRequest": {
        "type": "object",
        "required": [
          "user_id",
          "date_format"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "date_format": {
            "type": "string"
          }
        }
      },
      "UpdateEpisodeDurationRequest": {
        "type": "object",
        "required": [
          "episode_id",
          "new_duration",
          "is_youtube"
        ],
        "properties": {
          "episode_id": {
            "type": "integer",
            "format": "int32"
          },
          "new_duration": {
            "type": "integer",
            "format": "int32"
          },
          "is_youtube": {
            "type": "boolean"
          }
        }
      },
      "UpdateFeedCutoffDaysData": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id",
          "feed_cutoff_days"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "feed_cutoff_days": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "UpdateGpodderSyncRequest": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "UpdatePlaylistRequest": {
        "type": "object",
        "required": [
          "user_id",
          "playlist_id",
          "name",
          "include_unplayed",
          "include_partially_played",
          "include_played",
          "sort_order",
          "group_by_podcast",
          "icon_name"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "playlist_id": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "include_unplayed": {
            "type": "boolean"
          },
          "include_partially_played": {
            "type": "boolean"
          },
          "include_played": {
            "type": "boolean"
          },
          "play_progress_min": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "play_progress_max": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "time_filter_hours": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "min_duration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Minimum episode length in **minutes** (stored, and returned by get_playlists, in seconds)."
          },
          "max_duration": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Maximum episode length in **minutes** (stored, and returned by get_playlists, in seconds)."
          },
          "sort_order": {
            "type": "string",
            "description": "One of date_asc, date_desc, duration_asc, duration_desc, listen_progress, completion.",
            "example": "date_desc"
          },
          "group_by_podcast": {
            "type": "boolean"
          },
          "max_episodes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "icon_name": {
            "type": "string"
          }
        }
      },
      "UpdatePlaylistResponse": {
        "type": "object",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          }
        }
      },
      "UpdatePodcastIndexIdRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id",
          "podcast_index_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_index_id": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "UpdatePodcastInfoRequest": {
        "type": "object",
        "required": [
          "user_id",
          "podcast_id"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "feed_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          },
          "password": {
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "artwork_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "website_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "podcast_index_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "UpdatePodcastInfoResponse": {
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "UpdateServices": {
        "type": "object",
        "required": [
          "search",
          "podping"
        ],
        "properties": {
          "search": {
            "$ref": "#/components/schemas/SearchServiceStatus"
          },
          "podping": {
            "$ref": "#/components/schemas/PodpingInfo"
          }
        }
      },
      "UpdateTimeFormatRequest": {
        "type": "object",
        "required": [
          "user_id",
          "hour_pref"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "hour_pref": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "UpdateTimezoneRequest": {
        "type": "object",
        "required": [
          "user_id",
          "timezone"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "timezone": {
            "type": "string"
          }
        }
      },
      "UpdateYouTubeVideoFilterRequest": {
        "type": "object",
        "required": [
          "podcast_id",
          "user_id"
        ],
        "properties": {
          "podcast_id": {
            "type": "integer",
            "format": "int32"
          },
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "min_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Shortest video to add, in minutes; empty or 0 for no limit."
          },
          "max_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Longest video to add, in minutes; empty or 0 for no limit."
          },
          "title_contains": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only add videos whose title contains this (any case); empty for all."
          }
        }
      },
      "UserCategoriesResponse": {
        "type": "object",
        "required": [
          "categories"
        ],
        "properties": {
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "UserDetails": {
        "type": "object",
        "required": [
          "UserID"
        ],
        "properties": {
          "UserID": {
            "type": "integer",
            "format": "int32"
          },
          "Fullname": {
            "type": [
              "string",
              "null"
            ]
          },
          "Username": {
            "type": [
              "string",
              "null"
            ]
          },
          "Email": {
            "type": [
              "string",
              "null"
            ]
          },
          "Hashed_PW": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null: the password hash is never sent to clients. Kept for response compatibility."
          },
          "Salt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null; kept for response compatibility."
          }
        }
      },
      "UserInfo": {
        "type": "object",
        "required": [
          "userid",
          "fullname",
          "username",
          "email",
          "isadmin"
        ],
        "properties": {
          "userid": {
            "type": "integer",
            "format": "int32"
          },
          "fullname": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "isadmin": {
            "type": "boolean"
          }
        }
      },
      "UserLanguageResponse": {
        "type": "object",
        "required": [
          "language"
        ],
        "properties": {
          "language": {
            "type": "string"
          }
        }
      },
      "VerifyAndResetPasswordRequest": {
        "type": "object",
        "required": [
          "reset_code",
          "email",
          "new_password"
        ],
        "properties": {
          "reset_code": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "new_password": {
            "type": "string"
          }
        }
      },
      "VerifyAndResetPasswordResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        }
      },
      "VerifyGpodderAuthRequest": {
        "type": "object",
        "required": [
          "gpodder_url",
          "gpodder_username",
          "gpodder_password"
        ],
        "properties": {
          "gpodder_url": {
            "type": "string"
          },
          "gpodder_username": {
            "type": "string"
          },
          "gpodder_password": {
            "type": "string"
          }
        }
      },
      "VerifyKeyResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string"
          }
        }
      },
      "VerifyMfaLoginRequest": {
        "type": "object",
        "required": [
          "mfa_session_token",
          "mfa_code"
        ],
        "properties": {
          "mfa_session_token": {
            "type": "string"
          },
          "mfa_code": {
            "type": "string"
          }
        }
      },
      "VerifyMfaLoginResponse": {
        "type": "object",
        "required": [
          "status",
          "verified"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "retrieved_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "verified": {
            "type": "boolean"
          }
        }
      },
      "VerifyMfaRequest": {
        "type": "object",
        "required": [
          "user_id",
          "mfa_code"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "mfa_code": {
            "type": "string"
          }
        }
      },
      "VerifyTempMfaRequest": {
        "type": "object",
        "required": [
          "user_id",
          "mfa_code"
        ],
        "properties": {
          "user_id": {
            "type": "integer",
            "format": "int32"
          },
          "mfa_code": {
            "type": "string"
          }
        }
      },
      "YouTubeVideoFilter": {
        "type": "object",
        "description": "Which new videos a channel subscription adds. `None` means no limit.",
        "properties": {
          "min_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Shortest video, in minutes."
          },
          "max_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Longest video, in minutes."
          },
          "title_contains": {
            "type": [
              "string",
              "null"
            ],
            "description": "Text the title must contain (any case)."
          }
        }
      },
      "YtDlpSettingsUpdate": {
        "type": "object",
        "description": "Update payload from the settings page (only the two user-editable fields).",
        "required": [
          "auto_update",
          "channel"
        ],
        "properties": {
          "auto_update": {
            "type": "boolean"
          },
          "channel": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "in": "header",
        "name": "Api-Key"
      }
    }
  },
  "tags": [
    {
      "name": "health",
      "description": "Health and instance checks (no auth)"
    },
    {
      "name": "auth",
      "description": "Authentication, sessions, MFA, and OIDC"
    },
    {
      "name": "podcasts",
      "description": "Podcast subscriptions, episodes, queue, and playback"
    },
    {
      "name": "people",
      "description": "Hosts and guests on podcasts and episodes, person pages, follows, and contributing to PodPeopleDB"
    },
    {
      "name": "episodes",
      "description": "Episode actions: download, save, share, bulk ops"
    },
    {
      "name": "playlists",
      "description": "Smart and manual playlists"
    },
    {
      "name": "settings",
      "description": "User and server settings"
    },
    {
      "name": "sync",
      "description": "gpodder / Nextcloud synchronization"
    },
    {
      "name": "tasks",
      "description": "Background tasks and progress"
    },
    {
      "name": "notifications",
      "description": "Durable in-app notifications (Activity center)"
    },
    {
      "name": "feed",
      "description": "Public RSS feed generation"
    },
    {
      "name": "proxy",
      "description": "Media and image proxying"
    },
    {
      "name": "local",
      "description": "Local podcasts and media"
    },
    {
      "name": "youtube",
      "description": "YouTube channel integration"
    }
  ]
}