Skip to content

# 📡 Status

## Overview

The `POST /api/status` endpoint is used to retrieve the status of the given source. It contains information about the source, channels, and other relevant information.

### Request

`POST /api/status`

    {
      "clientVersion": "2.1.2",
      // Your server's global options can be sent in the status request
      "sort": "new",
      "flavor": "mint chocolate chip"
    }

Server Options

Your server's options can be used to customize the experience for the user. For example, you may return different categories, channels, or notices based on their preferences.

### Response

    {
      "id": "example-server",
      "name": "Example Video Server",
      "subtitle": "A demo video streaming service.",
      "description": "This is an example server demonstrating the Hot Tub API structure and capabilities.",
      "iconUrl": "https://example.com/icon.png",
      "color": "#007AFF",
      "status": "active",
      "notices": [
        {
          "status": "warning",
          "message": "Scheduled Maintenance",
          "details": "Our servers will undergo maintenance on January 15th from 2:00-4:00 AM UTC. Some features may be temporarily unavailable.",
          "priority": true,
          "url": null
        },
        {
          "status": "info",
          "message": "New Features Available",
          "details": "Check out our latest update with improved video quality and faster loading times!",
          "priority": false,
          "url": "https://example.com/changelog"
        }
      ],
      "channels": [
        {
          "id": "example-tube",
          "name": "Example Tube",
          "description": "A sample video channel demonstrating the API structure.",
          "premium": false,
          "favicon": "https://example.com/favicon.ico",
          "status": "active",
          "categories": ["Entertainment", "Education", "Music"],
          "options": [
            {
              "id": "quality",
              "title": "Video Quality",
              "systemImage": "video",
              "colorName": "blue",
              "multiSelect": false,
              "options": [
                {
                  "id": "hd",
                  "title": "HD",
                  "description": "High definition videos only"
                },
                {
                  "id": "any",
                  "title": "Any Quality",
                  "description": "Include all video qualities"
                }
              ]
            },
            {
              "id": "duration",
              "title": "Duration",
              "systemImage": "clock",
              "colorName": "orange",
              "multiSelect": true,
              "options": [
                {
                  "id": "short",
                  "title": "Short (< 5 min)",
                  "description": "Videos under 5 minutes"
                },
                {
                  "id": "medium",
                  "title": "Medium (5-20 min)",
                  "description": "Videos between 5-20 minutes"
                },
                {
                  "id": "long",
                  "title": "Long (> 20 min)",
                  "description": "Videos over 20 minutes"
                }
              ]
            }
          ],
          "nsfw": false,
          "ytdlpCommand": "yt-dlp --format best",
          "cacheDuration": 1800
        }
      ],
      "nsfw": false,
      "categories": [
        "Funny",
        "Cute",
        "Action",
        "Adventure",
        "Animation",
        "Comedy",
        "Documentary",
        "Drama"
      ],
      "options": [
        {
          "id": "sort",
          "title": "Sort",
          "systemImage": "arrow.up.arrow.down",
          "colorName": "blue",
          "multiSelect": false,
          "options": [
            {
              "id": "new",
              "title": "New",
              "description": "Sort the videos by newest first."
            },
            {
              "id": "likes",
              "title": "Most Liked",
              "description": "Sort the videos by likes."
            }
          ]
        }
      ],
      "popup": null,
      "filtersFooter": "Help us improve our algorithms by selecting the categories that best describe you. These may not change search results on your source, but they help personalize the overall app experience."
    }

## Field Reference

### ServerStatus Object

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Unique server identifier
`name` | `string` | ✅ | Server display name
`subtitle` | `string` | ⚪ | Brief server description
`description` | `string` | ⚪ | Detailed server description
`iconUrl` | `string` | ⚪ | Server icon/logo URL
`color` | `string` | ⚪ | Brand color (hex code or Swift color names)
`status` | `ChannelStatus` | ⚪ | Server operational status
`notices` | `Notice[]` | ⚪ | Status notices/alerts
`channels` | `Channel[]` | ⚪ | Available content channels
`channelGroups` | `ChannelGroup[]` | ⚪ | Explicit channel picker sections (takes priority over per-channel `groupKey`/`sortOrder`)
`nsfw` | `boolean` | ⚪ | Whether server contains adult content
`categories` | `string[]` | ⚪ | Available content categories
`options` | `ChannelOption[]` | ⚪ | Global server options
`filtersFooter` | `string` | ⚪ | Footer text for filter UI

### ChannelGroup Object

An explicit, ordered section definition for the channel picker. When present, `channelGroups` takes full priority over per-channel `groupKey` and `sortOrder`.

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Unique group identifier
`title` | `string` | ✅ | Section heading displayed in the channel picker
`channelIds` | `string[]` | ✅ | Ordered list of channel IDs belonging to this group

Channel Picker Section Logic

The channel picker builds sections using the following priority order:

1. `channelGroups` (top-level, on ServerStatus) — explicit sections with named titles and an ordered list of channel IDs. Use this for full control over grouping and order.
2. `groupKey` + `sortOrder` (per-channel fields) — lightweight fallback. Channels are grouped by their `groupKey` string; within each group they are sorted by `sortOrder` (ascending), then alphabetically. Use this when you don't want a separate top-level structure.
3. Default — if neither is provided, channels are split into a "Premium" section and a general "Channels" section, each sorted alphabetically.

    // Option A: channelGroups (explicit, recommended for complex layouts)
    {
      "channelGroups": [
        { "id": "featured", "title": "Featured", "channelIds": ["tube-a", "tube-b"] },
        { "id": "niche",    "title": "Niche",    "channelIds": ["tube-c"] }
      ]
    }

    // Option B: groupKey + sortOrder (per-channel, simpler)
    { "id": "tube-a", "groupKey": "Featured", "sortOrder": 1 }
    { "id": "tube-b", "groupKey": "Featured", "sortOrder": 2 }
    { "id": "tube-c", "groupKey": "Niche",    "sortOrder": 1 }

### Channel Object

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Unique channel identifier
`name` | `string` | ✅ | Channel display name
`favicon` | `string` | ⚪ | Channel favicon URL
`status` | `ChannelStatus` | ⚪ | Channel operational status
`categories` | `string[]` | ⚪ | Content categories for this channel — drives the home screen category browser (tapping one runs a search for that term)
`tags` | `ChannelTag[]` | ⚪ | Specialization chips shown in the channel picker (e.g. "4K", "Amateur")
`options` | `ChannelOption[]` | ⚪ | Channel-specific filter options
`maintainers` | `ChannelMaintainer[]` | ⚪ | Attribution entries shown in video cells
`premium` | `boolean` | ⚪ | Whether channel requires premium
`description` | `string` | ⚪ | Channel description
`image` | `string` | ⚪ | Channel banner/hero image URL
`nsfw` | `boolean` | ⚪ | Whether channel contains adult content
`default` | `boolean` | ⚪ | Whether this channel is selected by default
`sortOrder` | `number` | ⚪ | Display order when `channelGroups` is not used — lower values appear first
`groupKey` | `string` | ⚪ | Section key for grouping channels (e.g. `"favorites"`, `"premium"`, or a category name)
`ytdlpCommand` | `string` | ⚪ | Custom yt-dlp command
`cacheDuration` | `number` | ⚪ | Cache duration in seconds — yt-dlp re-extracts video details when expired

Categories vs Tags

- `categories` is a flat list of content keywords (e.g. `"Comedy"`, `"Action"`) shared across videos from this channel. They populate the home screen category browser — tapping one runs a search using that term.
- `tags` are specialization labels for the channel itself (e.g. `"4K"`, `"Amateur"`, `"VR"`) displayed as chips in the channel picker UI. They describe what the site is known for, not individual video content.

### ChannelTag Object

Tags can be supplied as a plain string (legacy) or a typed object — the app accepts both transparently.

Field | Type | Required | Description
--- | --- | --- | ---
`name` | `string` | ✅ | Tag label displayed on the channel chip
`systemImage` | `string` | ⚪ | SF Symbol name shown alongside the tag label

    // Plain string (legacy — still accepted)
    "categories": ["4K", "Amateur"]

    // Object format (recommended — supports icons)
    "tags": [
      { "name": "4K", "systemImage": "4k.tv" },
      { "name": "VR", "systemImage": "visionpro" }
    ]

### ChannelMaintainer Object

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Maintainer identifier
`name` | `string` | ✅ | Display name
`avatar` | `string` | ⚪ | Avatar image URL (canonical)
`role` | `string` | ⚪ | `"maintainer"` (built the integration) or `"upstream"` (federated proxy)

See JSON key names for naming conventions and the legacy `profile_picture_url` avatar key.

### Notice Object

Field | Type | Required | Description
--- | --- | --- | ---
`status` | `string` | ✅ | Notice type ("success", "info", "error", "warning", etc.)
`message` | `string` | ⚪ | Notice title/message
`details` | `string` | ⚪ | Detailed notice description
`priority` | `boolean` | ⚪ | Whether to display prominently on home page
`url` | `string` | ⚪ | Action URL for the notice

### ChannelOption Object

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Unique option identifier
`title` | `string` | ✅ | Option display title
`options` | `ChannelOptionChoice[]` | ✅ | Available choices for this option
`systemImage` | `string` | ⚪ | SF Symbol name for option icon
`colorName` | `string` | ⚪ | Swift color name for theming
`multiSelect` | `boolean` | ⚪ | Whether multiple choices can be selected
`value` | `string\|number\|boolean` | ⚪ | Current option value

### ChannelOptionChoice Object

Field | Type | Required | Description
--- | --- | --- | ---
`id` | `string` | ✅ | Unique choice identifier
`title` | `string` | ✅ | Choice display title
`description` | `string` | ⚪ | Choice description
`options` | `ChannelOption[]` | ⚪ | Nested options shown when this choice is selected

### ChannelStatus Enum

Value | Description
--- | ---
`active` | Channel is online and fully functional (same as `normal` / `ok`)
`normal` | Alias for `active`
`ok` | Alias for `active`
`inactive` | Channel deliberately disabled or suspended
`degraded` | Channel working with reduced quality or performance
`maintenance` | Channel temporarily unavailable due to planned work
`restricted` | Access is limited (e.g. region-locked, paywalled, or subject to a takedown)
`error` | Channel encountered a critical issue
`unknown` | Channel status is not known
`testing` | Channel is in testing mode for development

Implementation Notes

- Only `id` and `name` are truly required for both `ServerStatus` and `Channel`
- Options create hierarchical filter UIs — choices can have nested options
- `priority` notices appear on the home page; others only appear on the lock screen
- Colors support both hex codes (`#FF0000`) and Swift color names (`purple`)
- Channel `tags` accept either plain strings (legacy) or `{ name, systemImage }` objects — mixing both in the same array is fine
- `sortOrder` and `groupKey` are the per-channel fallback for sectioning; `channelGroups` on the server response takes priority when present

Popup System

The popup system allows servers to display onboarding flows, age verification, preferences, and other modal content. Here's an example multi-page onboarding popup:

    {
      "popup": {
        "id": "onboarding",
        "pages": [
          {
            "id": "ageVerification",
            "title": "Welcome to",
            "subtitle": "Example Server",
            "warning": "⚠️ Adult Content Warning",
            "body": "This source contains adult content. You must be 18 years or older to use it. By continuing, you confirm that you meet this requirement and agree to use the app responsibly.",
            "items": [
              {
                "type": "section",
                "title": "Age Verification",
                "items": [
                  {
                    "type": "toggle",
                    "id": "termsToggle",
                    "title": "I am over 18 years of age",
                    "systemImage": "checkmark.seal.fill",
                    "color": "gray",
                    "state": false
                  }
                ]
              }
            ],
            "actions": [
              {
                "title": "Continue",
                "systemImage": "arrow.right.circle.fill",
                "color": "blue",
                "actionType": "next",
                "enabledBy": "termsToggle"
              }
            ]
          },
          {
            "id": "preferences",
            "title": "Choose your Preferences",
            "subtitle": "Personalize Your Experience",
            "body": "Select the type of content you'd like to explore. This can be changed later in the filters menu.",
            "items": [
              {
                "type": "custom",
                "view": "ServerFiltersView"
              }
            ],
            "actions": [
              {
                "title": "Continue",
                "systemImage": "arrow.right.circle.fill",
                "color": "blue",
                "actionType": "next"
              }
            ]
          }
        ]
      }
    }

Popup Features:

- Multi-page flows - Create step-by-step onboarding experiences
- Conditional actions - Use `enabledBy` to require toggle states before proceeding
- Custom views - Embed specialized UI like `ServerFiltersView` for complex interactions
- Rich content - Support for titles, subtitles, warnings, body text, and actions
- Interactive controls - Toggles, buttons, and sections for user input

Was this page helpful?
Thanks for your feedback!
Thanks for your feedback! Help us improve this page by