{
  "openapi": "3.1.0",
  "info": {
    "title": "cheapass API",
    "version": "1.0.0",
    "description": "Utility APIs under one $5/mo bill. This spec is generated from the cheapass product catalog (GET /v1/products) — the single source of truth. Endpoints marked `x-cheapass-status: coming_soon` are specced but return 501 until shipped.",
    "contact": {
      "url": "https://cheapass.dev"
    }
  },
  "servers": [
    {
      "url": "https://api.cheapass.dev"
    }
  ],
  "tags": [
    {
      "name": "Social",
      "description": "Post to X, Bluesky, and Threads through one headless API (BYOK)."
    },
    {
      "name": "Social: Platforms",
      "description": "Social — Platforms"
    },
    {
      "name": "Social: Connections",
      "description": "Social — Connections"
    },
    {
      "name": "Social: OAuth",
      "description": "Social — OAuth"
    },
    {
      "name": "Social: Posting",
      "description": "Social — Posting"
    },
    {
      "name": "Social: Intelligence",
      "description": "Social — Intelligence"
    },
    {
      "name": "Social: Voices",
      "description": "Social — Voices"
    },
    {
      "name": "Social: Listening",
      "description": "Social — Listening"
    },
    {
      "name": "Assistant",
      "description": "A read-only AI helper for finding feeds, your subscriptions, and the cheapass CLI."
    },
    {
      "name": "Assistant: Account",
      "description": "Assistant — Account"
    },
    {
      "name": "Feeds",
      "description": "Curated RSS/Atom reader. Each source is fetched once globally; reads are fast and deduped."
    },
    {
      "name": "Feeds: Catalog",
      "description": "Feeds — Catalog"
    },
    {
      "name": "Feeds: Subscriptions",
      "description": "Feeds — Subscriptions"
    },
    {
      "name": "Feeds: Reading",
      "description": "Feeds — Reading"
    },
    {
      "name": "Feeds: Folders",
      "description": "Feeds — Folders"
    },
    {
      "name": "Connect",
      "description": "A reusable OAuth connection vault. Authenticate once, request scoped tokens from any project."
    },
    {
      "name": "Connect: Providers",
      "description": "Connect — Providers"
    },
    {
      "name": "Connect: Connections",
      "description": "Connect — Connections"
    },
    {
      "name": "Connect: Tokens",
      "description": "Connect — Tokens"
    },
    {
      "name": "RSS",
      "description": "Fetch, discover, convert, merge, and monitor feeds — anything in, normalized items out."
    },
    {
      "name": "RSS: Converters",
      "description": "RSS — Converters"
    },
    {
      "name": "RSS: Monitors",
      "description": "RSS — Monitors"
    },
    {
      "name": "RSS: Hosted feeds",
      "description": "RSS — Hosted feeds"
    },
    {
      "name": "RSS: Discover",
      "description": "RSS — Discover"
    },
    {
      "name": "Web",
      "description": "URL in, clean data out — markdown for RAG, metadata, a real headless browser, change monitoring."
    },
    {
      "name": "Text",
      "description": "Cheap text utilities — summarize, extract entities, classify, detect language & sentiment."
    },
    {
      "name": "Search",
      "description": "Web and news search through one API, plus trending detection across your feeds."
    },
    {
      "name": "Data",
      "description": "One API over dozens of free public datasets — weather, finance, health, drugs, gov, science, and more."
    },
    {
      "name": "Data: Weather & earth",
      "description": "Data — Weather & earth"
    },
    {
      "name": "Data: Money & markets",
      "description": "Data — Money & markets"
    },
    {
      "name": "Data: US government",
      "description": "Data — US government"
    },
    {
      "name": "Data: Nutrition & fitness",
      "description": "Data — Nutrition & fitness"
    },
    {
      "name": "Data: Health & medicine",
      "description": "Data — Health & medicine"
    },
    {
      "name": "Data: Science & space",
      "description": "Data — Science & space"
    },
    {
      "name": "Data: Reference & culture",
      "description": "Data — Reference & culture"
    },
    {
      "name": "Geo",
      "description": "Geocoding, boundaries, places, routing, timezones, IP & country lookups — one location API."
    },
    {
      "name": "Geo: Geocoding",
      "description": "Geo — Geocoding"
    },
    {
      "name": "Geo: Boundaries & regions",
      "description": "Geo — Boundaries & regions"
    },
    {
      "name": "Geo: Routing & distance",
      "description": "Geo — Routing & distance"
    },
    {
      "name": "Geo: Lookups",
      "description": "Geo — Lookups"
    },
    {
      "name": "Geo: Parcels",
      "description": "Geo — Parcels"
    },
    {
      "name": "Utils",
      "description": "Small, fast developer utilities — QR, favicon, avatars, hashing, DNS, validation, and more."
    },
    {
      "name": "Utils: Generators",
      "description": "Utils — Generators"
    },
    {
      "name": "Utils: Validation & lookup",
      "description": "Utils — Validation & lookup"
    },
    {
      "name": "Utils: Encoding & crypto",
      "description": "Utils — Encoding & crypto"
    },
    {
      "name": "Utils: Text",
      "description": "Utils — Text"
    },
    {
      "name": "Events",
      "description": "Real-time structured event streams — disasters, space, aviation, internet health."
    },
    {
      "name": "Events: Natural hazards",
      "description": "Events — Natural hazards"
    },
    {
      "name": "Events: Space & sky",
      "description": "Events — Space & sky"
    },
    {
      "name": "Events: Geopolitics & internet",
      "description": "Events — Geopolitics & internet"
    },
    {
      "name": "Events: Aviation & maritime",
      "description": "Events — Aviation & maritime"
    },
    {
      "name": "Events: Delivery",
      "description": "Events — Delivery"
    },
    {
      "name": "Transit",
      "description": "Public-transit agencies, routes, stops, real-time positions, and trip planning."
    },
    {
      "name": "Links",
      "description": "Create branded short links and track clicks."
    },
    {
      "name": "OG Images",
      "description": "Social-card images from a GET request — a URL you can put straight in an og:image tag."
    },
    {
      "name": "Trends",
      "description": "News-anchored cultural momentum. Track how much the world is paying attention to a term over time, and what's rising now."
    },
    {
      "name": "Trends: Watchlist",
      "description": "Trends — Watchlist"
    },
    {
      "name": "Trends: Reading",
      "description": "Trends — Reading"
    },
    {
      "name": "Trends: Discovery",
      "description": "Trends — Discovery"
    },
    {
      "name": "Trends: Topics",
      "description": "Trends — Topics"
    },
    {
      "name": "Sports",
      "description": "Scores for 40+ leagues from upstream APIs we no longer name. Two tiers: Sports Scores ($10/mo, a fresh snapshot every ~10s) and Live Sports Scores ($100/mo, sub-second push over WebSocket). Paid plan required."
    },
    {
      "name": "Sports: Reference",
      "description": "Sports — Reference"
    },
    {
      "name": "Sports: Scores",
      "description": "Sports — Scores"
    },
    {
      "name": "Sports: Game detail",
      "description": "Sports — Game detail"
    },
    {
      "name": "Sports: News",
      "description": "Sports — News"
    },
    {
      "name": "CV",
      "description": "Computer vision and image processing over HTTP. OpenCV and libvips do the hard part; we run them and forward the bill."
    },
    {
      "name": "CV: Catalog",
      "description": "CV — Catalog"
    },
    {
      "name": "CV: Detect",
      "description": "CV — Detect"
    },
    {
      "name": "CV: Transform",
      "description": "CV — Transform"
    },
    {
      "name": "CV: Motion",
      "description": "CV — Motion"
    },
    {
      "name": "CV: Edges",
      "description": "CV — Edges"
    },
    {
      "name": "CV: Tone",
      "description": "CV — Tone"
    },
    {
      "name": "CV: Morphology",
      "description": "CV — Morphology"
    },
    {
      "name": "CV: Geometry",
      "description": "CV — Geometry"
    },
    {
      "name": "CV: Media",
      "description": "CV — Media"
    },
    {
      "name": "CV: Video",
      "description": "CV — Video"
    },
    {
      "name": "CV: Pipeline",
      "description": "CV — Pipeline"
    },
    {
      "name": "CV: Raw bridge",
      "description": "CV — Raw bridge"
    },
    {
      "name": "Games",
      "description": "A bring-your-own-game multiplayer engine: rooms, presence, chat, relay, leaderboards."
    },
    {
      "name": "Games: Rooms",
      "description": "Games — Rooms"
    },
    {
      "name": "Games: Scores",
      "description": "Games — Scores"
    },
    {
      "name": "Games: Site keys",
      "description": "Games — Site keys"
    },
    {
      "name": "Podcasts",
      "description": "Upload audio segments, get a hosted podcast: stitched episodes, RSS, CDN, analytics."
    },
    {
      "name": "Podcasts: Shows",
      "description": "Podcasts — Shows"
    },
    {
      "name": "Podcasts: Episodes",
      "description": "Podcasts — Episodes"
    },
    {
      "name": "Podcasts: Distribution",
      "description": "Podcasts — Distribution"
    },
    {
      "name": "Podcasts: Analytics",
      "description": "Podcasts — Analytics"
    },
    {
      "name": "Podcasts: Public",
      "description": "Podcasts — Public"
    },
    {
      "name": "Platform",
      "description": "The account & meta API under every product: identity, keys, catalog, health, OpenAPI."
    },
    {
      "name": "Platform: Identity",
      "description": "Platform — Identity"
    },
    {
      "name": "Platform: Keys",
      "description": "Platform — Keys"
    },
    {
      "name": "Platform: Credentials",
      "description": "Platform — Credentials"
    },
    {
      "name": "Platform: Projects",
      "description": "Platform — Projects"
    },
    {
      "name": "Platform: Catalog",
      "description": "Platform — Catalog"
    },
    {
      "name": "Platform: Health",
      "description": "Platform — Health"
    },
    {
      "name": "Platform: Device auth",
      "description": "Platform — Device auth"
    },
    {
      "name": "Gate",
      "description": "One password, any site. Put a shared password in front of a preview, a staging box, a private page."
    },
    {
      "name": "Gate: Gates",
      "description": "Gate — Gates"
    },
    {
      "name": "Gate: Unlock",
      "description": "Gate — Unlock"
    }
  ],
  "paths": {
    "/v1/social/platforms": {
      "get": {
        "summary": "List supported social platforms and their capabilities.",
        "description": "List supported social platforms and their capabilities.\n\n**Example:**\n\n```\n[\n  { \"platform\": \"x\", \"authType\": \"oauth2\", \"capabilities\": { \"reply\": true, \"media\": true, \"maxTextLength\": 25000 } },\n  { \"platform\": \"bluesky\", \"authType\": \"app_password\", \"capabilities\": { \"reply\": false, \"media\": false, \"maxTextLength\": 300 } },\n  { \"platform\": \"threads\", \"authType\": \"oauth2\", \"capabilities\": { \"reply\": true, \"media\": false, \"maxTextLength\": 500 } }\n]\n```",
        "tags": [
          "Social",
          "Social: Platforms"
        ],
        "operationId": "get_v1_social_platforms",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Platforms",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "platform": {
                        "description": "Platform id.",
                        "type": "string"
                      },
                      "authType": {
                        "description": "How this platform authenticates.",
                        "type": "string"
                      },
                      "capabilities": {
                        "description": "What the adapter supports.",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "required": [
                      "platform",
                      "authType",
                      "capabilities"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/platforms/{platform}/connections": {
      "get": {
        "summary": "List this account's saved connections for a platform.",
        "description": "List this account's saved connections for a platform.",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "get_v1_social_platforms__platform_connections",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "description": "Platform id: \"x\" | \"bluesky\" | \"threads\".",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Connection id.",
                        "type": "string"
                      },
                      "platform": {
                        "description": "Platform id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name.",
                        "type": "string"
                      },
                      "authType": {
                        "description": "oauth2 | app_password | token.",
                        "type": "string"
                      },
                      "accountHandle": {
                        "description": "Platform handle, once known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "accountId": {
                        "description": "Platform account id, once known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "isDefault": {
                        "description": "Default connection in its scope.",
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "id",
                      "platform",
                      "name",
                      "authType",
                      "isDefault"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Register a BYOK connection (X app creds, Bluesky app password, Threads token).",
        "description": "Register a BYOK connection (X app creds, Bluesky app password, Threads token).",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "post_v1_social_platforms__platform_connections",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "description": "Platform id: \"x\" | \"bluesky\" | \"threads\".",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "description": "Body varies by platform: X wants an OAuth2 app, Bluesky an app password, Threads an access token.",
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "projectId": {
                        "description": "Project scope for the connection (defaults to the key's project, else Global).",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name for this connection.",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "clientId": {
                        "description": "Your X OAuth2 app's client id.",
                        "type": "string",
                        "minLength": 1
                      },
                      "clientSecret": {
                        "description": "Your X OAuth2 app's client secret (encrypted at rest).",
                        "type": "string",
                        "minLength": 1
                      },
                      "isDefault": {
                        "description": "Make this the default X connection in its scope.",
                        "default": true,
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "name",
                      "clientId",
                      "clientSecret",
                      "isDefault"
                    ],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "projectId": {
                        "description": "Project scope for the connection.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name for this connection.",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "identifier": {
                        "description": "Bluesky handle or DID.",
                        "type": "string",
                        "minLength": 1
                      },
                      "appPassword": {
                        "description": "A Bluesky app password (encrypted at rest — never your main password).",
                        "type": "string",
                        "minLength": 1
                      },
                      "service": {
                        "description": "PDS service URL (defaults to bsky.social).",
                        "type": "string",
                        "format": "uri"
                      },
                      "isDefault": {
                        "description": "Make this the default Bluesky connection in its scope.",
                        "default": true,
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "name",
                      "identifier",
                      "appPassword",
                      "isDefault"
                    ],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "projectId": {
                        "description": "Project scope for the connection.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name for this connection.",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "accessToken": {
                        "description": "A Threads Graph-API access token (encrypted at rest).",
                        "type": "string",
                        "minLength": 1
                      },
                      "expiresAt": {
                        "description": "Token expiry (ISO 8601).",
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
                      },
                      "isDefault": {
                        "description": "Make this the default Threads connection in its scope.",
                        "default": true,
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "name",
                      "accessToken",
                      "isDefault"
                    ],
                    "additionalProperties": false
                  }
                ]
              },
              "example": {
                "name": "personal",
                "identifier": "erich.bsky.social",
                "appPassword": "xxxx-xxxx-xxxx-xxxx"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "platform": {
                      "description": "Platform id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "authType": {
                      "description": "oauth2 | app_password | token.",
                      "type": "string"
                    },
                    "accountHandle": {
                      "description": "Platform handle, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "accountId": {
                      "description": "Platform account id, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "isDefault": {
                      "description": "Default connection in its scope.",
                      "type": "boolean"
                    },
                    "nextStep": {
                      "description": "Present when a browser step remains (X OAuth).",
                      "type": "object",
                      "properties": {
                        "action": {
                          "description": "e.g. \"complete_oauth\".",
                          "type": "string"
                        },
                        "authorizeUrl": {
                          "description": "Where to send the user to finish OAuth.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "action",
                        "authorizeUrl"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "platform",
                    "name",
                    "authType",
                    "isDefault"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/platforms/x/connections/import": {
      "post": {
        "summary": "Import pre-obtained X OAuth tokens directly (skip the hosted authorize flow).",
        "description": "Import pre-obtained X OAuth tokens directly (skip the hosted authorize flow).",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "post_v1_social_platforms_x_connections_import",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "projectId": {
                    "description": "Project scope for the connection.",
                    "type": "string"
                  },
                  "name": {
                    "description": "Display name for this connection.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "clientId": {
                    "description": "Your X OAuth2 app's client id.",
                    "type": "string",
                    "minLength": 1
                  },
                  "clientSecret": {
                    "description": "Your X OAuth2 app's client secret.",
                    "type": "string",
                    "minLength": 1
                  },
                  "accessToken": {
                    "description": "An existing X access token to import.",
                    "type": "string",
                    "minLength": 1
                  },
                  "refreshToken": {
                    "description": "Refresh token, if you have one.",
                    "type": "string"
                  },
                  "expiresAt": {
                    "description": "Access-token expiry (ISO 8601).",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
                  },
                  "isDefault": {
                    "description": "Make this the default X connection in its scope.",
                    "default": true,
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "clientId",
                  "clientSecret",
                  "accessToken",
                  "isDefault"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "imported",
                "clientId": "cid",
                "clientSecret": "cs",
                "accessToken": "tok"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "platform": {
                      "description": "Platform id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "authType": {
                      "description": "oauth2 | app_password | token.",
                      "type": "string"
                    },
                    "accountHandle": {
                      "description": "Platform handle, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "accountId": {
                      "description": "Platform account id, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "isDefault": {
                      "description": "Default connection in its scope.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "platform",
                    "name",
                    "authType",
                    "isDefault"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/platforms/{platform}/connections/{id}": {
      "get": {
        "summary": "One connection by id (identity/bookkeeping only — credentials are never returned).",
        "description": "One connection by id (identity/bookkeeping only — credentials are never returned).",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "get_v1_social_platforms__platform_connections__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "description": "Platform id: \"x\" | \"bluesky\" | \"threads\".",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "platform": {
                      "description": "Platform id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "authType": {
                      "description": "oauth2 | app_password | token.",
                      "type": "string"
                    },
                    "accountHandle": {
                      "description": "Platform handle, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "accountId": {
                      "description": "Platform account id, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "isDefault": {
                      "description": "Default connection in its scope.",
                      "type": "boolean"
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    },
                    "updatedAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "platform",
                    "name",
                    "authType",
                    "isDefault",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a connection by id.",
        "description": "Delete a connection by id.",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "delete_v1_social_platforms__platform_connections__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "description": "Platform id: \"x\" | \"bluesky\" | \"threads\".",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The deleted connection id.",
                      "type": "string"
                    },
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/platforms/{platform}/connections/{id}/default": {
      "patch": {
        "summary": "Mark a connection as the default for its platform.",
        "description": "Mark a connection as the default for its platform.",
        "tags": [
          "Social",
          "Social: Connections"
        ],
        "operationId": "patch_v1_social_platforms__platform_connections__id_default",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "description": "Platform id: \"x\" | \"bluesky\" | \"threads\".",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "isDefault": {
                    "description": "true to promote this connection to default in its scope; false to demote.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "isDefault"
                ],
                "additionalProperties": false
              },
              "example": {
                "isDefault": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "isDefault": {
                      "description": "The new default state.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "isDefault"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/platforms/x/oauth/authorize": {
      "get": {
        "summary": "Start the X OAuth 2.0 PKCE flow. Returns { authorizeUrl } to open in a browser.",
        "description": "Start the X OAuth 2.0 PKCE flow. Returns { authorizeUrl } to open in a browser.",
        "tags": [
          "Social",
          "Social: OAuth"
        ],
        "operationId": "get_v1_social_platforms_x_oauth_authorize",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "OAuth",
        "parameters": [
          {
            "name": "connection_id",
            "in": "query",
            "required": true,
            "description": "The X connection to authorize.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "redirect_after",
            "in": "query",
            "required": false,
            "description": "URL to send the browser to after the OAuth dance.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "302 to X's OAuth consent screen."
          }
        }
      }
    },
    "/v1/social/posts": {
      "post": {
        "summary": "Cross-post to multiple platforms in one call (default connection per target unless overridden). Pass scheduledAt (ISO 8601) to post later instead of now.",
        "description": "Cross-post to multiple platforms in one call (default connection per target unless overridden). Pass scheduledAt (ISO 8601) to post later instead of now.\n\n**Example:**\n\n```\n{\n  \"status\": 207,\n  \"summary\": \"2 of 3 posted\",\n  \"results\": [\n    { \"platform\": \"x\", \"ok\": true, \"id\": \"1799…\" },\n    { \"platform\": \"bluesky\", \"ok\": true, \"uri\": \"at://…\" },\n    { \"platform\": \"threads\", \"ok\": false, \"error\": \"token expired\" }\n  ]\n}\n```",
        "tags": [
          "Social",
          "Social: Posting"
        ],
        "operationId": "post_v1_social_posts",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Posting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "The post text (platform limits apply per target).",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 25000
                  },
                  "replyTo": {
                    "description": "Post id to reply to (applies to every target unless overridden per target).",
                    "type": "string"
                  },
                  "mediaIds": {
                    "description": "Previously-uploaded media ids to attach.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "targets": {
                    "description": "Where to post — at least one target.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "description": "Platform id shorthand (\"x\" | \"bluesky\" | \"threads\") — uses that platform's default connection.",
                          "type": "string"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "platform": {
                              "description": "Platform id.",
                              "type": "string"
                            },
                            "connectionId": {
                              "description": "Specific connection (defaults to the platform default).",
                              "type": "string"
                            },
                            "replyTo": {
                              "description": "Platform-native post id to reply to on this target.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "platform"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    }
                  },
                  "scheduledAt": {
                    "description": "ISO 8601 datetime to post at instead of now (min 1 minute, max 1 year out). Returns 202 with a post id; cancel with DELETE /v1/social/posts/:id while still scheduled.",
                    "type": "string"
                  }
                },
                "required": [
                  "text",
                  "targets"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Hello from cheapass",
                "targets": [
                  "bluesky"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "anyOf": [
                    {
                      "description": "Immediate post (no scheduledAt).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Post record id (also in GET /v1/social/posts).",
                          "type": "string"
                        },
                        "status": {
                          "description": "201 all posted · 207 partial · 502 all failed.",
                          "type": "number"
                        },
                        "summary": {
                          "type": "object",
                          "properties": {
                            "total": {
                              "description": "Targets attempted.",
                              "type": "number"
                            },
                            "posted": {
                              "description": "Targets that succeeded.",
                              "type": "number"
                            },
                            "failed": {
                              "description": "Targets that failed.",
                              "type": "number"
                            }
                          },
                          "required": [
                            "total",
                            "posted",
                            "failed"
                          ],
                          "additionalProperties": false
                        },
                        "results": {
                          "description": "Per-target result: { platform, status: posted|failed, post? | error? }.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          }
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "summary",
                        "results"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "description": "202 — stored for the dispatcher (scheduledAt was set).",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Scheduled post id — cancel with DELETE /v1/social/posts/:id.",
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "const": "scheduled"
                        },
                        "scheduledAt": {
                          "description": "Normalized UTC dispatch time.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "status",
                        "scheduledAt"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Post history and the pending scheduled queue (filter with ?status=scheduled).",
        "description": "Post history and the pending scheduled queue (filter with ?status=scheduled).",
        "tags": [
          "Social",
          "Social: Posting"
        ],
        "operationId": "get_v1_social_posts",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Posting",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter to one status (e.g. scheduled for the pending queue).",
            "schema": {
              "type": "string",
              "enum": [
                "scheduled",
                "posting",
                "posted",
                "partial",
                "failed",
                "canceled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max rows (default 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "posts": {
                      "description": "Caller's posts, newest first.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "Post record id.",
                            "type": "string"
                          },
                          "text": {
                            "description": "The post text.",
                            "type": "string"
                          },
                          "targets": {
                            "description": "Normalized targets.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            }
                          },
                          "status": {
                            "description": "scheduled | posting | posted | partial | failed | canceled.",
                            "type": "string",
                            "enum": [
                              "scheduled",
                              "posting",
                              "posted",
                              "partial",
                              "failed",
                              "canceled"
                            ]
                          },
                          "scheduledAt": {
                            "description": "Dispatch time for scheduled posts.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "results": {
                            "description": "Per-target outcomes once attempted.",
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {}
                                }
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "error": {
                            "description": "Row-level error (e.g. dispatch_lost).",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "createdAt": {
                            "description": "ISO timestamp.",
                            "type": "string"
                          },
                          "dispatchedAt": {
                            "description": "When the post loop ran.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "text",
                          "targets",
                          "status",
                          "scheduledAt",
                          "results",
                          "error",
                          "createdAt",
                          "dispatchedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "posts"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/posts/x": {
      "post": {
        "summary": "Post to X only (shortcut for a single-target X post).",
        "description": "Post to X only (shortcut for a single-target X post).",
        "tags": [
          "Social",
          "Social: Posting"
        ],
        "operationId": "post_v1_social_posts_x",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Posting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "The post text.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 25000
                  },
                  "connectionId": {
                    "description": "Specific X connection to post from (defaults to the default X connection).",
                    "type": "string"
                  },
                  "replyToTweetId": {
                    "description": "X post id to reply to.",
                    "type": "string"
                  },
                  "mediaIds": {
                    "description": "Previously-uploaded media ids.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Hello X"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "The created X post: { id, url?, ... } (platform-shaped).",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/posts/{id}": {
      "delete": {
        "summary": "Cancel a scheduled post that hasn't dispatched yet (409 once it has).",
        "description": "Cancel a scheduled post that hasn't dispatched yet (409 once it has).",
        "tags": [
          "Social",
          "Social: Posting"
        ],
        "operationId": "delete_v1_social_posts__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Posting",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Post record id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "409 not_cancelable unless the row is still scheduled.",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The canceled post id.",
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "const": "canceled"
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/best-times": {
      "get": {
        "summary": "Curated best-times-to-post windows per platform + ready-made slot suggestions.",
        "description": "Curated best-times-to-post windows per platform + ready-made slot suggestions.",
        "tags": [
          "Social",
          "Social: Intelligence"
        ],
        "operationId": "get_v1_social_best-times",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Intelligence",
        "parameters": [
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Platform id (default \"x\").",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "Echoed into the response — slot hours are audience-local.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Suggested slots to return (default 3).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "platform": {
                      "description": "Platform the data is for.",
                      "type": "string"
                    },
                    "timezone": {
                      "description": "Echo of the requested timezone; hours are audience-local.",
                      "type": "string"
                    },
                    "windows": {
                      "description": "Top engagement windows, best first.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "days": {
                            "type": "string",
                            "enum": [
                              "weekdays",
                              "weekends"
                            ]
                          },
                          "hour": {
                            "description": "0–23, audience-local.",
                            "type": "number"
                          },
                          "score": {
                            "description": "0–100 relative engagement.",
                            "type": "number"
                          }
                        },
                        "required": [
                          "days",
                          "hour",
                          "score"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "suggestedSlots": {
                      "description": "Ready-made \"HH:00\" slot times, ≥2h apart.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "platform",
                    "timezone",
                    "windows",
                    "suggestedSlots"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/compose": {
      "post": {
        "summary": "Generate post/reply drafts in one of your registered voices (fits X's weighted 280).",
        "description": "Generate post/reply drafts in one of your registered voices (fits X's weighted 280).",
        "tags": [
          "Social",
          "Social: Intelligence"
        ],
        "operationId": "post_v1_social_compose",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Intelligence",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "voice": {
                    "description": "Slug of a registered voice profile.",
                    "type": "string",
                    "minLength": 1
                  },
                  "task": {
                    "description": "post = announce something; reply = respond to a found post.",
                    "type": "string",
                    "enum": [
                      "post",
                      "reply"
                    ]
                  },
                  "headline": {
                    "description": "post task: what the post announces.",
                    "type": "string"
                  },
                  "url": {
                    "description": "post task: URL the post must include.",
                    "type": "string"
                  },
                  "replyToAuthor": {
                    "description": "reply task: author handle of the post being replied to.",
                    "type": "string"
                  },
                  "replyToText": {
                    "description": "reply task: text of the post being replied to.",
                    "type": "string"
                  },
                  "notes": {
                    "description": "Optional operator guidance for this generation.",
                    "type": "string"
                  },
                  "count": {
                    "description": "Drafts to return (default 3).",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3
                  }
                },
                "required": [
                  "voice",
                  "task"
                ],
                "additionalProperties": false
              },
              "example": {
                "voice": "housevoice",
                "task": "post",
                "headline": "We shipped a thing",
                "url": "https://example.com/thing"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "voice": {
                      "type": "string"
                    },
                    "task": {
                      "type": "string"
                    },
                    "drafts": {
                      "description": "Voice-matched drafts, each within X's weighted 280.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "voice",
                    "task",
                    "drafts"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/voices/{slug}": {
      "put": {
        "summary": "Register or update a voice profile — the style guide compose writes in.",
        "description": "Register or update a voice profile — the style guide compose writes in.",
        "tags": [
          "Social",
          "Social: Voices"
        ],
        "operationId": "put_v1_social_voices__slug",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Voices",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Voice slug (your identifier).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Display name for the voice.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "guidelines": {
                    "description": "The style guide that defines this voice (markdown fine, ≤32k chars).",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32000
                  }
                },
                "required": [
                  "name",
                  "guidelines"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "House voice",
                "guidelines": "Dry. Precise. No exclamation marks."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "created": {
                      "description": "true on first upsert.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "slug",
                    "created"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "One voice profile, including its full guidelines.",
        "description": "One voice profile, including its full guidelines.",
        "tags": [
          "Social",
          "Social: Voices"
        ],
        "operationId": "get_v1_social_voices__slug",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Voices",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "guidelines": {
                      "type": "string"
                    },
                    "guidelinesChars": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "slug",
                    "name",
                    "guidelines",
                    "guidelinesChars",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a voice profile.",
        "description": "Delete a voice profile.",
        "tags": [
          "Social",
          "Social: Voices"
        ],
        "operationId": "delete_v1_social_voices__slug",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Voices",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "slug",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/voices": {
      "get": {
        "summary": "List your voice profiles.",
        "description": "List your voice profiles.",
        "tags": [
          "Social",
          "Social: Voices"
        ],
        "operationId": "get_v1_social_voices",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Voices",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "voices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "guidelinesChars": {
                            "description": "Size of the stored guide.",
                            "type": "number"
                          },
                          "updatedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "slug",
                          "name",
                          "guidelinesChars",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "voices"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/watches": {
      "post": {
        "summary": "Watch mentions, keywords, or an account; found posts land in your inbox. Reply modes: off / queue / auto.",
        "description": "Watch mentions, keywords, or an account; found posts land in your inbox. Reply modes: off / queue / auto.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "post_v1_social_watches",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "platform": {
                    "description": "Platform to listen on (X reads are budget-metered; Bluesky search is free).",
                    "type": "string",
                    "enum": [
                      "x",
                      "bluesky"
                    ]
                  },
                  "kind": {
                    "description": "mention = replies/mentions of the connected account; keyword = search terms; account = a specific account's posts.",
                    "type": "string",
                    "enum": [
                      "mention",
                      "keyword",
                      "account"
                    ]
                  },
                  "query": {
                    "description": "Search terms or @handle (unused for mention watches).",
                    "type": "string",
                    "maxLength": 512
                  },
                  "replyMode": {
                    "description": "off = inbox only · queue = draft a reply, wait for approval · auto = send immediately (capped; X automation policy is the caller's responsibility)",
                    "type": "string",
                    "enum": [
                      "off",
                      "queue",
                      "auto"
                    ]
                  },
                  "voiceSlug": {
                    "description": "Voice profile used to draft replies (required for queue/auto).",
                    "type": "string",
                    "maxLength": 120
                  },
                  "autoDailyCap": {
                    "description": "Max auto replies per day for this watch (default 10).",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "replyContext": {
                    "type": "object",
                    "properties": {
                      "links": {
                        "description": "When set, reply drafts MUST include the single most relevant of these links — and no draft is produced when none is relevant.",
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "description": "Human-readable link title (used for relevance).",
                              "type": "string",
                              "minLength": 1
                            },
                            "url": {
                              "description": "The URL to include.",
                              "type": "string",
                              "minLength": 1
                            }
                          },
                          "required": [
                            "title",
                            "url"
                          ],
                          "additionalProperties": false
                        }
                      }
                    },
                    "required": [
                      "links"
                    ],
                    "additionalProperties": false
                  },
                  "pollMode": {
                    "description": "budget (default) = cadence derived from the read budget · daily-peak = one poll per day at the platform's best-times peak hour.",
                    "type": "string",
                    "enum": [
                      "budget",
                      "daily-peak"
                    ]
                  }
                },
                "required": [
                  "platform",
                  "kind"
                ],
                "additionalProperties": false
              },
              "example": {
                "platform": "bluesky",
                "kind": "keyword",
                "query": "teh grep"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Watch id.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List your watches.",
        "description": "List your watches.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "get_v1_social_watches",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "watches": {
                      "description": "{ id, platform, kind, query, enabled, replyMode, voiceSlug, autoDailyCap, nextPollAt }.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "watches"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/watches/{id}": {
      "patch": {
        "summary": "Update a watch (enable/disable, query, reply mode, voice, caps).",
        "description": "Update a watch (enable/disable, query, reply mode, voice, caps).",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "patch_v1_social_watches__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "query": {
                    "type": "string",
                    "maxLength": 512
                  },
                  "replyMode": {
                    "description": "off = inbox only · queue = draft a reply, wait for approval · auto = send immediately (capped; X automation policy is the caller's responsibility)",
                    "type": "string",
                    "enum": [
                      "off",
                      "queue",
                      "auto"
                    ]
                  },
                  "voiceSlug": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "autoDailyCap": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "replyContext": {
                    "type": "object",
                    "properties": {
                      "links": {
                        "description": "When set, reply drafts MUST include the single most relevant of these links — and no draft is produced when none is relevant.",
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "title": {
                              "description": "Human-readable link title (used for relevance).",
                              "type": "string",
                              "minLength": 1
                            },
                            "url": {
                              "description": "The URL to include.",
                              "type": "string",
                              "minLength": 1
                            }
                          },
                          "required": [
                            "title",
                            "url"
                          ],
                          "additionalProperties": false
                        }
                      }
                    },
                    "required": [
                      "links"
                    ],
                    "additionalProperties": false
                  },
                  "pollMode": {
                    "description": "budget (default) = cadence derived from the read budget · daily-peak = one poll per day at the platform's best-times peak hour.",
                    "type": "string",
                    "enum": [
                      "budget",
                      "daily-peak"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "replyMode": "queue"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "updated": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "updated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a watch.",
        "description": "Delete a watch.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "delete_v1_social_watches__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/inbox": {
      "get": {
        "summary": "Posts your watches found, with any drafted replies (filter by status).",
        "description": "Posts your watches found, with any drafted replies (filter by status).",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "get_v1_social_inbox",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "drafted",
                "replied",
                "skipped",
                "failed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "items": {
                      "description": "{ id, watchId, platform, platformPostId, authorHandle, text, url, foundAt, status, draftText, repliedPostId, error }.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    }
                  },
                  "required": [
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/inbox/{id}/reply": {
      "post": {
        "summary": "Send the drafted (or provided) reply to a found post.",
        "description": "Send the drafted (or provided) reply to a found post.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "post_v1_social_inbox__id_reply",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Reply text — omit to send the stored draft.",
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "const": "replied"
                    },
                    "post": {
                      "description": "The sent reply ({ id, url }).",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "post"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/inbox/{id}/skip": {
      "post": {
        "summary": "Dismiss a found post without replying.",
        "description": "Dismiss a found post without replying.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "post_v1_social_inbox__id_skip",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "const": "skipped"
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/social/listen-settings": {
      "get": {
        "summary": "Your monthly X read budget and how much of it this month's polling has used.",
        "description": "Your monthly X read budget and how much of it this month's polling has used.",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "get_v1_social_listen-settings",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "xMonthlyReadBudget": {
                      "description": "Monthly X post-read cap.",
                      "type": "number"
                    },
                    "xReadsUsedThisMonth": {
                      "description": "Reads spent so far this month.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "xMonthlyReadBudget",
                    "xReadsUsedThisMonth"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Set the monthly X read budget (X bills ~$0.005 per post read; pollers stop at the cap).",
        "description": "Set the monthly X read budget (X bills ~$0.005 per post read; pollers stop at the cap).",
        "tags": [
          "Social",
          "Social: Listening"
        ],
        "operationId": "put_v1_social_listen-settings",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "social",
        "x-cheapass-group": "Listening",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "xMonthlyReadBudget": {
                    "description": "Monthly X post-read budget (~$0.005/read on pay-per-use). Pollers hard-stop at the cap.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2000000
                  }
                },
                "required": [
                  "xMonthlyReadBudget"
                ],
                "additionalProperties": false
              },
              "example": {
                "xMonthlyReadBudget": 4000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "xMonthlyReadBudget": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "xMonthlyReadBudget"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/assistant/chat": {
      "post": {
        "summary": "Stream an assistant reply over SSE. Accepts a chat history.",
        "description": "Stream an assistant reply over SSE. Accepts a chat history.\n\n**Example:**\n\n```\ndata: {\"type\":\"tool\",\"name\":\"search_catalog\",\"phase\":\"call\"}\ndata: {\"type\":\"tool\",\"name\":\"search_catalog\",\"phase\":\"result\"}\ndata: {\"type\":\"text\",\"text\":\"To subscribe to BBC News, run: \"}\ndata: {\"type\":\"text\",\"text\":\"cheapass feeds subscribe https://feeds.bbci.co.uk/news/rss.xml\"}\n```",
        "tags": [
          "Assistant"
        ],
        "operationId": "post_v1_assistant_chat",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "assistant",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "messages": {
                    "description": "Chat history (at least one message). The assistant reads the last user-role message as the current turn.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "role": {
                          "description": "Who sent this message.",
                          "type": "string",
                          "enum": [
                            "user",
                            "assistant"
                          ]
                        },
                        "content": {
                          "description": "Message text.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "role",
                        "content"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "messages"
                ],
                "additionalProperties": false
              },
              "example": {
                "messages": [
                  {
                    "role": "user",
                    "content": "how do I subscribe to the BBC news feed?"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server-sent events; one JSON object per `data:` line. The stream simply closes when the turn ends — there is no explicit completion event.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Your usage over the headless API: request counts, error rate, and latency (avg/p95) from the per-request log — scoped to the calling key's project by default (?project=<id> overrides, ?hours= sets the window) — plus assistant token usage and today's budget.",
        "description": "Your usage over the headless API: request counts, error rate, and latency (avg/p95) from the per-request log — scoped to the calling key's project by default (?project=<id> overrides, ?hours= sets the window) — plus assistant token usage and today's budget.",
        "tags": [
          "Assistant",
          "Assistant: Account"
        ],
        "operationId": "get_v1_usage",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "assistant",
        "x-cheapass-group": "Account",
        "parameters": [
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Time window, in hours, for the request-stats aggregate (1–720).",
            "schema": {
              "default": 168,
              "type": "integer",
              "minimum": 1,
              "maximum": 720
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Number of days of assistant-usage history to return (1–365).",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "project",
            "in": "query",
            "required": false,
            "description": "Project id to scope request stats to. Defaults to the calling key's own project scope, or the whole account for a Global key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "requests": {
                      "description": "Request stats from the per-request log (see convex/requests.ts computeStats).",
                      "type": "object",
                      "properties": {
                        "scope": {
                          "description": "Project id the request stats are scoped to, or \"all\" for the whole account.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "hours": {
                          "description": "The resolved time window, in hours.",
                          "type": "number"
                        },
                        "total": {
                          "description": "Total requests in the window.",
                          "type": "number"
                        },
                        "errors": {
                          "description": "Requests in the window with status >= 400.",
                          "type": "number"
                        },
                        "avgMs": {
                          "description": "Average request duration, in ms.",
                          "type": "number"
                        },
                        "p95Ms": {
                          "description": "p95 request duration, in ms.",
                          "type": "number"
                        },
                        "byProduct": {
                          "description": "Per-product request counts, most-requested first.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "product": {
                                "description": "Product id.",
                                "type": "string"
                              },
                              "count": {
                                "description": "Request count for this product in the window.",
                                "type": "number"
                              }
                            },
                            "required": [
                              "product",
                              "count"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "scope",
                        "hours",
                        "total",
                        "errors",
                        "avgMs",
                        "p95Ms",
                        "byProduct"
                      ],
                      "additionalProperties": false
                    },
                    "assistant": {
                      "description": "AI-assistant token usage.",
                      "type": "object",
                      "properties": {
                        "today": {
                          "type": "object",
                          "properties": {
                            "day": {
                              "description": "Date (YYYY-MM-DD).",
                              "type": "string"
                            },
                            "requests": {
                              "description": "Assistant chat requests made that day.",
                              "type": "number"
                            },
                            "tokens": {
                              "description": "Assistant tokens consumed that day.",
                              "type": "number"
                            },
                            "budget": {
                              "description": "Daily AI token budget.",
                              "type": "number"
                            },
                            "remaining": {
                              "description": "Tokens remaining today (budget − tokens, floored at 0).",
                              "type": "number"
                            }
                          },
                          "required": [
                            "day",
                            "requests",
                            "tokens",
                            "budget",
                            "remaining"
                          ],
                          "additionalProperties": false
                        },
                        "history": {
                          "description": "Daily assistant-usage history, most recent first.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "day": {
                                "description": "Date (YYYY-MM-DD).",
                                "type": "string"
                              },
                              "requests": {
                                "description": "Assistant chat requests made that day.",
                                "type": "number"
                              },
                              "tokens": {
                                "description": "Assistant tokens consumed that day.",
                                "type": "number"
                              }
                            },
                            "required": [
                              "day",
                              "requests",
                              "tokens"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "today",
                        "history"
                      ],
                      "additionalProperties": false
                    },
                    "today": {
                      "description": "Back-compat duplicate of assistant.today (pre-projects response shape).",
                      "type": "object",
                      "properties": {
                        "day": {
                          "description": "Date (YYYY-MM-DD).",
                          "type": "string"
                        },
                        "requests": {
                          "description": "Assistant chat requests made that day.",
                          "type": "number"
                        },
                        "tokens": {
                          "description": "Assistant tokens consumed that day.",
                          "type": "number"
                        },
                        "budget": {
                          "description": "Daily AI token budget.",
                          "type": "number"
                        },
                        "remaining": {
                          "description": "Tokens remaining today (budget − tokens, floored at 0).",
                          "type": "number"
                        }
                      },
                      "required": [
                        "day",
                        "requests",
                        "tokens",
                        "budget",
                        "remaining"
                      ],
                      "additionalProperties": false
                    },
                    "history": {
                      "description": "Back-compat duplicate of assistant.history (pre-projects response shape).",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "day": {
                            "description": "Date (YYYY-MM-DD).",
                            "type": "string"
                          },
                          "requests": {
                            "description": "Assistant chat requests made that day.",
                            "type": "number"
                          },
                          "tokens": {
                            "description": "Assistant tokens consumed that day.",
                            "type": "number"
                          }
                        },
                        "required": [
                          "day",
                          "requests",
                          "tokens"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "requests",
                    "assistant",
                    "today",
                    "history"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/categories": {
      "get": {
        "summary": "Curated category taxonomy, grouped into sections (parentName) with a feed count each. Public, no API key. JSON (default) or CSV via ?format=csv.",
        "description": "Curated category taxonomy, grouped into sections (parentName) with a feed count each. Public, no API key. JSON (default) or CSV via ?format=csv.",
        "tags": [
          "Feeds",
          "Feeds: Catalog"
        ],
        "operationId": "get_v1_feeds_categories",
        "security": [],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Catalog",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "slug": {
                        "description": "Category slug.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Category name.",
                        "type": "string"
                      },
                      "parentSlug": {
                        "description": "Parent group slug, when this category belongs to one.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "parentName": {
                        "description": "Parent group's display name.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "count": {
                        "description": "Number of feeds currently in this category.",
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "slug",
                      "name",
                      "parentSlug",
                      "parentName",
                      "count"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/categories/{slug}/feeds": {
      "get": {
        "summary": "Feeds in a category (each with `reliability`).",
        "description": "Feeds in a category (each with `reliability`).",
        "tags": [
          "Feeds",
          "Feeds: Catalog"
        ],
        "operationId": "get_v1_feeds_categories__slug_feeds",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Category slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "feedId": {
                        "description": "Feed id.",
                        "type": "string"
                      },
                      "title": {
                        "description": "Feed title (raw — not run through the cleaner, unlike GET /v1/feeds/sources).",
                        "type": "string"
                      },
                      "url": {
                        "description": "Feed URL.",
                        "type": "string"
                      },
                      "reliability": {
                        "description": "Editorial reliability tier.",
                        "type": "string",
                        "enum": [
                          "mainstream",
                          "watchdog",
                          "unverified"
                        ]
                      }
                    },
                    "required": [
                      "feedId",
                      "title",
                      "url",
                      "reliability"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/subscriptions": {
      "get": {
        "summary": "List your subscriptions.",
        "description": "List your subscriptions.",
        "tags": [
          "Feeds",
          "Feeds: Subscriptions"
        ],
        "operationId": "get_v1_feeds_subscriptions",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Subscriptions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Subscription id.",
                        "type": "string"
                      },
                      "feedId": {
                        "description": "The subscribed feed's id.",
                        "type": "string"
                      },
                      "title": {
                        "description": "Display title — the caller's own title, else the feed's title.",
                        "type": "string"
                      },
                      "url": {
                        "description": "The feed's URL.",
                        "type": "string"
                      },
                      "status": {
                        "description": "Feed health, derived from recent fetch outcomes.",
                        "type": "string",
                        "enum": [
                          "active",
                          "errored",
                          "dead"
                        ]
                      },
                      "reliability": {
                        "description": "Editorial reliability tier.",
                        "type": "string",
                        "enum": [
                          "mainstream",
                          "watchdog",
                          "unverified"
                        ]
                      },
                      "folderId": {
                        "description": "Folder this subscription is filed under, or null.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "id",
                      "feedId",
                      "title",
                      "url",
                      "status",
                      "reliability",
                      "folderId"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Subscribe to a feed URL. Validated, SSRF-guarded, with feed autodiscovery. Optionally place it in a folder.",
        "description": "Subscribe to a feed URL. Validated, SSRF-guarded, with feed autodiscovery. Optionally place it in a folder.",
        "tags": [
          "Feeds",
          "Feeds: Subscriptions"
        ],
        "operationId": "post_v1_feeds_subscriptions",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Subscriptions",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The feed URL to subscribe to (or a page URL — feed autodiscovery runs automatically).",
                    "type": "string",
                    "format": "uri"
                  },
                  "title": {
                    "description": "Display title. Defaults to the feed's own title.",
                    "type": "string"
                  },
                  "folderId": {
                    "description": "Folder to file the subscription under. Not existence- or ownership-checked at subscribe time.",
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://feeds.bbci.co.uk/news/rss.xml"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The subscription's id (existing or newly created).",
                      "type": "string"
                    },
                    "feedId": {
                      "description": "The resolved feed's id.",
                      "type": "string"
                    },
                    "title": {
                      "description": "Resolved title — the caller's `title`, else the feed's own title.",
                      "type": "string"
                    },
                    "url": {
                      "description": "The resolved, canonical feed URL (after autodiscovery, if any).",
                      "type": "string"
                    },
                    "alreadySubscribed": {
                      "description": "True if the caller was already subscribed (response is 200); false on a new subscription (201).",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "feedId",
                    "title",
                    "url",
                    "alreadySubscribed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/subscriptions/{id}": {
      "get": {
        "summary": "One subscription by id.",
        "description": "One subscription by id.",
        "tags": [
          "Feeds",
          "Feeds: Subscriptions"
        ],
        "operationId": "get_v1_feeds_subscriptions__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Subscriptions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Subscription id.",
                      "type": "string"
                    },
                    "feedId": {
                      "description": "The subscribed feed's id.",
                      "type": "string"
                    },
                    "title": {
                      "description": "Display title — the caller's own title, else the feed's title.",
                      "type": "string"
                    },
                    "url": {
                      "description": "The feed's URL.",
                      "type": "string"
                    },
                    "status": {
                      "description": "Feed health, derived from recent fetch outcomes.",
                      "type": "string",
                      "enum": [
                        "active",
                        "errored",
                        "dead"
                      ]
                    },
                    "reliability": {
                      "description": "Editorial reliability tier.",
                      "type": "string",
                      "enum": [
                        "mainstream",
                        "watchdog",
                        "unverified"
                      ]
                    },
                    "folderId": {
                      "description": "Folder this subscription is filed under, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "feedId",
                    "title",
                    "url",
                    "status",
                    "reliability",
                    "folderId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Rename a subscription and/or move it to a folder. `folderId: null` removes it from its folder.",
        "description": "Rename a subscription and/or move it to a folder. `folderId: null` removes it from its folder.",
        "tags": [
          "Feeds",
          "Feeds: Subscriptions"
        ],
        "operationId": "patch_v1_feeds_subscriptions__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Subscriptions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "description": "Rename the subscription.",
                    "type": "string"
                  },
                  "folderId": {
                    "description": "Move to this folder, or null to remove it from its current folder.",
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Renamed"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Subscription id.",
                      "type": "string"
                    },
                    "updated": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "updated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Unsubscribe by subscription id.",
        "description": "Unsubscribe by subscription id.",
        "tags": [
          "Feeds",
          "Feeds: Subscriptions"
        ],
        "operationId": "delete_v1_feeds_subscriptions__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Subscriptions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "removed": {
                      "description": "True if the id existed and belonged to the caller; false otherwise. Always a 200 either way.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/items": {
      "get": {
        "summary": "Aggregated stream across your subscriptions, merged with your per-user state. One comprehensive method: every item returns everything the source exposes — full title, snippet, full article HTML and plain text, all images, categories, every author, source attribution, and both published & updated timestamps. Missing fields are null/[] (not omitted). Available in four formats: JSON (default), CSV for spreadsheets/ETL, and RSS or Atom so the merged stream can be re-subscribed in any reader — pass ?format=json|csv|rss|atom or the matching Accept header.",
        "description": "Aggregated stream across your subscriptions, merged with your per-user state. One comprehensive method: every item returns everything the source exposes — full title, snippet, full article HTML and plain text, all images, categories, every author, source attribution, and both published & updated timestamps. Missing fields are null/[] (not omitted). Available in four formats: JSON (default), CSV for spreadsheets/ETL, and RSS or Atom so the merged stream can be re-subscribed in any reader — pass ?format=json|csv|rss|atom or the matching Accept header.\n\n**Example:**\n\n```\n{\n  \"id\": \"k57…\",\n  \"source\": { \"title\": \"AI | The Verge\", \"url\": \"https://www.theverge.com/rss/ai-artificial-intelligence/index.xml\", \"language\": \"en-US\" },\n  \"title\": \"The film about Sam Altman has been dropped by Amazon MGM\",\n  \"url\": \"https://www.theverge.com/…/sam-altman-film\",\n  \"authors\": [\"Hayden Field\"],\n  \"categories\": [\"AI\", \"News\", \"OpenAI\"],\n  \"publishedAt\": \"2026-06-19T14:15:29.000Z\",\n  \"updatedAt\": \"2026-06-19T14:58:45.000Z\",\n  \"summary\": \"Luca Guadagnino's film about OpenAI CEO Sam Altman…\",\n  \"contentHtml\": \"<p>…full article body…</p>\",\n  \"contentText\": \"…full article body, tags stripped…\",\n  \"image\": \"https://platform.theverge.com/…/STK201_SAM_ALTMAN.jpg\",\n  \"images\": [{ \"url\": \"https://platform.theverge.com/…jpg\", \"type\": \"image/jpeg\" }],\n  \"read\": false, \"starred\": false, \"tags\": []\n}\n```",
        "tags": [
          "Feeds",
          "Feeds: Reading"
        ],
        "operationId": "get_v1_feeds_items",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Reading",
        "parameters": [
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "description": "Only unread items when exactly \"true\". Any other value (or omitting it) is treated as false — a loose passthrough string, matching the old handler's exact `=== \"true\"` check.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max items to return (1–200). Defaults to 50 — also the old code's fallback for non-numeric input or \"0\". Out-of-range and fractional values were silently clamped/truncated before; all now rejected instead (same clamp/truncate→reject class as rss merge's `limit`).",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "feedId",
            "in": "query",
            "required": false,
            "description": "Restrict to one subscribed feed. Loose passthrough — a non-matching id just yields an empty stream.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categorySlug",
            "in": "query",
            "required": false,
            "description": "Restrict to subscriptions in one category. Loose passthrough — an unknown slug just yields an empty stream.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Item id.",
                        "type": "string"
                      },
                      "feedId": {
                        "description": "The source feed's id.",
                        "type": "string"
                      },
                      "source": {
                        "description": "Attribution for the source feed — null only if the feed row itself is missing.",
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "title": {
                                "description": "Source feed title (cleaned).",
                                "type": "string"
                              },
                              "url": {
                                "description": "Source feed URL.",
                                "type": "string"
                              },
                              "language": {
                                "description": "Source language, when known.",
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "title",
                              "url",
                              "language"
                            ],
                            "additionalProperties": false
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "guid": {
                        "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                        "type": "string"
                      },
                      "title": {
                        "description": "Item title (cleaned).",
                        "type": "string"
                      },
                      "url": {
                        "description": "Item URL, when the source provides one.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "authors": {
                        "description": "Author names — merged from author/dc:creator/atom author, de-duped, cleaned.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "categories": {
                        "description": "Categories/tags, cleaned.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "publishedAt": {
                        "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                        "type": "string"
                      },
                      "updatedAt": {
                        "description": "ISO update timestamp, when distinct from publishedAt.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "summary": {
                        "description": "Short plain-text snippet (HTML tags stripped, entities decoded).",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "contentHtml": {
                        "description": "Full article HTML, sanitized to an allow-listed tag/attribute set, when the source provides it.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "contentText": {
                        "description": "Plain-text version of contentHtml (or summary, when there's no dedicated content field).",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "image": {
                        "description": "Primary image URL, when any image was found.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "images": {
                        "description": "All images found on the item.",
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "url": {
                              "description": "Image URL.",
                              "type": "string"
                            },
                            "type": {
                              "description": "MIME type, when known.",
                              "type": "string"
                            },
                            "width": {
                              "description": "Width in pixels, when known.",
                              "type": "number"
                            },
                            "height": {
                              "description": "Height in pixels, when known.",
                              "type": "number"
                            },
                            "length": {
                              "description": "Byte size, when known (e.g. an RSS enclosure).",
                              "type": "number"
                            }
                          },
                          "required": [
                            "url"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "read": {
                        "description": "Whether the caller has marked this item read.",
                        "type": "boolean"
                      },
                      "starred": {
                        "description": "Whether the caller has starred this item.",
                        "type": "boolean"
                      },
                      "tags": {
                        "description": "The caller's own tags on this item.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "id",
                      "feedId",
                      "source",
                      "guid",
                      "title",
                      "url",
                      "authors",
                      "categories",
                      "publishedAt",
                      "updatedAt",
                      "summary",
                      "contentHtml",
                      "contentText",
                      "image",
                      "images",
                      "read",
                      "starred",
                      "tags"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/sources": {
      "get": {
        "summary": "Every source in the catalog (public, no API key). Browse what's available and which categories each belongs to. JSON (default) or CSV via ?format=csv.",
        "description": "Every source in the catalog (public, no API key). Browse what's available and which categories each belongs to. JSON (default) or CSV via ?format=csv.",
        "tags": [
          "Feeds",
          "Feeds: Catalog"
        ],
        "operationId": "get_v1_feeds_sources",
        "security": [],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Catalog",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Feed id.",
                        "type": "string"
                      },
                      "title": {
                        "description": "Feed title (cleaned).",
                        "type": "string"
                      },
                      "url": {
                        "description": "Feed URL.",
                        "type": "string"
                      },
                      "status": {
                        "description": "Feed health, derived from recent fetch outcomes.",
                        "type": "string",
                        "enum": [
                          "active",
                          "errored",
                          "dead"
                        ]
                      },
                      "reliability": {
                        "description": "Editorial reliability tier.",
                        "type": "string",
                        "enum": [
                          "mainstream",
                          "watchdog",
                          "unverified"
                        ]
                      },
                      "language": {
                        "description": "Feed language, when known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "categorySlug": {
                        "description": "Primary category (first) this feed belongs to, or null.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "categorySlugs": {
                        "description": "Every category this feed belongs to.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "id",
                      "title",
                      "url",
                      "status",
                      "reliability",
                      "language",
                      "categorySlug",
                      "categorySlugs"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/sources/{id}/example": {
      "get": {
        "summary": "Public, no API key. One real recent item from a source in the full normalized shape, plus a `fields` map showing exactly which data that source provides. Powers the per-source examples in these docs.",
        "description": "Public, no API key. One real recent item from a source in the full normalized shape, plus a `fields` map showing exactly which data that source provides. Powers the per-source examples in these docs.",
        "tags": [
          "Feeds",
          "Feeds: Catalog"
        ],
        "operationId": "get_v1_feeds_sources__id_example",
        "security": [],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Feed id.",
                          "type": "string"
                        },
                        "title": {
                          "description": "Feed title (raw).",
                          "type": "string"
                        },
                        "url": {
                          "description": "Feed URL.",
                          "type": "string"
                        },
                        "status": {
                          "description": "Feed health, derived from recent fetch outcomes.",
                          "type": "string",
                          "enum": [
                            "active",
                            "errored",
                            "dead"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "title",
                        "url",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "item": {
                      "description": "The source's most recent item, in the full normalized shape, or null if nothing has been fetched from it yet.",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "description": "Item id.",
                              "type": "string"
                            },
                            "feedId": {
                              "description": "The source feed's id.",
                              "type": "string"
                            },
                            "source": {
                              "description": "Attribution for the source feed — null only if the feed row itself is missing.",
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "title": {
                                      "description": "Source feed title (cleaned).",
                                      "type": "string"
                                    },
                                    "url": {
                                      "description": "Source feed URL.",
                                      "type": "string"
                                    },
                                    "language": {
                                      "description": "Source language, when known.",
                                      "anyOf": [
                                        {
                                          "type": "string"
                                        },
                                        {
                                          "type": "null"
                                        }
                                      ]
                                    }
                                  },
                                  "required": [
                                    "title",
                                    "url",
                                    "language"
                                  ],
                                  "additionalProperties": false
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "guid": {
                              "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                              "type": "string"
                            },
                            "title": {
                              "description": "Item title (cleaned).",
                              "type": "string"
                            },
                            "url": {
                              "description": "Item URL, when the source provides one.",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "authors": {
                              "description": "Author names — merged from author/dc:creator/atom author, de-duped, cleaned.",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "categories": {
                              "description": "Categories/tags, cleaned.",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "publishedAt": {
                              "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                              "type": "string"
                            },
                            "updatedAt": {
                              "description": "ISO update timestamp, when distinct from publishedAt.",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "summary": {
                              "description": "Short plain-text snippet (HTML tags stripped, entities decoded).",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "contentHtml": {
                              "description": "Full article HTML, sanitized to an allow-listed tag/attribute set, when the source provides it.",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "contentText": {
                              "description": "Plain-text version of contentHtml (or summary, when there's no dedicated content field).",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "image": {
                              "description": "Primary image URL, when any image was found.",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "images": {
                              "description": "All images found on the item.",
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "description": "Image URL.",
                                    "type": "string"
                                  },
                                  "type": {
                                    "description": "MIME type, when known.",
                                    "type": "string"
                                  },
                                  "width": {
                                    "description": "Width in pixels, when known.",
                                    "type": "number"
                                  },
                                  "height": {
                                    "description": "Height in pixels, when known.",
                                    "type": "number"
                                  },
                                  "length": {
                                    "description": "Byte size, when known (e.g. an RSS enclosure).",
                                    "type": "number"
                                  }
                                },
                                "required": [
                                  "url"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "id",
                            "feedId",
                            "source",
                            "guid",
                            "title",
                            "url",
                            "authors",
                            "categories",
                            "publishedAt",
                            "updatedAt",
                            "summary",
                            "contentHtml",
                            "contentText",
                            "image",
                            "images"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "description": "Which fields this source actually populates. Omitted entirely (`{}`) when `item` is null.",
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "boolean"
                        },
                        "url": {
                          "type": "boolean"
                        },
                        "authors": {
                          "type": "boolean"
                        },
                        "categories": {
                          "type": "boolean"
                        },
                        "summary": {
                          "type": "boolean"
                        },
                        "contentHtml": {
                          "type": "boolean"
                        },
                        "contentText": {
                          "type": "boolean"
                        },
                        "image": {
                          "type": "boolean"
                        },
                        "images": {
                          "type": "boolean"
                        },
                        "updatedAt": {
                          "type": "boolean"
                        },
                        "publishedAt": {
                          "type": "boolean"
                        }
                      },
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "source",
                    "item",
                    "fields"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/items/{id}": {
      "get": {
        "summary": "One item by id, in the full normalized shape, merged with your read/starred/tags state.",
        "description": "One item by id, in the full normalized shape, merged with your read/starred/tags state.",
        "tags": [
          "Feeds",
          "Feeds: Reading"
        ],
        "operationId": "get_v1_feeds_items__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Reading",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Item id.",
                      "type": "string"
                    },
                    "feedId": {
                      "description": "The source feed's id.",
                      "type": "string"
                    },
                    "source": {
                      "description": "Attribution for the source feed — null only if the feed row itself is missing.",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "title": {
                              "description": "Source feed title (cleaned).",
                              "type": "string"
                            },
                            "url": {
                              "description": "Source feed URL.",
                              "type": "string"
                            },
                            "language": {
                              "description": "Source language, when known.",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "title",
                            "url",
                            "language"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "guid": {
                      "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                      "type": "string"
                    },
                    "title": {
                      "description": "Item title (cleaned).",
                      "type": "string"
                    },
                    "url": {
                      "description": "Item URL, when the source provides one.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "authors": {
                      "description": "Author names — merged from author/dc:creator/atom author, de-duped, cleaned.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "categories": {
                      "description": "Categories/tags, cleaned.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "publishedAt": {
                      "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                      "type": "string"
                    },
                    "updatedAt": {
                      "description": "ISO update timestamp, when distinct from publishedAt.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "summary": {
                      "description": "Short plain-text snippet (HTML tags stripped, entities decoded).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "contentHtml": {
                      "description": "Full article HTML, sanitized to an allow-listed tag/attribute set, when the source provides it.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "contentText": {
                      "description": "Plain-text version of contentHtml (or summary, when there's no dedicated content field).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "image": {
                      "description": "Primary image URL, when any image was found.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "images": {
                      "description": "All images found on the item.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "url": {
                            "description": "Image URL.",
                            "type": "string"
                          },
                          "type": {
                            "description": "MIME type, when known.",
                            "type": "string"
                          },
                          "width": {
                            "description": "Width in pixels, when known.",
                            "type": "number"
                          },
                          "height": {
                            "description": "Height in pixels, when known.",
                            "type": "number"
                          },
                          "length": {
                            "description": "Byte size, when known (e.g. an RSS enclosure).",
                            "type": "number"
                          }
                        },
                        "required": [
                          "url"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "read": {
                      "description": "Whether the caller has marked this item read.",
                      "type": "boolean"
                    },
                    "starred": {
                      "description": "Whether the caller has starred this item.",
                      "type": "boolean"
                    },
                    "tags": {
                      "description": "The caller's own tags on this item.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "id",
                    "feedId",
                    "source",
                    "guid",
                    "title",
                    "url",
                    "authors",
                    "categories",
                    "publishedAt",
                    "updatedAt",
                    "summary",
                    "contentHtml",
                    "contentText",
                    "image",
                    "images",
                    "read",
                    "starred",
                    "tags"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Set read/starred/tags on an item (send `false` to mark unread / un-star).",
        "description": "Set read/starred/tags on an item (send `false` to mark unread / un-star).",
        "tags": [
          "Feeds",
          "Feeds: Reading"
        ],
        "operationId": "patch_v1_feeds_items__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Reading",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "read": {
                    "description": "Set read/unread.",
                    "type": "boolean"
                  },
                  "starred": {
                    "description": "Set starred state.",
                    "type": "boolean"
                  },
                  "tags": {
                    "description": "Replace the caller's tags on this item.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "read": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "ok": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/folders": {
      "get": {
        "summary": "List your folders, each with its subscription count.",
        "description": "List your folders, each with its subscription count.",
        "tags": [
          "Feeds",
          "Feeds: Folders"
        ],
        "operationId": "get_v1_feeds_folders",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Folders",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Folder id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Folder name.",
                        "type": "string"
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      },
                      "subscriptionCount": {
                        "description": "Number of subscriptions currently filed under this folder.",
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "createdAt",
                      "subscriptionCount"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a folder to organize subscriptions.",
        "description": "Create a folder to organize subscriptions.",
        "tags": [
          "Feeds",
          "Feeds: Folders"
        ],
        "operationId": "post_v1_feeds_folders",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Folders",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Folder name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Reading list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The created folder's id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Trimmed folder name.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/feeds/folders/{id}": {
      "get": {
        "summary": "One folder by id.",
        "description": "One folder by id.",
        "tags": [
          "Feeds",
          "Feeds: Folders"
        ],
        "operationId": "get_v1_feeds_folders__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Folders",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Folder id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Folder name.",
                      "type": "string"
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    },
                    "subscriptionCount": {
                      "description": "Number of subscriptions currently filed under this folder.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "createdAt",
                    "subscriptionCount"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Rename a folder.",
        "description": "Rename a folder.",
        "tags": [
          "Feeds",
          "Feeds: Folders"
        ],
        "operationId": "patch_v1_feeds_folders__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Folders",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Folder name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Renamed"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Folder id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "The renamed (trimmed) folder name.",
                      "type": "string"
                    },
                    "updated": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "updated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a folder. Subscriptions in it are kept and moved out of the folder.",
        "description": "Delete a folder. Subscriptions in it are kept and moved out of the folder.",
        "tags": [
          "Feeds",
          "Feeds: Folders"
        ],
        "operationId": "delete_v1_feeds_folders__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "feeds",
        "x-cheapass-group": "Folders",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Folder id.",
                      "type": "string"
                    },
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect/providers": {
      "get": {
        "summary": "List supported OAuth providers and their capabilities.",
        "description": "List supported OAuth providers and their capabilities.",
        "tags": [
          "Connect",
          "Connect: Providers"
        ],
        "operationId": "get_v1_connect_providers",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Providers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "Provider id.",
                        "type": "string"
                      },
                      "displayName": {
                        "description": "Human-readable provider name.",
                        "type": "string"
                      },
                      "authType": {
                        "description": "Always \"oauth2\" — connect only supports OAuth2 providers today.",
                        "type": "string",
                        "const": "oauth2"
                      },
                      "pkce": {
                        "description": "Whether this provider's flow uses PKCE.",
                        "type": "boolean"
                      },
                      "defaultScopes": {
                        "description": "Scopes requested when the caller doesn't specify any.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "callbackHint": {
                        "description": "Where the caller must register the OAuth callback URL when creating their app.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "provider",
                      "displayName",
                      "authType",
                      "pkce",
                      "defaultScopes",
                      "callbackHint"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect/connections": {
      "get": {
        "summary": "List your saved connections.",
        "description": "List your saved connections.",
        "tags": [
          "Connect",
          "Connect: Connections"
        ],
        "operationId": "get_v1_connect_connections",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "description": "Filter to one provider's connections.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Connection id.",
                        "type": "string"
                      },
                      "provider": {
                        "description": "Provider id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name.",
                        "type": "string"
                      },
                      "authType": {
                        "description": "Always \"oauth2\" — every connect provider is OAuth2 today.",
                        "type": "string",
                        "const": "oauth2"
                      },
                      "accountHandle": {
                        "description": "Provider account handle, once known (set after OAuth completes).",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "accountId": {
                        "description": "Provider account id, once known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "scopesAuthorized": {
                        "description": "Scopes actually granted.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "connected": {
                        "description": "True once OAuth has completed (accountId is set).",
                        "type": "boolean"
                      },
                      "isDefault": {
                        "description": "Default connection for its provider in its scope.",
                        "type": "boolean"
                      },
                      "projectId": {
                        "description": "Project scope, or null for Global.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      },
                      "updatedAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "provider",
                      "name",
                      "authType",
                      "accountHandle",
                      "accountId",
                      "scopesAuthorized",
                      "connected",
                      "isDefault",
                      "projectId",
                      "createdAt",
                      "updatedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Register a new BYOK OAuth app + start the OAuth flow.",
        "description": "Register a new BYOK OAuth app + start the OAuth flow.",
        "tags": [
          "Connect",
          "Connect: Connections"
        ],
        "operationId": "post_v1_connect_connections",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Connections",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "projectId": {
                    "description": "Project scope for the connection (defaults to the key's project, else Global).",
                    "type": "string"
                  },
                  "provider": {
                    "description": "OAuth provider id — \"github\" | \"google\" | \"linkedin\" | \"x\" | \"discord\" | \"spotify\".",
                    "type": "string",
                    "minLength": 1
                  },
                  "name": {
                    "description": "Display name for this connection.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "clientId": {
                    "description": "Your OAuth app's client id (BYOK).",
                    "type": "string",
                    "minLength": 1
                  },
                  "clientSecret": {
                    "description": "Your OAuth app's client secret (BYOK, encrypted at rest).",
                    "type": "string",
                    "minLength": 1
                  },
                  "scopes": {
                    "description": "Scopes to request. Defaults to the provider's recommended scopes.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "redirectAfter": {
                    "description": "URL to send the browser to once OAuth completes (defaults to the built-in success page).",
                    "type": "string"
                  },
                  "notify": {
                    "description": "RFC 8252 loopback notification target for CLI-driven flows.",
                    "type": "object",
                    "properties": {
                      "port": {
                        "description": "Loopback port the CLI is listening on.",
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 65535
                      },
                      "nonce": {
                        "description": "Shared secret the CLI expects back, to reject spoofed callbacks.",
                        "type": "string",
                        "minLength": 8
                      }
                    },
                    "required": [
                      "port",
                      "nonce"
                    ],
                    "additionalProperties": false
                  },
                  "isDefault": {
                    "description": "Make this the default connection for the provider in its scope.",
                    "default": true,
                    "type": "boolean"
                  }
                },
                "required": [
                  "provider",
                  "name",
                  "clientId",
                  "clientSecret",
                  "isDefault"
                ],
                "additionalProperties": false
              },
              "example": {
                "provider": "github",
                "name": "personal",
                "clientId": "<clientId>",
                "clientSecret": "<clientSecret>"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The created connection's id.",
                      "type": "string"
                    },
                    "provider": {
                      "description": "Provider id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "isDefault": {
                      "description": "Whether this is now the default connection for the provider in its scope.",
                      "type": "boolean"
                    },
                    "connected": {
                      "description": "Always false immediately after creation — OAuth hasn't completed yet.",
                      "type": "boolean",
                      "const": false
                    },
                    "nextStep": {
                      "description": "The browser step the caller (or CLI) must complete to finish connecting.",
                      "type": "object",
                      "properties": {
                        "action": {
                          "description": "What the caller must do next.",
                          "type": "string",
                          "const": "open_authorize_url"
                        },
                        "authorizeUrl": {
                          "description": "Open this URL in a browser to complete OAuth with the provider.",
                          "type": "string"
                        },
                        "stateExpiresAt": {
                          "description": "ISO timestamp — the authorize URL's state expires after this.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "action",
                        "authorizeUrl",
                        "stateExpiresAt"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "provider",
                    "name",
                    "isDefault",
                    "connected",
                    "nextStep"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect/connections/{id}": {
      "get": {
        "summary": "Get one connection (refresh token is never returned).",
        "description": "Get one connection (refresh token is never returned).",
        "tags": [
          "Connect",
          "Connect: Connections"
        ],
        "operationId": "get_v1_connect_connections__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "provider": {
                      "description": "Provider id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "authType": {
                      "description": "Always \"oauth2\" — every connect provider is OAuth2 today.",
                      "type": "string",
                      "const": "oauth2"
                    },
                    "accountHandle": {
                      "description": "Provider account handle, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "accountId": {
                      "description": "Provider account id, once known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "scopesAuthorized": {
                      "description": "Scopes actually granted.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "connected": {
                      "description": "True once OAuth has completed (accountId is set).",
                      "type": "boolean"
                    },
                    "isDefault": {
                      "description": "Default connection for its provider in its scope.",
                      "type": "boolean"
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    },
                    "updatedAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "provider",
                    "name",
                    "authType",
                    "accountHandle",
                    "accountId",
                    "scopesAuthorized",
                    "connected",
                    "isDefault",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a connection.",
        "description": "Delete a connection.",
        "tags": [
          "Connect",
          "Connect: Connections"
        ],
        "operationId": "delete_v1_connect_connections__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The deleted connection's id.",
                      "type": "string"
                    },
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect/connections/{id}/default": {
      "patch": {
        "summary": "Mark a connection as the default for its provider.",
        "description": "Mark a connection as the default for its provider.",
        "tags": [
          "Connect",
          "Connect: Connections"
        ],
        "operationId": "patch_v1_connect_connections__id_default",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Connections",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connection id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "isDefault": {
                    "description": "true to promote this connection to default in its scope; false to demote.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "isDefault"
                ],
                "additionalProperties": false
              },
              "example": {
                "isDefault": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Connection id.",
                      "type": "string"
                    },
                    "isDefault": {
                      "description": "The new default state.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "isDefault"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect/tokens": {
      "post": {
        "summary": "Mint a fresh access token for a connection (refreshes first if stale).",
        "description": "Mint a fresh access token for a connection (refreshes first if stale).\n\n**Example:**\n\n```\n{\n  \"accessToken\": \"gho_xxxxxxxxxxxxxxxxxxxx\",\n  \"expiresAt\": \"2026-06-20T01:30:00.000Z\",\n  \"scopes\": [\"repo\", \"read:user\"]\n}\n```",
        "tags": [
          "Connect",
          "Connect: Tokens"
        ],
        "operationId": "post_v1_connect_tokens",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "connect",
        "x-cheapass-group": "Tokens",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "provider": {
                    "description": "OAuth provider id — \"github\" | \"google\" | \"linkedin\" | \"x\" | \"discord\" | \"spotify\".",
                    "type": "string",
                    "minLength": 1
                  },
                  "connectionId": {
                    "description": "Specific connection to mint from (defaults to the provider's default connection).",
                    "type": "string"
                  }
                },
                "required": [
                  "provider"
                ],
                "additionalProperties": false
              },
              "example": {
                "provider": "github"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "provider": {
                      "description": "Provider id.",
                      "type": "string"
                    },
                    "accessToken": {
                      "description": "Short-lived access token — refreshed first if the stored one was near expiry. The refresh token is never returned.",
                      "type": "string"
                    },
                    "expiresAt": {
                      "description": "ISO timestamp the access token expires at, if the provider reports one.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "scopes": {
                      "description": "Scopes granted to this token.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "provider",
                    "accessToken",
                    "expiresAt",
                    "scopes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/fetch": {
      "post": {
        "summary": "Fetch & parse any feed URL into normalized items. Pass a `since` cursor for delta polling (only newer items).",
        "description": "Fetch & parse any feed URL into normalized items. Pass a `since` cursor for delta polling (only newer items).\n\n**Example:**\n\n```\n{\n  \"items\": [\n    { \"title\": \"…\", \"url\": \"https://…\", \"authors\": [\"…\"], \"categories\": [\"…\"],\n      \"publishedAt\": \"2026-06-19T14:15:29.000Z\", \"summary\": \"…\",\n      \"contentHtml\": \"<p>…</p>\", \"contentText\": \"…\", \"image\": \"https://…\", \"images\": [{ \"url\": \"https://…\" }] }\n  ],\n  \"cursor\": \"2026-06-19T14:15:29.000Z\"\n}\n```",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_fetch",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The feed URL to fetch and parse.",
                    "type": "string",
                    "format": "uri"
                  },
                  "since": {
                    "description": "Cursor from a prior response's `cursor` — return only items strictly newer than it (delta polling).",
                    "type": "string"
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 100.",
                    "default": 100,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "url",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://hnrss.org/frontpage"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cursor": {
                      "description": "Newest publishedAt seen — pass back as `since` next time. null if no item carried a date.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "title",
                    "items",
                    "cursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/discover": {
      "post": {
        "summary": "Auto-discover feed URLs advertised on (or conventionally located at) a site URL.",
        "description": "Auto-discover feed URLs advertised on (or conventionally located at) a site URL.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_discover",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "Page URL to discover feeds on.",
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://news.ycombinator.com/"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "feeds": {
                      "description": "Feeds discovered on (or advertised by) the page.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "url": {
                            "description": "Discovered feed URL.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Feed title, when advertised.",
                            "type": "string"
                          },
                          "type": {
                            "description": "Detected feed format.",
                            "type": "string",
                            "enum": [
                              "rss",
                              "atom",
                              "json"
                            ]
                          }
                        },
                        "required": [
                          "url",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "feeds"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/from-site": {
      "post": {
        "summary": "Synthesize a feed from a feedless page by extracting repeated article blocks (headless render when needed).",
        "description": "Synthesize a feed from a feedless page by extracting repeated article blocks (headless render when needed).",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_from-site",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The feedless page URL to synthesize items from.",
                    "type": "string",
                    "format": "uri"
                  },
                  "selector": {
                    "description": "CSS selector scoping the story blocks. Omit to try a ranked list of common containers.",
                    "type": "string"
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "url",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://news.ycombinator.com/",
                "selector": ".athing"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/from-youtube": {
      "post": {
        "summary": "Turn a YouTube channel or playlist into a normalized feed.",
        "description": "Turn a YouTube channel or playlist into a normalized feed.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_from-youtube",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "channelId": {
                    "description": "YouTube channel id. Only a \"UC…\" (20+ char) id is used directly — anything else falls through to handle/url resolution.",
                    "type": "string"
                  },
                  "handle": {
                    "description": "YouTube @handle (with or without the leading \"@\").",
                    "type": "string"
                  },
                  "url": {
                    "description": "A channel or video page URL to resolve the channel from.",
                    "type": "string",
                    "format": "uri"
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "handle": "@mkbhd"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/from-reddit": {
      "post": {
        "summary": "Turn a subreddit into a normalized feed.",
        "description": "Turn a subreddit into a normalized feed.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_from-reddit",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "subreddit": {
                    "description": "Subreddit name (with or without a leading \"r/\" or \"/r/\").",
                    "type": "string",
                    "minLength": 1
                  },
                  "sort": {
                    "description": "Sort: \"new\" | \"hot\" | \"top\" | \"rising\". Any other value (or omitting it) falls back to \"new\".",
                    "type": "string"
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "subreddit",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "subreddit": "programming",
                "sort": "new"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/from-github": {
      "post": {
        "summary": "Turn a GitHub repo's releases into a normalized feed.",
        "description": "Turn a GitHub repo's releases into a normalized feed.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_from-github",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "owner": {
                    "description": "Repo owner.",
                    "type": "string",
                    "minLength": 1
                  },
                  "repo": {
                    "description": "Repo name.",
                    "type": "string",
                    "minLength": 1
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "owner",
                  "repo",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "owner": "facebook",
                "repo": "react"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/from-substack": {
      "post": {
        "summary": "Turn a Substack publication into a normalized feed.",
        "description": "Turn a Substack publication into a normalized feed.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_from-substack",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "publication": {
                    "description": "Substack publication — a bare name (\"bigtechnology\"), a *.substack.com URL, or a custom domain.",
                    "type": "string",
                    "minLength": 1
                  },
                  "limit": {
                    "description": "Max items to return. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "publication",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "publication": "stripe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/merge": {
      "post": {
        "summary": "Fetch multiple feeds, dedupe by guid+url, and return one time-ordered stream.",
        "description": "Fetch multiple feeds, dedupe by guid+url, and return one time-ordered stream.",
        "tags": [
          "RSS",
          "RSS: Converters"
        ],
        "operationId": "post_v1_rss_merge",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Converters",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "urls": {
                    "description": "Feed URLs to merge (first 20; more are ignored). Dedupe is by guid+url across all of them.",
                    "minItems": 1,
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "limit": {
                    "description": "Max merged items to return (1–200, clamped in the old code — now rejected instead). Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 200
                  }
                },
                "required": [
                  "urls",
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "urls": [
                  "https://news.ycombinator.com/rss",
                  "https://lobste.rs/rss"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "title": {
                      "description": "The source's own title.",
                      "type": "string"
                    },
                    "items": {
                      "description": "Normalized items.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guid": {
                            "description": "Stable item id — RSS guid, Atom id, or a derived fallback.",
                            "type": "string"
                          },
                          "title": {
                            "description": "Item title.",
                            "type": "string"
                          },
                          "url": {
                            "description": "Item URL, when the source provides one.",
                            "type": "string"
                          },
                          "authors": {
                            "description": "Author names — merged from author/dc:creator/atom author, de-duped.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "categories": {
                            "description": "Categories/tags.",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp — empty string when the source doesn't provide one.",
                            "type": "string"
                          },
                          "updatedAt": {
                            "description": "ISO update timestamp, when distinct from publishedAt.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short snippet (RSS description / Atom summary).",
                            "type": "string"
                          },
                          "contentHtml": {
                            "description": "Full article HTML, when the source provides it.",
                            "type": "string"
                          },
                          "contentText": {
                            "description": "Plain-text version of contentHtml (or summary).",
                            "type": "string"
                          },
                          "image": {
                            "description": "Primary image URL — the first of images[], when any.",
                            "type": "string"
                          },
                          "images": {
                            "description": "All images found on the item.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "url": {
                                  "description": "Image URL.",
                                  "type": "string"
                                },
                                "type": {
                                  "description": "MIME type, when known.",
                                  "type": "string"
                                },
                                "width": {
                                  "description": "Width in pixels, when known.",
                                  "type": "number"
                                },
                                "height": {
                                  "description": "Height in pixels, when known.",
                                  "type": "number"
                                },
                                "length": {
                                  "description": "Byte size, when known (e.g. an RSS enclosure).",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "url"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "guid",
                          "title",
                          "authors",
                          "categories",
                          "publishedAt",
                          "images"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "title",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/monitor": {
      "post": {
        "summary": "Register a webhook that is POSTed new items as they appear (stop polling). At-least-once delivery.",
        "description": "Register a webhook that is POSTed new items as they appear (stop polling). At-least-once delivery.",
        "tags": [
          "RSS",
          "RSS: Monitors"
        ],
        "operationId": "post_v1_rss_monitor",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Monitors",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The feed URL to watch. NOT format-validated at creation — a malformed URL is accepted here and only surfaces as `lastError` on the next scheduled check.",
                    "type": "string",
                    "minLength": 1
                  },
                  "webhookUrl": {
                    "description": "Where to POST when new items appear. Same posture as `url` — not format-validated at creation.",
                    "type": "string",
                    "minLength": 1
                  },
                  "intervalSeconds": {
                    "description": "Recheck interval in seconds (300–86400, i.e. 5 min–24 h). Defaults to 900 (15 min).",
                    "default": 900,
                    "type": "integer",
                    "minimum": 300,
                    "maximum": 86400
                  }
                },
                "required": [
                  "url",
                  "webhookUrl",
                  "intervalSeconds"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://hnrss.org/frontpage",
                "webhookUrl": "https://example.com/hook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "monitorId": {
                      "description": "The created monitor's id.",
                      "type": "string"
                    },
                    "url": {
                      "description": "The watched feed URL.",
                      "type": "string"
                    },
                    "webhookUrl": {
                      "description": "Where new-item notifications POST to.",
                      "type": "string"
                    },
                    "intervalSeconds": {
                      "description": "The resolved recheck interval, in seconds.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "monitorId",
                    "url",
                    "webhookUrl",
                    "intervalSeconds"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List your active monitors.",
        "description": "List your active monitors.",
        "tags": [
          "RSS",
          "RSS: Monitors"
        ],
        "operationId": "get_v1_rss_monitor",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Monitors",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "The caller's monitors.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "monitorId": {
                        "description": "Monitor id.",
                        "type": "string"
                      },
                      "url": {
                        "description": "The watched feed URL.",
                        "type": "string"
                      },
                      "webhookUrl": {
                        "description": "Where new-item notifications POST to.",
                        "type": "string"
                      },
                      "intervalSeconds": {
                        "description": "Recheck interval, in seconds.",
                        "type": "number"
                      },
                      "lastDeliveredAt": {
                        "description": "ISO timestamp of the last successful webhook delivery, if any.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "lastError": {
                        "description": "Most recent check error, if any.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "monitorId",
                      "url",
                      "webhookUrl",
                      "intervalSeconds",
                      "lastDeliveredAt",
                      "lastError"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/monitor/{id}": {
      "delete": {
        "summary": "Stop and delete a monitor.",
        "description": "Stop and delete a monitor.",
        "tags": [
          "RSS",
          "RSS: Monitors"
        ],
        "operationId": "delete_v1_rss_monitor__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Monitors",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/feeds": {
      "post": {
        "summary": "Create a persistent hosted feed you can subscribe to in any reader, from any source (a feedless site + selector, a YouTube channel, a merge set, …). Returns a stable feed URL. Kind is inferred from the fields, or pass it explicitly.",
        "description": "Create a persistent hosted feed you can subscribe to in any reader, from any source (a feedless site + selector, a YouTube channel, a merge set, …). Returns a stable feed URL. Kind is inferred from the fields, or pass it explicitly.\n\n**Example:**\n\n```\n{ \"id\": \"k17…\", \"kind\": \"site\", \"title\": \"example.com\", \"feedUrl\": \"https://api.cheapass.dev/v1/rss/feeds/k17….xml\", \"itemCount\": 20 }\n```",
        "tags": [
          "RSS",
          "RSS: Hosted feeds"
        ],
        "operationId": "post_v1_rss_feeds",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Hosted feeds",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "kind": {
                    "description": "Explicit source kind. Inferred from the other fields when omitted: urls[] → merge; subreddit → reddit; owner+repo → github; publication → substack; channelId/handle → youtube; selector+url → site; url alone → fetch.",
                    "type": "string",
                    "enum": [
                      "fetch",
                      "site",
                      "youtube",
                      "reddit",
                      "github",
                      "substack",
                      "merge"
                    ]
                  },
                  "url": {
                    "description": "Feed/page URL — for kind fetch (alone) or site (with selector).",
                    "type": "string",
                    "format": "uri"
                  },
                  "selector": {
                    "description": "CSS selector scoping story blocks — for kind site.",
                    "type": "string"
                  },
                  "urls": {
                    "description": "Source feed URLs to merge — for kind merge (first 20; more are ignored).",
                    "minItems": 1,
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "channelId": {
                    "description": "YouTube channel id — for kind youtube. Only a \"UC…\" id is used directly; anything else falls through to handle/url.",
                    "type": "string"
                  },
                  "handle": {
                    "description": "YouTube @handle — for kind youtube.",
                    "type": "string"
                  },
                  "subreddit": {
                    "description": "Subreddit name — for kind reddit.",
                    "type": "string"
                  },
                  "sort": {
                    "description": "Reddit sort — \"new\" | \"hot\" | \"top\" | \"rising\". Any other value falls back to \"new\".",
                    "type": "string"
                  },
                  "owner": {
                    "description": "GitHub repo owner — for kind github (with repo).",
                    "type": "string"
                  },
                  "repo": {
                    "description": "GitHub repo name — for kind github (with owner).",
                    "type": "string"
                  },
                  "publication": {
                    "description": "Substack publication — for kind substack.",
                    "type": "string"
                  },
                  "limit": {
                    "description": "Max items in the validation preview / re-synthesized feed. Defaults to 50.",
                    "default": 50,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "title": {
                    "description": "Feed title. Defaults to the source's own title.",
                    "type": "string"
                  },
                  "category": {
                    "description": "Category label, surfaced in /v1/rss/directory when visibility is public.",
                    "type": "string"
                  },
                  "visibility": {
                    "description": "\"unlisted\" (default) or \"public\" (listed in /v1/rss/directory). Any other value falls back to \"unlisted\".",
                    "type": "string"
                  },
                  "format": {
                    "description": "\"rss\" (default) or \"atom\". Any other value falls back to \"rss\".",
                    "type": "string"
                  }
                },
                "required": [
                  "limit"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://hnrss.org/frontpage"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The created feed's id.",
                      "type": "string"
                    },
                    "kind": {
                      "description": "The resolved source kind (explicit or inferred).",
                      "type": "string",
                      "enum": [
                        "fetch",
                        "site",
                        "youtube",
                        "reddit",
                        "github",
                        "substack",
                        "merge"
                      ]
                    },
                    "title": {
                      "description": "Feed title — the caller's `title`, else the source's own title.",
                      "type": "string"
                    },
                    "feedUrl": {
                      "description": "The public, subscribable feed URL.",
                      "type": "string"
                    },
                    "itemCount": {
                      "description": "Item count from the validation preview fetch.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "feedUrl",
                    "itemCount"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List your hosted feeds.",
        "description": "List your hosted feeds.",
        "tags": [
          "RSS",
          "RSS: Hosted feeds"
        ],
        "operationId": "get_v1_rss_feeds",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Hosted feeds",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "The caller's hosted feeds.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Feed id.",
                        "type": "string"
                      },
                      "kind": {
                        "description": "Source kind.",
                        "type": "string",
                        "enum": [
                          "fetch",
                          "site",
                          "youtube",
                          "reddit",
                          "github",
                          "substack",
                          "merge"
                        ]
                      },
                      "title": {
                        "description": "Feed title, when known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "feedUrl": {
                        "description": "The public, subscribable feed URL.",
                        "type": "string"
                      },
                      "lastError": {
                        "description": "Most recent re-synthesis error, if any.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "kind",
                      "title",
                      "feedUrl",
                      "lastError",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/feeds/{id}.xml": {
      "get": {
        "summary": "The hosted feed itself — PUBLIC (no API key); subscribe to it in any reader. A readable /:id/:slug.xml form works too (the id resolves; the slug is cosmetic). Re-synthesized on read, cached ~10 min. Append .atom for Atom.",
        "description": "The hosted feed itself — PUBLIC (no API key); subscribe to it in any reader. A readable /:id/:slug.xml form works too (the id resolves; the slug is cosmetic). Re-synthesized on read, cached ~10 min. Append .atom for Atom.",
        "tags": [
          "RSS",
          "RSS: Hosted feeds"
        ],
        "operationId": "get_v1_rss_feeds__id.xml",
        "security": [],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Hosted feeds",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The hosted feed itself — RSS 2.0 XML, or Atom via a trailing \".atom\" instead of \".xml\". Re-synthesized on read, cached ~10 min; serves stale cache through an upstream hiccup. A readable /:id/:slug.xml form also resolves (the id is canonical; the slug is cosmetic).",
            "content": {
              "application/rss+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/atom+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/directory": {
      "get": {
        "summary": "Public directory of feeds users have opted to share (visibility: public). Filter with ?category=. Feeds are private (unlisted) by default and never appear here unless shared.",
        "description": "Public directory of feeds users have opted to share (visibility: public). Filter with ?category=. Feeds are private (unlisted) by default and never appear here unless shared.",
        "tags": [
          "RSS",
          "RSS: Discover"
        ],
        "operationId": "get_v1_rss_directory",
        "security": [],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Discover",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter to one category.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Public (opt-in) hosted feeds.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Feed id.",
                        "type": "string"
                      },
                      "kind": {
                        "description": "Source kind.",
                        "type": "string",
                        "enum": [
                          "fetch",
                          "site",
                          "youtube",
                          "reddit",
                          "github",
                          "substack",
                          "merge"
                        ]
                      },
                      "title": {
                        "description": "Feed title, when known.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "category": {
                        "description": "Category label, when the owner set one.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "feedUrl": {
                        "description": "The public, subscribable feed URL.",
                        "type": "string"
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "kind",
                      "title",
                      "category",
                      "feedUrl",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/rss/feeds/{id}": {
      "delete": {
        "summary": "Delete a hosted feed (its public URL stops working).",
        "description": "Delete a hosted feed (its public URL stops working).",
        "tags": [
          "RSS",
          "RSS: Hosted feeds"
        ],
        "operationId": "delete_v1_rss_feeds__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "rss",
        "x-cheapass-group": "Hosted feeds",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/web/markdown": {
      "post": {
        "summary": "Extract the main article and return clean markdown (in-isolate heuristic extractor — strips boilerplate, isolates <article>/<main>, converts to markdown).",
        "description": "Extract the main article and return clean markdown (in-isolate heuristic extractor — strips boilerplate, isolates <article>/<main>, converts to markdown).\n\n**Example:**\n\n```\n{\n  \"title\": \"The article title\",\n  \"byline\": \"Jane Doe\",\n  \"lang\": \"en\",\n  \"wordCount\": 812,\n  \"markdown\": \"# The article title\\n\\nClean body text as markdown…\"\n}\n```",
        "tags": [
          "Web"
        ],
        "operationId": "post_v1_web_markdown",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The page URL to fetch and extract (SSRF-guarded — http/https only, no private/loopback targets).",
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "url": {
                      "description": "Final URL after redirects.",
                      "type": "string"
                    },
                    "title": {
                      "description": "Page title (og:title, else <title>).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "byline": {
                      "description": "Author, when present (meta author, else article:author).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "excerpt": {
                      "description": "Description (og:description, twitter:description, or meta description).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lang": {
                      "description": "Page language, 2-letter (from <html lang>).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "wordCount": {
                      "description": "Word count of the extracted text.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "markdown": {
                      "description": "Main content as markdown — heuristic extraction (strips boilerplate, isolates <article>/<main>), not a full Readability pass; no JS execution.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "url",
                    "title",
                    "byline",
                    "excerpt",
                    "lang",
                    "wordCount",
                    "markdown"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/web/metadata": {
      "post": {
        "summary": "Open Graph / Twitter / meta tags + canonical URL and favicon, no JS execution.",
        "description": "Open Graph / Twitter / meta tags + canonical URL and favicon, no JS execution.",
        "tags": [
          "Web"
        ],
        "operationId": "post_v1_web_metadata",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The page URL to fetch and parse (SSRF-guarded — http/https only, no private/loopback targets).",
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "url": {
                      "description": "Final URL after redirects.",
                      "type": "string"
                    },
                    "title": {
                      "description": "Page title (og:title, else <title>).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "description": {
                      "description": "og:description, twitter:description, or meta description.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "image": {
                      "description": "og:image or twitter:image, resolved to an absolute URL.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "canonical": {
                      "description": "<link rel=canonical>, resolved to an absolute URL.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "favicon": {
                      "description": "Site favicon — <link rel=icon/shortcut icon/apple-touch-icon>, else /favicon.ico.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lang": {
                      "description": "Page language, 2-letter (from <html lang>).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "author": {
                      "description": "meta author, else og:article:author.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "og": {
                      "description": "Open Graph tags, keyed without the 'og:' prefix.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    },
                    "twitter": {
                      "description": "Twitter card tags, keyed without the 'twitter:' prefix.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "url",
                    "title",
                    "description",
                    "image",
                    "canonical",
                    "favicon",
                    "lang",
                    "author",
                    "og",
                    "twitter"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/web/browser": {
      "post": {
        "summary": "Headless-render a JS-heavy page in a real Chromium (Cloudflare Browser Rendering): executes JavaScript, waits for a selector or the network to settle, and returns any combination of rendered HTML, markdown, CSS-selector scrapes, and a PNG screenshot (returned as a Convex storage URL — the response is always JSON). You supply the URL; respecting the target site's ToS is the caller's responsibility.",
        "description": "Headless-render a JS-heavy page in a real Chromium (Cloudflare Browser Rendering): executes JavaScript, waits for a selector or the network to settle, and returns any combination of rendered HTML, markdown, CSS-selector scrapes, and a PNG screenshot (returned as a Convex storage URL — the response is always JSON). You supply the URL; respecting the target site's ToS is the caller's responsibility.\n\n**Example:**\n\n```\n{\n  \"url\": \"https://example.com/app\",\n  \"markdown\": \"# Rendered after JS ran\\n\\n…\",\n  \"elements\": [{ \"selector\": \".price\", \"results\": [{ \"text\": \"$9\", \"html\": \"<span…\", \"attributes\": [] }] }],\n  \"screenshotUrl\": \"https://…/storage/…png\"\n}\n```",
        "tags": [
          "Web"
        ],
        "operationId": "post_v1_web_browser",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The page URL to render (SSRF-guarded — http/https only, no private/loopback targets).",
                    "type": "string",
                    "format": "uri"
                  },
                  "render": {
                    "description": "Rendered artifact to return. Defaults to 'markdown' when both screenshot and scrape are omitted; omitted entirely otherwise.",
                    "type": "string",
                    "enum": [
                      "html",
                      "markdown"
                    ]
                  },
                  "screenshot": {
                    "description": "Also capture a PNG screenshot. Default false.",
                    "type": "boolean"
                  },
                  "scrape": {
                    "description": "CSS selectors to pull structured elements from.",
                    "type": "array",
                    "items": {
                      "description": "A non-empty CSS selector.",
                      "type": "string",
                      "minLength": 1
                    }
                  },
                  "waitFor": {
                    "description": "CSS selector to wait for before capturing.",
                    "type": "string"
                  },
                  "waitUntil": {
                    "description": "Cloudflare navigation-settle signal to wait for.",
                    "type": "string",
                    "enum": [
                      "load",
                      "domcontentloaded",
                      "networkidle0",
                      "networkidle2"
                    ]
                  },
                  "timeoutMs": {
                    "description": "Navigation/wait timeout in ms (Cloudflare clamps to 1000–60000).",
                    "type": "number"
                  },
                  "fullPage": {
                    "description": "Capture the full scrollable page, not just the viewport. Default false.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com",
                "render": "markdown"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "url": {
                      "description": "Echo of the input URL.",
                      "type": "string"
                    },
                    "html": {
                      "description": "Rendered HTML — present when render:\"html\".",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "markdown": {
                      "description": "Cloudflare-rendered markdown — present when render:\"markdown\" (the default when screenshot/scrape are both omitted).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "elements": {
                      "description": "Structured scrape results — present when scrape[] was requested.",
                      "anyOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "selector": {
                                "description": "The CSS selector that was scraped.",
                                "type": "string"
                              },
                              "results": {
                                "description": "One entry per matching element.",
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "text": {
                                      "description": "Matched element's text content.",
                                      "type": "string"
                                    },
                                    "html": {
                                      "description": "Matched element's inner HTML.",
                                      "type": "string"
                                    },
                                    "attributes": {
                                      "description": "Matched element's attributes.",
                                      "type": "array",
                                      "items": {
                                        "type": "object",
                                        "properties": {
                                          "name": {
                                            "description": "Attribute name.",
                                            "type": "string"
                                          },
                                          "value": {
                                            "description": "Attribute value.",
                                            "type": "string"
                                          }
                                        },
                                        "required": [
                                          "name",
                                          "value"
                                        ],
                                        "additionalProperties": false
                                      }
                                    }
                                  },
                                  "required": [
                                    "text",
                                    "html",
                                    "attributes"
                                  ],
                                  "additionalProperties": false
                                }
                              }
                            },
                            "required": [
                              "selector",
                              "results"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "screenshotUrl": {
                      "description": "Convex storage URL for the PNG screenshot — present when screenshot:true.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "renderedWith": {
                      "description": "Always \"cloudflare-browser-rendering\".",
                      "type": "string"
                    }
                  },
                  "required": [
                    "url",
                    "html",
                    "markdown",
                    "elements",
                    "screenshotUrl",
                    "renderedWith"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/web/monitor": {
      "post": {
        "summary": "Watch a URL (optionally scoped to a CSS selector — #id, .class, or tag) for changes and POST a webhook when its text changes. intervalSeconds clamps to 300–86400.",
        "description": "Watch a URL (optionally scoped to a CSS selector — #id, .class, or tag) for changes and POST a webhook when its text changes. intervalSeconds clamps to 300–86400.",
        "tags": [
          "Web"
        ],
        "operationId": "post_v1_web_monitor",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The URL to watch for changes (SSRF-guarded — http/https only, no private/loopback targets).",
                    "type": "string",
                    "format": "uri"
                  },
                  "selector": {
                    "description": "Scope change-detection to one element — #id, .class, or a bare tag name.",
                    "type": "string"
                  },
                  "webhookUrl": {
                    "description": "Where to POST when the watched content changes (SSRF-guarded — http/https only, no private/loopback targets).",
                    "type": "string",
                    "format": "uri"
                  },
                  "intervalSeconds": {
                    "description": "Recheck interval in seconds (300–86400, i.e. 5 min–24 h). Defaults to 3600 (1 h).",
                    "default": 3600,
                    "type": "integer",
                    "minimum": 300,
                    "maximum": 86400
                  }
                },
                "required": [
                  "url",
                  "webhookUrl",
                  "intervalSeconds"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com/pricing",
                "webhookUrl": "https://example.com/hook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "monitorId": {
                      "description": "The created monitor's id.",
                      "type": "string"
                    },
                    "url": {
                      "description": "The watched URL.",
                      "type": "string"
                    },
                    "selector": {
                      "description": "The element scope, if one was given.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "webhookUrl": {
                      "description": "Where change notifications POST to.",
                      "type": "string"
                    },
                    "intervalSeconds": {
                      "description": "The resolved recheck interval, in seconds.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "monitorId",
                    "url",
                    "selector",
                    "webhookUrl",
                    "intervalSeconds"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List your active URL monitors.",
        "description": "List your active URL monitors.",
        "tags": [
          "Web"
        ],
        "operationId": "get_v1_web_monitor",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "count": {
                      "description": "Number of monitors returned.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "monitors": {
                      "description": "The caller's URL monitors.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "monitorId": {
                            "description": "Monitor id.",
                            "type": "string"
                          },
                          "url": {
                            "description": "The watched URL.",
                            "type": "string"
                          },
                          "selector": {
                            "description": "The element scope, if one was given.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "webhookUrl": {
                            "description": "Where change notifications POST to.",
                            "type": "string"
                          },
                          "intervalSeconds": {
                            "description": "Recheck interval, in seconds.",
                            "type": "number"
                          },
                          "lastCheckedAt": {
                            "description": "ISO timestamp of the last check, if any.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lastChangedAt": {
                            "description": "ISO timestamp of the last detected change, if any.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lastError": {
                            "description": "Most recent check error, if any.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "monitorId",
                          "url",
                          "selector",
                          "webhookUrl",
                          "intervalSeconds",
                          "lastCheckedAt",
                          "lastChangedAt",
                          "lastError"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "count",
                    "monitors"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/web/monitor/{id}": {
      "delete": {
        "summary": "Stop and delete a URL monitor.",
        "description": "Stop and delete a URL monitor.",
        "tags": [
          "Web"
        ],
        "operationId": "delete_v1_web_monitor__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "web",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Monitor id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "description": "Always true on success.",
                      "type": "boolean"
                    },
                    "monitorId": {
                      "description": "The deleted monitor's id.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "deleted",
                    "monitorId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/text/summarize": {
      "post": {
        "summary": "[coming soon] Summarize text or a URL to a target length.",
        "description": "Summarize text or a URL to a target length.\n\n**Example:**\n\n```\n{ \"summary\": \"A concise 2-3 sentence summary of the input…\", \"wordCount\": 42 }\n```\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_summarize",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Raw text to summarize (provide this or url).",
                    "type": "string"
                  },
                  "url": {
                    "description": "URL to fetch + clean (via web/markdown) before summarizing.",
                    "type": "string",
                    "format": "uri"
                  },
                  "maxWords": {
                    "description": "Target maximum word count for the summary.",
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com/article",
                "maxWords": 80
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/text/entities": {
      "post": {
        "summary": "[coming soon] Named-entity recognition — people, orgs, places, products, dates.",
        "description": "Named-entity recognition — people, orgs, places, products, dates.\n\n**Example:**\n\n```\n{ \"entities\": [\n  { \"text\": \"Sam Altman\", \"type\": \"PERSON\", \"score\": 0.99 },\n  { \"text\": \"OpenAI\", \"type\": \"ORG\", \"score\": 0.98 }\n] }\n```\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_entities",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to extract named entities from.",
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Sam Altman leads OpenAI."
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/text/classify": {
      "post": {
        "summary": "[coming soon] Zero-shot classification against labels you provide.",
        "description": "Zero-shot classification against labels you provide.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_classify",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to classify.",
                    "type": "string",
                    "minLength": 1
                  },
                  "labels": {
                    "description": "Candidate labels to classify against (zero-shot).",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "multiLabel": {
                    "description": "Allow more than one label to apply (optional).",
                    "type": "boolean"
                  }
                },
                "required": [
                  "text",
                  "labels"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "The invoice is overdue.",
                "labels": [
                  "billing",
                  "support",
                  "sales"
                ]
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/text/language": {
      "post": {
        "summary": "[coming soon] Detect the language of a piece of text.",
        "description": "Detect the language of a piece of text.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_language",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to detect the language of.",
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Bonjour tout le monde"
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/text/sentiment": {
      "post": {
        "summary": "[coming soon] Sentiment polarity of a piece of text.",
        "description": "Sentiment polarity of a piece of text.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_sentiment",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to score for sentiment.",
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "I love this product."
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/text/reading-time": {
      "post": {
        "summary": "[coming soon] Word count and estimated reading time.",
        "description": "Word count and estimated reading time.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Text"
        ],
        "operationId": "post_v1_text_reading-time",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "text",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to measure.",
                    "type": "string",
                    "minLength": 1
                  },
                  "wpm": {
                    "description": "Reading speed override, words per minute (optional).",
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "A short paragraph of sample text for timing."
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/search/web": {
      "get": {
        "summary": "[coming soon] Web search. Normalized results regardless of the upstream provider.",
        "description": "Web search. Normalized results regardless of the upstream provider.\n\n**Example:**\n\n```\n{\n  \"query\": \"best espresso machine\",\n  \"results\": [\n    { \"title\": \"The 8 Best Espresso Machines of 2026\", \"url\": \"https://example.com/best-espresso\", \"description\": \"…\" }\n  ]\n}\n```\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Search"
        ],
        "operationId": "get_v1_search_web",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "search",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Number of results to return.",
            "schema": {
              "default": 10,
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Pagination offset.",
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/search/news": {
      "get": {
        "summary": "[coming soon] News search with recency filtering.",
        "description": "News search with recency filtering.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Search"
        ],
        "operationId": "get_v1_search_news",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "search",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "freshness",
            "in": "query",
            "required": false,
            "description": "Recency filter.",
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week",
                "month"
              ]
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Number of results to return.",
            "schema": {
              "default": 10,
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/search/trending": {
      "get": {
        "summary": "[coming soon] Trending topics across your subscribed feed bundles (in-house).",
        "description": "Trending topics across your subscribed feed bundles (in-house).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Search"
        ],
        "operationId": "get_v1_search_trending",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "search",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "windowHours",
            "in": "query",
            "required": false,
            "description": "Recent-window size, in hours.",
            "schema": {
              "default": 24,
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max number of trending terms to return.",
            "schema": {
              "default": 20,
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/weather": {
      "get": {
        "summary": "[coming soon] Current conditions + daily forecast by coordinates (Open-Meteo).",
        "description": "Current conditions + daily forecast by coordinates (Open-Meteo).\n\n**Example:**\n\n```\n{ \"current\": { \"temperature_2m\": 18.2, \"wind_speed_10m\": 11.0 }, \"daily\": [{ \"date\": \"2026-06-20\", \"tMax\": 24, \"tMin\": 14 }], \"units\": { \"temperature_2m\": \"°C\" } }\n```\n\n_Coming soon — returns 501 until shipped._\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Data",
          "Data: Weather & earth"
        ],
        "operationId": "get_v1_data_weather",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Weather & earth",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: latitude.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: lat.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: longitude.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: lng.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/air-quality": {
      "get": {
        "summary": "[coming soon] AQI, PM2.5/PM10, ozone, NO2, CO, SO2 by coordinates (Open-Meteo Air Quality).",
        "description": "AQI, PM2.5/PM10, ozone, NO2, CO, SO2 by coordinates (Open-Meteo Air Quality).\n\n_Coming soon — returns 501 until shipped._\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Data",
          "Data: Weather & earth"
        ],
        "operationId": "get_v1_data_air-quality",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Weather & earth",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: latitude.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: lat.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: longitude.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: lng.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/sunrise-sunset": {
      "get": {
        "summary": "[coming soon] Sunrise, sunset, and twilight times by coordinates/date (sunrise-sunset.org).",
        "description": "Sunrise, sunset, and twilight times by coordinates/date (sunrise-sunset.org).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Weather & earth"
        ],
        "operationId": "get_v1_data_sunrise-sunset",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Weather & earth",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: latitude.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Latitude (-90 to 90). Alias: lat.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: longitude.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Longitude (-180 to 180). Alias: lng.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Date to compute for (any format sunrise-sunset.org accepts, e.g. \"YYYY-MM-DD\"). Defaults to today.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/tides": {
      "get": {
        "summary": "[coming soon] Tide predictions for US coastal stations (NOAA CO-OPS).",
        "description": "Tide predictions for US coastal stations (NOAA CO-OPS).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Weather & earth"
        ],
        "operationId": "get_v1_data_tides",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Weather & earth",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NOAA CO-OPS station id. Defaults to \"8443970\" (Boston, MA).",
            "schema": {
              "default": "8443970",
              "type": "string"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Date to fetch — \"today\", \"recent\", \"YYYYMMDD\", or a NOAA date range keyword. Defaults to \"today\".",
            "schema": {
              "default": "today",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/earthquakes": {
      "get": {
        "summary": "[coming soon] Earthquake event query with magnitude/time/area filters (USGS).",
        "description": "Earthquake event query with magnitude/time/area filters (USGS).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Weather & earth"
        ],
        "operationId": "get_v1_data_earthquakes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Weather & earth",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "starttime",
            "in": "query",
            "required": false,
            "description": "ISO date/time lower bound (USGS `starttime`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endtime",
            "in": "query",
            "required": false,
            "description": "ISO date/time upper bound (USGS `endtime`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "minmagnitude",
            "in": "query",
            "required": false,
            "description": "Minimum magnitude. Alias: minMagnitude.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "minMagnitude",
            "in": "query",
            "required": false,
            "description": "Alias for minmagnitude.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxmagnitude",
            "in": "query",
            "required": false,
            "description": "Maximum magnitude. (No camelCase alias — asymmetric with minmagnitude in the upstream handler, kept as-is.)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "required": false,
            "description": "Center latitude for a radius search (with longitude + maxradiuskm).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "required": false,
            "description": "Center longitude for a radius search (with latitude + maxradiuskm).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxradiuskm",
            "in": "query",
            "required": false,
            "description": "Search radius in km around latitude/longitude.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/forex": {
      "get": {
        "summary": "[coming soon] Foreign-exchange reference rates (ExchangeRate-API open access).",
        "description": "Foreign-exchange reference rates (ExchangeRate-API open access).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Money & markets"
        ],
        "operationId": "get_v1_data_forex",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Money & markets",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "base",
            "in": "query",
            "required": false,
            "description": "Base currency code, e.g. \"EUR\". Not format-checked here — an unknown code still reaches the upstream and 422s from there. Defaults to \"USD\" (uppercased downstream).",
            "schema": {
              "default": "USD",
              "type": "string"
            }
          },
          {
            "name": "symbols",
            "in": "query",
            "required": false,
            "description": "Comma-separated currency codes to filter the response to, e.g. \"EUR,GBP,JPY\". Omit for every rate the upstream returns.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/crypto": {
      "get": {
        "summary": "[coming soon] Crypto market data — price, market cap, 24h volume/change (CoinGecko). (Coming soon — returns 501; not wired up yet.)",
        "description": "Crypto market data — price, market cap, 24h volume/change (CoinGecko). (Coming soon — returns 501; not wired up yet.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Money & markets"
        ],
        "operationId": "get_v1_data_crypto",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Money & markets",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated CoinGecko coin ids, e.g. \"bitcoin,ethereum\".",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vs",
            "in": "query",
            "required": false,
            "description": "Quote currency. Defaults to \"usd\".",
            "schema": {
              "default": "usd",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/stocks": {
      "get": {
        "summary": "[coming soon] Stock quotes and time series (Alpha Vantage). (Coming soon — returns 501; needs an Alpha Vantage key.)",
        "description": "Stock quotes and time series (Alpha Vantage). (Coming soon — returns 501; needs an Alpha Vantage key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Money & markets"
        ],
        "operationId": "get_v1_data_stocks",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Money & markets",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "description": "Ticker symbol, e.g. \"AAPL\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "description": "Time series interval. Defaults to \"daily\".",
            "schema": {
              "default": "daily",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/economic": {
      "get": {
        "summary": "[coming soon] Economic time series — CPI, unemployment, GDP, rates, M2 (FRED). (Coming soon — returns 501; needs a FRED key.)",
        "description": "Economic time series — CPI, unemployment, GDP, rates, M2 (FRED). (Coming soon — returns 501; needs a FRED key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Money & markets"
        ],
        "operationId": "get_v1_data_economic",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Money & markets",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "series",
            "in": "query",
            "required": true,
            "description": "FRED series id, e.g. \"CPIAUCSL\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/world-bank": {
      "get": {
        "summary": "[coming soon] Country-level development indicators (World Bank Open Data).",
        "description": "Country-level development indicators (World Bank Open Data).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Money & markets"
        ],
        "operationId": "get_v1_data_world-bank",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Money & markets",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO2/ISO3 country code or World Bank aggregate (e.g. \"US\", \"WLD\"). Defaults to \"US\".",
            "schema": {
              "default": "US",
              "type": "string"
            }
          },
          {
            "name": "indicator",
            "in": "query",
            "required": false,
            "description": "World Bank indicator code. Defaults to \"SP.POP.TOTL\" (total population).",
            "schema": {
              "default": "SP.POP.TOTL",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/treasury": {
      "get": {
        "summary": "[coming soon] US Treasury fiscal data — national debt, exchange rates, gift contributions (Treasury Fiscal Data).",
        "description": "US Treasury fiscal data — national debt, exchange rates, gift contributions (Treasury Fiscal Data).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_treasury",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "dataset",
            "in": "query",
            "required": false,
            "description": "One of \"debt_to_penny\" | \"exchange_rates\" | \"gift_contributions\". An unrecognized value is NOT rejected — it silently falls back to \"debt_to_penny\" (loose passthrough, matching the handler's own `endpoints[dataset] ?? endpoints.debt_to_penny` fallback; unchanged here).",
            "schema": {
              "default": "debt_to_penny",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/sec-companyfacts": {
      "get": {
        "summary": "[coming soon] Public-company financials via XBRL, by CIK or ticker (SEC EDGAR).",
        "description": "Public-company financials via XBRL, by CIK or ticker (SEC EDGAR).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_sec-companyfacts",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "cik",
            "in": "query",
            "required": false,
            "description": "SEC CIK (with or without leading zeros).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ticker",
            "in": "query",
            "required": false,
            "description": "Stock ticker — resolved to a CIK via SEC's company_tickers.json when cik isn't given.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "concept",
            "in": "query",
            "required": false,
            "description": "us-gaap XBRL concept, e.g. \"Revenues\". Defaults to trying Revenues, then RevenueFromContractWithCustomerExcludingAssessedTax, then SalesRevenueNet.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/census": {
      "get": {
        "summary": "[coming soon] US Census demographics by geography (Census Bureau ACS). (Coming soon — returns 501; needs a data.gov key.)",
        "description": "US Census demographics by geography (Census Bureau ACS). (Coming soon — returns 501; needs a data.gov key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_census",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "variables",
            "in": "query",
            "required": true,
            "description": "Comma-separated ACS variable codes, e.g. \"B01001_001E\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "geography",
            "in": "query",
            "required": true,
            "description": "Geography spec, e.g. \"state:*\" or \"county:*&in=state:25\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/usaspending": {
      "get": {
        "summary": "[coming soon] Federal contracts and grants search (USAspending.gov).",
        "description": "Federal contracts and grants search (USAspending.gov).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_usaspending",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "keyword",
            "in": "query",
            "required": false,
            "description": "Search keyword. Alias: q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Alias for keyword.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "\"contracts\" or \"grants\". Any other value is treated as \"contracts\" (loose passthrough, unchanged).",
            "schema": {
              "default": "contracts",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/federal-register": {
      "get": {
        "summary": "[coming soon] US regulations, executive orders, and notices (Federal Register).",
        "description": "US regulations, executive orders, and notices (Federal Register).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_federal-register",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "term",
            "in": "query",
            "required": false,
            "description": "Full-text search term. Alias: q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Alias for term.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "Sort order passed straight through to the upstream (e.g. \"newest\", \"oldest\", \"relevance\"). Not validated — an unrecognized value is whatever the Federal Register API does with it. Defaults to \"newest\".",
            "schema": {
              "default": "newest",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/fec": {
      "get": {
        "summary": "[coming soon] Campaign finance — candidate filings, PACs, contributions (FEC). (Coming soon — returns 501; needs a data.gov key.)",
        "description": "Campaign finance — candidate filings, PACs, contributions (FEC). (Coming soon — returns 501; needs a data.gov key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_fec",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/patents": {
      "get": {
        "summary": "[coming soon] Patent, trademark, and assignment search (USPTO). (Coming soon — returns 501; no integration started yet.)",
        "description": "Patent, trademark, and assignment search (USPTO). (Coming soon — returns 501; no integration started yet.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_patents",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/fbi-wanted": {
      "get": {
        "summary": "[coming soon] FBI Wanted persons list (FBI).",
        "description": "FBI Wanted persons list (FBI).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: US government"
        ],
        "operationId": "get_v1_data_fbi-wanted",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "US government",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number (as a string — not numerically validated). Defaults to \"1\".",
            "schema": {
              "default": "1",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/nutrition": {
      "get": {
        "summary": "[coming soon] Authoritative food & nutrient data — search foods, get full nutrient profiles per serving (USDA FoodData Central, public domain). (Coming soon — returns 501; needs a USDA key.)",
        "description": "Authoritative food & nutrient data — search foods, get full nutrient profiles per serving (USDA FoodData Central, public domain). (Coming soon — returns 501; needs a USDA key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Nutrition & fitness"
        ],
        "operationId": "get_v1_data_nutrition",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Nutrition & fitness",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Food search text.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fdcId",
            "in": "query",
            "required": false,
            "description": "USDA FoodData Central id, for a direct lookup.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/food-products": {
      "get": {
        "summary": "[coming soon] Packaged-product lookup — nutrition, ingredients, allergens by barcode (Open Food Facts).",
        "description": "Packaged-product lookup — nutrition, ingredients, allergens by barcode (Open Food Facts).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Nutrition & fitness"
        ],
        "operationId": "get_v1_data_food-products",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Nutrition & fitness",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "barcode",
            "in": "query",
            "required": true,
            "description": "Product barcode (EAN/UPC).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/exercises": {
      "get": {
        "summary": "[coming soon] Exercise database — name, category, equipment, muscles worked (wger; CC-BY-SA, attributed). Friendly names or numeric wger IDs both accepted for category/muscle/equipment.",
        "description": "Exercise database — name, category, equipment, muscles worked (wger; CC-BY-SA, attributed). Friendly names or numeric wger IDs both accepted for category/muscle/equipment.\n\n_Coming soon — returns 501 until shipped._\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Data",
          "Data: Nutrition & fitness"
        ],
        "operationId": "get_v1_data_exercises",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Nutrition & fitness",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Name filter, applied client-side against the fetched page (wger no longer offers server-side text search). Alias: term.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "term",
            "in": "query",
            "required": false,
            "description": "Alias for q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "wger language id. Defaults to \"2\" (English).",
            "schema": {
              "default": "2",
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Category — a friendly name (\"chest\", \"legs\", …) or a raw wger numeric id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "muscle",
            "in": "query",
            "required": false,
            "description": "Muscle — a friendly name or a raw wger numeric id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "equipment",
            "in": "query",
            "required": false,
            "description": "Equipment — a friendly name or a raw wger numeric id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results (integer, 1-50). Defaults to 20. Non-numeric, zero, fractional, or out-of-range values were silently defaulted/clamped/tolerated by the old code; now rejected instead.",
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/drugs": {
      "get": {
        "summary": "[coming soon] Drug labeling — dosage, warnings, ingredients, NDC info (openFDA drug label + NDC directory).",
        "description": "Drug labeling — dosage, warnings, ingredients, NDC info (openFDA drug label + NDC directory).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_drugs",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Generic or brand name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ndc",
            "in": "query",
            "required": false,
            "description": "National Drug Code.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/rxnorm": {
      "get": {
        "summary": "[coming soon] Normalize a drug name to its RxNorm concept (RxCUI) (NLM RxNav). Name resolution, not interaction checking.",
        "description": "Normalize a drug name to its RxNorm concept (RxCUI) (NLM RxNav). Name resolution, not interaction checking.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_rxnorm",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Drug name to normalize.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/clinical-trials": {
      "get": {
        "summary": "[coming soon] Search clinical studies — conditions, interventions, status, sponsors (ClinicalTrials.gov v2, public domain).",
        "description": "Search clinical studies — conditions, interventions, status, sponsors (ClinicalTrials.gov v2, public domain).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_clinical-trials",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "cond",
            "in": "query",
            "required": false,
            "description": "Condition search text. Alias: q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Alias for cond.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "intervention",
            "in": "query",
            "required": false,
            "description": "Intervention search text. Alias: intr.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "intr",
            "in": "query",
            "required": false,
            "description": "Alias for intervention.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Overall status filter (e.g. \"recruiting\"), uppercased before being sent upstream.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/chemicals": {
      "get": {
        "summary": "[coming soon] Compound & chemical data — structure, properties, identifiers (PubChem PUG REST).",
        "description": "Compound & chemical data — structure, properties, identifiers (PubChem PUG REST).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_chemicals",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Compound name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cid",
            "in": "query",
            "required": false,
            "description": "PubChem Compound ID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/research-grants": {
      "get": {
        "summary": "[coming soon] NIH/HHS-funded research projects — abstracts, funding, PIs (NIH RePORTER).",
        "description": "NIH/HHS-funded research projects — abstracts, funding, PIs (NIH RePORTER).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_research-grants",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": false,
            "description": "Full-text search term. Alias: q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Alias for text.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fiscalYears",
            "in": "query",
            "required": false,
            "description": "Comma-separated fiscal years, e.g. \"2024,2025\". Non-numeric entries are silently dropped downstream.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "org",
            "in": "query",
            "required": false,
            "description": "Organization name filter.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/pubmed": {
      "get": {
        "summary": "[coming soon] PubMed biomedical literature search (NCBI eutils).",
        "description": "PubMed biomedical literature search (NCBI eutils).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_pubmed",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search term.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "retmax",
            "in": "query",
            "required": false,
            "description": "Max results (as a string — not numerically validated). Defaults to \"10\".",
            "schema": {
              "default": "10",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/health-providers": {
      "get": {
        "summary": "[coming soon] US healthcare providers by NPI, taxonomy, address (NPPES).",
        "description": "US healthcare providers by NPI, taxonomy, address (NPPES).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_health-providers",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "npi",
            "in": "query",
            "required": false,
            "description": "National Provider Identifier, for a direct lookup.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Provider last name (mapped to last_name).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "first_name",
            "in": "query",
            "required": false,
            "description": "First name filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "last_name",
            "in": "query",
            "required": false,
            "description": "Last name filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "city",
            "in": "query",
            "required": false,
            "description": "City filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "State filter (2-letter).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postal_code",
            "in": "query",
            "required": false,
            "description": "Postal code filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taxonomy",
            "in": "query",
            "required": false,
            "description": "Taxonomy description filter, e.g. a specialty name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/health-insurance-plans": {
      "get": {
        "summary": "[coming soon] Marketplace health-insurance plan data (Healthcare.gov). (Coming soon — returns 501; blocked on a finicky upstream POST API, not just a missing key.)",
        "description": "Marketplace health-insurance plan data (Healthcare.gov). (Coming soon — returns 501; blocked on a finicky upstream POST API, not just a missing key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_health-insurance-plans",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "zip",
            "in": "query",
            "required": true,
            "description": "ZIP code.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Plan year. Defaults to the marketplace's current year.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/health-topics": {
      "get": {
        "summary": "[coming soon] Evidence-based preventive-health recommendations by age/sex (health.gov MyHealthfinder, public domain).",
        "description": "Evidence-based preventive-health recommendations by age/sex (health.gov MyHealthfinder, public domain).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_health-topics",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "age",
            "in": "query",
            "required": false,
            "description": "Age filter, in years.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sex",
            "in": "query",
            "required": false,
            "description": "Sex filter (\"male\" | \"female\").",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/dailymed": {
      "get": {
        "summary": "[coming soon] Full FDA drug labels (Structured Product Labeling) by name, NDC, or set id (NLM DailyMed, public domain).",
        "description": "Full FDA drug labels (Structured Product Labeling) by name, NDC, or set id (NLM DailyMed, public domain).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_dailymed",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "setid",
            "in": "query",
            "required": false,
            "description": "DailyMed SPL set id, for a direct lookup (takes precedence over name/ndc).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Drug name search.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ndc",
            "in": "query",
            "required": false,
            "description": "NDC search.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/cdc": {
      "get": {
        "summary": "[coming soon] US public-health statistics — chronic disease indicators, disease surveillance (CDC open data).",
        "description": "US public-health statistics — chronic disease indicators, disease surveillance (CDC open data).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_cdc",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "dataset",
            "in": "query",
            "required": false,
            "description": "CDC Socrata dataset id, or a friendly alias (\"chronic-disease-indicators\", \"adult-tobacco\"). Defaults to chronic-disease-indicators's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "SoQL $limit (as a string — not numerically validated). Defaults to \"20\".",
            "schema": {
              "default": "20",
              "type": "string"
            }
          },
          {
            "name": "$where",
            "in": "query",
            "required": false,
            "description": "SoQL $where clause. Alias: where.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "where",
            "in": "query",
            "required": false,
            "description": "Alias for $where.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "$select",
            "in": "query",
            "required": false,
            "description": "SoQL $select clause. Alias: select.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "select",
            "in": "query",
            "required": false,
            "description": "Alias for $select.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "$order",
            "in": "query",
            "required": false,
            "description": "SoQL $order clause. Alias: order.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "Alias for $order.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "$q",
            "in": "query",
            "required": false,
            "description": "SoQL full-text $q. Alias: q.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Alias for $q.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/recalls": {
      "get": {
        "summary": "[coming soon] Food, drug, and device recalls (openFDA).",
        "description": "Food, drug, and device recalls (openFDA).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Health & medicine"
        ],
        "operationId": "get_v1_data_recalls",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Health & medicine",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "One of \"food\" | \"drug\" | \"device\" (case-insensitive; the handler lowercases before checking membership and 400s on anything else). Defaults to \"food\".",
            "schema": {
              "default": "food",
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "openFDA search expression.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/space": {
      "get": {
        "summary": "[coming soon] NASA datasets — APOD, near-earth objects, Mars rover photos, EPIC imagery. (Coming soon — returns 501; needs a NASA key.)",
        "description": "NASA datasets — APOD, near-earth objects, Mars rover photos, EPIC imagery. (Coming soon — returns 501; needs a NASA key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Science & space"
        ],
        "operationId": "get_v1_data_space",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Science & space",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "dataset",
            "in": "query",
            "required": true,
            "description": "Which NASA dataset to query.",
            "schema": {
              "type": "string",
              "enum": [
                "apod",
                "neo",
                "mars",
                "epic"
              ]
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/holidays": {
      "get": {
        "summary": "[coming soon] Public holidays for 100+ countries (Nager.Date).",
        "description": "Public holidays for 100+ countries (Nager.Date).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_holidays",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO2 country code. Defaults to \"US\".",
            "schema": {
              "default": "US",
              "type": "string"
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Year. Defaults to the current UTC year.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/wiki": {
      "get": {
        "summary": "[coming soon] Wikipedia article summaries and search (Wikimedia REST).",
        "description": "Wikipedia article summaries and search (Wikimedia REST).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_wiki",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "title",
            "in": "query",
            "required": false,
            "description": "Exact article title, for a summary lookup.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search text, when title isn't given.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/books": {
      "get": {
        "summary": "[coming soon] Book metadata, authors, and cover images by ISBN/title (Open Library).",
        "description": "Book metadata, authors, and cover images by ISBN/title (Open Library).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_books",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Title/author search text.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "isbn",
            "in": "query",
            "required": false,
            "description": "ISBN, for a direct lookup.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/tv": {
      "get": {
        "summary": "[coming soon] TV show metadata and search (TVMaze).",
        "description": "TV show metadata and search (TVMaze).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_tv",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "TVMaze show id, for a direct lookup.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Title search text, when id isn't given.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/music": {
      "get": {
        "summary": "[coming soon] Artist, release, and recording metadata (MusicBrainz).",
        "description": "Artist, release, and recording metadata (MusicBrainz).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_music",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search text.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "One of \"artist\" | \"release\" | \"recording\" (case-insensitive; the handler lowercases before checking membership and 400s on anything else). Defaults to \"artist\".",
            "schema": {
              "default": "artist",
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/breweries": {
      "get": {
        "summary": "[coming soon] Brewery directory search by city/name/type/postal code (Open Brewery DB).",
        "description": "Brewery directory search by city/name/type/postal code (Open Brewery DB).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_breweries",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "by_city",
            "in": "query",
            "required": false,
            "description": "Filter by city.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "by_name",
            "in": "query",
            "required": false,
            "description": "Filter by name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "by_state",
            "in": "query",
            "required": false,
            "description": "Filter by state.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "by_type",
            "in": "query",
            "required": false,
            "description": "Filter by type (e.g. \"micro\", \"brewpub\").",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "by_postal",
            "in": "query",
            "required": false,
            "description": "Filter by postal code.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/dictionary": {
      "get": {
        "summary": "[coming soon] Word definitions, phonetics, and parts of speech (Free Dictionary).",
        "description": "Word definitions, phonetics, and parts of speech (Free Dictionary).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_dictionary",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "word",
            "in": "query",
            "required": true,
            "description": "Word to define.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/words": {
      "get": {
        "summary": "[coming soon] Find words by meaning, rhyme, sound-alike, or topic (Datamuse).",
        "description": "Find words by meaning, rhyme, sound-alike, or topic (Datamuse).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_words",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "required": false,
            "description": "Max results (as a string — not numerically validated). Defaults to \"20\".",
            "schema": {
              "default": "20",
              "type": "string"
            }
          },
          {
            "name": "ml",
            "in": "query",
            "required": false,
            "description": "Find words with a meaning similar to this (\"means like\").",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rel_rhy",
            "in": "query",
            "required": false,
            "description": "Find words that rhyme with this.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sl",
            "in": "query",
            "required": false,
            "description": "Find words that sound like this (\"sounds like\").",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sp",
            "in": "query",
            "required": false,
            "description": "Find words matching this spelling pattern (wildcards allowed).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "topics",
            "in": "query",
            "required": false,
            "description": "Bias results toward these topic words. NOTE: satisfies the \"at least one of\" requirement despite the old handler's own error message text omitting it — a pre-existing quirk, reproduced exactly.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rel_syn",
            "in": "query",
            "required": false,
            "description": "Find synonyms of this word.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/data/parks": {
      "get": {
        "summary": "[coming soon] US National Park info, alerts, events, fees (NPS). (Coming soon — returns 501; needs a data.gov key.)",
        "description": "US National Park info, alerts, events, fees (NPS). (Coming soon — returns 501; needs a data.gov key.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Data",
          "Data: Reference & culture"
        ],
        "operationId": "get_v1_data_parks",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "data",
        "x-cheapass-group": "Reference & culture",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "parkCode",
            "in": "query",
            "required": false,
            "description": "NPS 4-letter park code.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "2-letter state code, for parks in that state.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/geo/geocode": {
      "get": {
        "summary": "Forward geocode an address/place name to coordinates (Photon/OSM).",
        "description": "Forward geocode an address/place name to coordinates (Photon/OSM).",
        "tags": [
          "Geo",
          "Geo: Geocoding"
        ],
        "operationId": "get_v1_geo_geocode",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Geocoding",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Address or place name to geocode.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results to return (1–20). Defaults to 5.",
            "schema": {
              "default": 5,
              "type": "integer",
              "minimum": 1,
              "maximum": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "query": {
                      "description": "Echo of the input query.",
                      "type": "string"
                    },
                    "results": {
                      "description": "Matches, most relevant first.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "lat": {
                            "description": "Latitude.",
                            "type": "number"
                          },
                          "lng": {
                            "description": "Longitude.",
                            "type": "number"
                          },
                          "displayName": {
                            "description": "Human-readable place label, most-specific part first.",
                            "type": "string"
                          },
                          "type": {
                            "description": "OSM feature type (e.g. city, house).",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "class": {
                            "description": "OSM tag key the match came from (e.g. place, building).",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "importance": {
                            "description": "Always null — Photon (the upstream) doesn't return a relevance score.",
                            "type": "null"
                          },
                          "boundingBox": {
                            "description": "[south, north, west, east], when Photon returned an extent.",
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "number"
                                }
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "lat",
                          "lng",
                          "displayName",
                          "type",
                          "class",
                          "importance",
                          "boundingBox"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "query",
                    "results"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/reverse-geocode": {
      "get": {
        "summary": "Reverse geocode coordinates to an address (Photon/OSM).",
        "description": "Reverse geocode coordinates to an address (Photon/OSM).",
        "tags": [
          "Geo",
          "Geo: Geocoding"
        ],
        "operationId": "get_v1_geo_reverse-geocode",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Geocoding",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (-90 to 90).",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Longitude (-180 to 180).",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "displayName": {
                      "description": "Human-readable address label.",
                      "type": "string"
                    },
                    "address": {
                      "type": "object",
                      "properties": {
                        "road": {
                          "description": "Street name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "city": {
                          "description": "City.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "district": {
                          "description": "District/neighborhood.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "county": {
                          "description": "County.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "state": {
                          "description": "State/province.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "postcode": {
                          "description": "Postal code.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "country": {
                          "description": "Country name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "country_code": {
                          "description": "ISO2 country code, lowercase.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "road",
                        "city",
                        "district",
                        "county",
                        "state",
                        "postcode",
                        "country",
                        "country_code"
                      ],
                      "additionalProperties": false
                    },
                    "lat": {
                      "description": "Echo of the input latitude.",
                      "type": "number"
                    },
                    "lng": {
                      "description": "Echo of the input longitude.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "displayName",
                    "address",
                    "lat",
                    "lng"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/places": {
      "get": {
        "summary": "Find places/POIs near a point by tag (OSM Overpass).",
        "description": "Find places/POIs near a point by tag (OSM Overpass).",
        "tags": [
          "Geo",
          "Geo: Geocoding"
        ],
        "operationId": "get_v1_geo_places",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Geocoding",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (-90 to 90).",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Longitude (-180 to 180).",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "OSM tag to search for — a bare value (\"cafe\" → amenity=cafe) or \"key=value\" (e.g. \"shop=bakery\"). Defaults to \"cafe\".",
            "schema": {
              "default": "cafe",
              "type": "string"
            }
          },
          {
            "name": "radius",
            "in": "query",
            "required": false,
            "description": "Search radius in meters (1–5000). Defaults to 1000.",
            "schema": {
              "default": 1000,
              "type": "integer",
              "minimum": 1,
              "maximum": 5000
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results to return (1–100). Defaults to 30.",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "lat": {
                      "description": "Echo of the input latitude.",
                      "type": "number"
                    },
                    "lng": {
                      "description": "Echo of the input longitude.",
                      "type": "number"
                    },
                    "radius": {
                      "description": "Echo of the resolved search radius, in meters.",
                      "type": "number"
                    },
                    "tag": {
                      "description": "Echo of the resolved OSM tag filter.",
                      "type": "string"
                    },
                    "count": {
                      "description": "Number of places returned.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "places": {
                      "description": "Matching places, as returned by Overpass (unordered).",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "description": "Place name, when tagged.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lat": {
                            "description": "Place latitude.",
                            "type": "number"
                          },
                          "lng": {
                            "description": "Place longitude.",
                            "type": "number"
                          },
                          "tags": {
                            "description": "Raw OSM tags for this node.",
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "name",
                          "lat",
                          "lng",
                          "tags"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "lat",
                    "lng",
                    "radius",
                    "tag",
                    "count",
                    "places"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/gazetteer": {
      "get": {
        "summary": "[coming soon] Search the global place gazetteer — name → coordinates, country, admin1/admin2, population, feature class, elevation, timezone (GeoNames; CC-BY, attributed). (Coming soon — returns 501 until a GeoNames account is wired; until then, use geocode.)",
        "description": "Search the global place gazetteer — name → coordinates, country, admin1/admin2, population, feature class, elevation, timezone (GeoNames; CC-BY, attributed). (Coming soon — returns 501 until a GeoNames account is wired; until then, use geocode.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Geo",
          "Geo: Geocoding"
        ],
        "operationId": "get_v1_geo_gazetteer",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Geocoding",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Place name to search for.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "featureClass",
            "in": "query",
            "required": false,
            "description": "GeoNames feature class filter (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO2 country filter (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/geo/boundaries": {
      "get": {
        "summary": "[coming soon] Boundary polygons as GeoJSON — continents, countries, states/provinces, and counties/districts, at selectable resolution (Natural Earth, public domain + geoBoundaries gbOpen, CC-BY). (Coming soon — returns 501. The multi-resolution polygon tiers need a self-hosted dataset; for point-in-region answers today, use /v1/geo/regions.)",
        "description": "Boundary polygons as GeoJSON — continents, countries, states/provinces, and counties/districts, at selectable resolution (Natural Earth, public domain + geoBoundaries gbOpen, CC-BY). (Coming soon — returns 501. The multi-resolution polygon tiers need a self-hosted dataset; for point-in-region answers today, use /v1/geo/regions.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Geo",
          "Geo: Boundaries & regions"
        ],
        "operationId": "get_v1_geo_boundaries",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Boundaries & regions",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "level",
            "in": "query",
            "required": true,
            "description": "Boundary tier to fetch.",
            "schema": {
              "type": "string",
              "enum": [
                "continent",
                "country",
                "admin1",
                "admin2"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The region id at that level (e.g. \"US\", \"US-CA\").",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "resolution",
            "in": "query",
            "required": false,
            "description": "Polygon detail level (optional).",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "med",
                "high"
              ]
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/geo/regions": {
      "get": {
        "summary": "Point-in-region lookup — given coordinates, return the continent, country, state/province, and county that contain them. Resolved from OpenStreetMap's reverse geocode (Photon), so it needs no hosted polygons; source is always \"osm\".",
        "description": "Point-in-region lookup — given coordinates, return the continent, country, state/province, and county that contain them. Resolved from OpenStreetMap's reverse geocode (Photon), so it needs no hosted polygons; source is always \"osm\".",
        "tags": [
          "Geo",
          "Geo: Boundaries & regions"
        ],
        "operationId": "get_v1_geo_regions",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Boundaries & regions",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (-90 to 90).",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Longitude (-180 to 180).",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "continent": {
                      "description": "Continent name, derived from the ISO2 country code.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "country": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "description": "Country name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "iso": {
                          "description": "ISO2 country code, uppercase.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "iso"
                      ],
                      "additionalProperties": false
                    },
                    "admin1": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "description": "State/province name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "code": {
                          "description": "Always null today — Photon doesn't return an admin1 code.",
                          "type": "null"
                        }
                      },
                      "required": [
                        "name",
                        "code"
                      ],
                      "additionalProperties": false
                    },
                    "admin2": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "description": "County/district name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    "lat": {
                      "description": "Echo of the input latitude.",
                      "type": "number"
                    },
                    "lng": {
                      "description": "Echo of the input longitude.",
                      "type": "number"
                    },
                    "source": {
                      "description": "Always \"osm\" — regions is resolved from the reverse geocode, no hosted polygons.",
                      "type": "string",
                      "const": "osm"
                    }
                  },
                  "required": [
                    "continent",
                    "country",
                    "admin1",
                    "admin2",
                    "lat",
                    "lng",
                    "source"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/distance": {
      "get": {
        "summary": "Driving distance and route between two coordinates (public OSRM server; car profile). Pass geometry=true for the route LineString as GeoJSON.",
        "description": "Driving distance and route between two coordinates (public OSRM server; car profile). Pass geometry=true for the route LineString as GeoJSON.",
        "tags": [
          "Geo",
          "Geo: Routing & distance"
        ],
        "operationId": "get_v1_geo_distance",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Routing & distance",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "from coordinates as \"lat,lng\" (e.g. \"48.8566,2.3522\").",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "to coordinates as \"lat,lng\" (e.g. \"48.8566,2.3522\").",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "geometry",
            "in": "query",
            "required": false,
            "description": "Pass \"true\" to include the route as GeoJSON geometry. Any other value (or omitting it) means false.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "mode": {
                      "description": "Routing profile — the public OSRM server is car-only today.",
                      "type": "string",
                      "const": "driving"
                    },
                    "distanceMeters": {
                      "description": "Route distance in meters.",
                      "type": "number"
                    },
                    "durationSeconds": {
                      "description": "Route duration in seconds.",
                      "type": "number"
                    },
                    "from": {
                      "description": "Echo of the parsed origin.",
                      "type": "object",
                      "properties": {
                        "lat": {
                          "type": "number"
                        },
                        "lng": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "lat",
                        "lng"
                      ],
                      "additionalProperties": false
                    },
                    "to": {
                      "description": "Echo of the parsed destination.",
                      "type": "object",
                      "properties": {
                        "lat": {
                          "type": "number"
                        },
                        "lng": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "lat",
                        "lng"
                      ],
                      "additionalProperties": false
                    },
                    "geometry": {
                      "description": "GeoJSON LineString of the route, when ?geometry=true.",
                      "anyOf": [
                        {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "mode",
                    "distanceMeters",
                    "durationSeconds",
                    "from",
                    "to",
                    "geometry"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/timezone": {
      "get": {
        "summary": "IANA timezone for coordinates (Open-Meteo).",
        "description": "IANA timezone for coordinates (Open-Meteo).\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Geo",
          "Geo: Lookups"
        ],
        "operationId": "get_v1_geo_timezone",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Lookups",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (-90 to 90).",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Longitude (-180 to 180).",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "timezone": {
                      "description": "IANA timezone id.",
                      "type": "string"
                    },
                    "abbreviation": {
                      "description": "Timezone abbreviation (e.g. CET).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "utcOffset": {
                      "description": "UTC offset as \"±HH:MM\".",
                      "type": "string"
                    },
                    "utcOffsetSeconds": {
                      "description": "UTC offset in seconds.",
                      "type": "number"
                    },
                    "lat": {
                      "description": "Echo of the input latitude.",
                      "type": "number"
                    },
                    "lng": {
                      "description": "Echo of the input longitude.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "timezone",
                    "abbreviation",
                    "utcOffset",
                    "utcOffsetSeconds",
                    "lat",
                    "lng"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/elevation": {
      "get": {
        "summary": "Elevation in meters for coordinates (Open-Meteo).",
        "description": "Elevation in meters for coordinates (Open-Meteo).\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Geo",
          "Geo: Lookups"
        ],
        "operationId": "get_v1_geo_elevation",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Lookups",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (-90 to 90).",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Longitude (-180 to 180).",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "elevation": {
                      "description": "Elevation above sea level.",
                      "type": "number"
                    },
                    "unit": {
                      "type": "string",
                      "const": "meters"
                    },
                    "lat": {
                      "description": "Echo of the input latitude.",
                      "type": "number"
                    },
                    "lng": {
                      "description": "Echo of the input longitude.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "elevation",
                    "unit",
                    "lat",
                    "lng"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/ip": {
      "get": {
        "summary": "Geolocate an IP address — country, city, coordinates, ASN, org (ipwho.is).",
        "description": "Geolocate an IP address — country, city, coordinates, ASN, org (ipwho.is).",
        "tags": [
          "Geo",
          "Geo: Lookups"
        ],
        "operationId": "get_v1_geo_ip",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Lookups",
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": true,
            "description": "IPv4 or IPv6 address to geolocate.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "pattern": "^[0-9a-fA-F:.]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "ip": {
                      "description": "The resolved IP address.",
                      "type": "string"
                    },
                    "country": {
                      "description": "Country name.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "countryCode": {
                      "description": "ISO2 country code.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "region": {
                      "description": "Region/state.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "city": {
                      "description": "City.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lat": {
                      "description": "Latitude, when known.",
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lng": {
                      "description": "Longitude, when known.",
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "timezone": {
                      "description": "IANA timezone id.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "asn": {
                      "description": "Autonomous system number.",
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "org": {
                      "description": "Network operator/ISP name.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "ip",
                    "country",
                    "countryCode",
                    "region",
                    "city",
                    "lat",
                    "lng",
                    "timezone",
                    "asn",
                    "org"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/country-info": {
      "get": {
        "summary": "Country metadata — capital, region, income level, coordinates, flag (World Bank; flag via flagcdn). Pass an ISO2 or ISO3 country code.",
        "description": "Country metadata — capital, region, income level, coordinates, flag (World Bank; flag via flagcdn). Pass an ISO2 or ISO3 country code.",
        "tags": [
          "Geo",
          "Geo: Lookups"
        ],
        "operationId": "get_v1_geo_country-info",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Lookups",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "description": "ISO2 or ISO3 country code.",
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z]{2,3}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "name": {
                      "description": "Country name.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "iso2": {
                      "description": "ISO2 code.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "iso3": {
                      "description": "ISO3 code.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "capital": {
                      "description": "Capital city.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "region": {
                      "description": "World Bank region grouping.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "incomeLevel": {
                      "description": "World Bank income-level grouping.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lat": {
                      "description": "Capital latitude, when known.",
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lng": {
                      "description": "Capital longitude, when known.",
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "flag": {
                      "description": "Flag image URL (flagcdn), when an ISO2 code is known.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "name",
                    "iso2",
                    "iso3",
                    "capital",
                    "region",
                    "incomeLevel",
                    "lat",
                    "lng",
                    "flag"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/postal": {
      "get": {
        "summary": "Postal/ZIP code lookup for 60+ countries (Zippopotam).",
        "description": "Postal/ZIP code lookup for 60+ countries (Zippopotam).",
        "tags": [
          "Geo",
          "Geo: Lookups"
        ],
        "operationId": "get_v1_geo_postal",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Lookups",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "ISO2 country code.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "code",
            "in": "query",
            "required": true,
            "description": "Postal/ZIP code.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "country": {
                      "description": "Country name.",
                      "type": "string"
                    },
                    "countryCode": {
                      "description": "Country code, as echoed by the upstream.",
                      "type": "string"
                    },
                    "postalCode": {
                      "description": "Echo of the postal code.",
                      "type": "string"
                    },
                    "places": {
                      "description": "Places matching this postal code (can be more than one).",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "placeName": {
                            "description": "Place name.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "state": {
                            "description": "State/province.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "stateCode": {
                            "description": "State abbreviation.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lat": {
                            "description": "Latitude, when known.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lng": {
                            "description": "Longitude, when known.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "placeName",
                          "state",
                          "stateCode",
                          "lat",
                          "lng"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "country",
                    "countryCode",
                    "postalCode",
                    "places"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/parcel": {
      "get": {
        "summary": "Property parcel boundary + attributes (APN, owner, situs address, acreage, county) for a US address or lat/lon, served from self-hosted per-state FlatGeobuf files (built from free statewide bulk downloads — not a live upstream proxy). The smallest-area containing parcel is returned as `parcel`; any other overlapping matches come back as `alternates`. Every 200 carries a reference-grade disclaimer — this is public county/state GIS data, not a legal survey. Errors: 404 `parcel_not_covered` when the resolved state isn't loaded yet (includes `loadedStates`); 404 `parcel_not_found` for a gap inside an otherwise-loaded state; 422 `address_not_found` when the address can't be geocoded. Check /v1/geo/parcel/coverage for which states are loaded, plus each source's license/attribution.",
        "description": "Property parcel boundary + attributes (APN, owner, situs address, acreage, county) for a US address or lat/lon, served from self-hosted per-state FlatGeobuf files (built from free statewide bulk downloads — not a live upstream proxy). The smallest-area containing parcel is returned as `parcel`; any other overlapping matches come back as `alternates`. Every 200 carries a reference-grade disclaimer — this is public county/state GIS data, not a legal survey. Errors: 404 `parcel_not_covered` when the resolved state isn't loaded yet (includes `loadedStates`); 404 `parcel_not_found` for a gap inside an otherwise-loaded state; 422 `address_not_found` when the address can't be geocoded. Check /v1/geo/parcel/coverage for which states are loaded, plus each source's license/attribution.\n\n**Example:**\n\n```\n{\n  \"parcel\": {\n    \"apn\": \"0710-123-4567\",\n    \"owner\": \"PUBLIC JOHN Q\",\n    \"situsAddress\": \"123 MAIN ST\",\n    \"acreage\": 0.25,\n    \"county\": \"DANE\",\n    \"state\": \"WI\",\n    \"sourceId\": \"wi_v12\",\n    \"sourceVersion\": \"WI-V12-2026\",\n    \"boundary\": { \"type\": \"MultiPolygon\", \"coordinates\": [[[[-89.401, 43.073], [-89.4008, 43.073], [-89.4008, 43.0732], [-89.401, 43.0732], [-89.401, 43.073]]]] }\n  },\n  \"alternates\": [],\n  \"geocode\": { \"lat\": 43.073, \"lon\": -89.401, \"quality\": \"exact\" },\n  \"disclaimer\": \"Reference-grade parcel geometry from public county/state GIS sources — not a legal survey.\"\n}\n```",
        "tags": [
          "Geo",
          "Geo: Parcels"
        ],
        "operationId": "get_v1_geo_parcel",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Parcels",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "required": false,
            "description": "Free-text US address to geocode, then look up the containing parcel. Wins over lat/lng/lon if both are given.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude — pairs with lng (or its alias lon) when no address is given.",
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude. `lon` is accepted as an alias (this endpoint's own response shape uses `lon`) — if both are given, `lon` wins.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": false,
            "description": "Alias for `lng`, accepted so callers already using this endpoint's own `lon` naming don't break. Wins over `lng` if both are given.",
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "parcel": {
                      "description": "The smallest-area parcel containing the point.",
                      "type": "object",
                      "properties": {
                        "apn": {
                          "description": "Assessor parcel number.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "owner": {
                          "description": "Owner of record, as published by the source.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "situsAddress": {
                          "description": "Site/situs address.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "acreage": {
                          "description": "Parcel acreage.",
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "county": {
                          "description": "County name.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "state": {
                          "description": "USPS 2-letter state code.",
                          "type": "string"
                        },
                        "sourceId": {
                          "description": "Which loaded source this parcel came from.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "sourceVersion": {
                          "description": "Source dataset version.",
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "boundary": {
                          "description": "GeoJSON MultiPolygon geometry.",
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        }
                      },
                      "required": [
                        "apn",
                        "owner",
                        "situsAddress",
                        "acreage",
                        "county",
                        "state",
                        "sourceId",
                        "sourceVersion",
                        "boundary"
                      ],
                      "additionalProperties": false
                    },
                    "alternates": {
                      "description": "Any other overlapping matches.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "apn": {
                            "description": "Assessor parcel number.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "owner": {
                            "description": "Owner of record, as published by the source.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "situsAddress": {
                            "description": "Site/situs address.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "acreage": {
                            "description": "Parcel acreage.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "county": {
                            "description": "County name.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "state": {
                            "description": "USPS 2-letter state code.",
                            "type": "string"
                          },
                          "sourceId": {
                            "description": "Which loaded source this parcel came from.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sourceVersion": {
                            "description": "Source dataset version.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "boundary": {
                            "description": "GeoJSON MultiPolygon geometry.",
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          }
                        },
                        "required": [
                          "apn",
                          "owner",
                          "situsAddress",
                          "acreage",
                          "county",
                          "state",
                          "sourceId",
                          "sourceVersion",
                          "boundary"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "geocode": {
                      "type": "object",
                      "properties": {
                        "lat": {
                          "description": "Resolved latitude.",
                          "type": "number"
                        },
                        "lon": {
                          "description": "Resolved longitude.",
                          "type": "number"
                        },
                        "quality": {
                          "description": "Match quality (e.g. \"exact\", \"rooftop\", \"approximate\", \"provided\").",
                          "type": "string"
                        }
                      },
                      "required": [
                        "lat",
                        "lon",
                        "quality"
                      ],
                      "additionalProperties": false
                    },
                    "disclaimer": {
                      "description": "Reference-grade-data disclaimer, present on every 200.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "parcel",
                    "alternates",
                    "geocode",
                    "disclaimer"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/geo/parcel/coverage": {
      "get": {
        "summary": "Which states have parcel data loaded, and each one's source id, version, license, feature count, and publish date — the attribution surface some source licenses require (read the `license` per state before redistributing). Also useful to call before /v1/geo/parcel to check a jurisdiction is loaded.",
        "description": "Which states have parcel data loaded, and each one's source id, version, license, feature count, and publish date — the attribution surface some source licenses require (read the `license` per state before redistributing). Also useful to call before /v1/geo/parcel to check a jurisdiction is loaded.\n\n**Example:**\n\n```\n{\n  \"generatedAt\": \"2026-07-04T20:30:00.000Z\",\n  \"states\": {\n    \"WI\": { \"sourceId\": \"wi_v12\", \"version\": \"WI-V12-2026\", \"license\": \"Public domain\", \"count\": 1823456, \"publishedAt\": \"2026-07-04T20:30:00.000Z\", \"bbox\": [-92.9, 42.4, -86.2, 47.1] }\n  }\n}\n```",
        "tags": [
          "Geo",
          "Geo: Parcels"
        ],
        "operationId": "get_v1_geo_parcel_coverage",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "geo",
        "x-cheapass-group": "Parcels",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "generatedAt": {
                      "description": "When the manifest was published (ISO), when the publisher set it.",
                      "type": "string"
                    },
                    "states": {
                      "description": "Loaded states, keyed by USPS 2-letter code.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "sourceId": {
                            "description": "Source dataset id.",
                            "type": "string"
                          },
                          "version": {
                            "description": "Source dataset version.",
                            "type": "string"
                          },
                          "license": {
                            "description": "Source license.",
                            "type": "string"
                          },
                          "count": {
                            "description": "Feature count.",
                            "type": "number"
                          },
                          "publishedAt": {
                            "description": "Publish date (ISO).",
                            "type": "string"
                          },
                          "bbox": {
                            "description": "[minX, minY, maxX, maxY] extent (lon/lat), when the publisher wrote one.",
                            "type": "array",
                            "items": {
                              "type": "number"
                            }
                          }
                        },
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "states"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/qr": {
      "get": {
        "summary": "Generate a QR code as SVG or PNG.",
        "description": "Generate a QR code as SVG or PNG.",
        "tags": [
          "Utils",
          "Utils: Generators"
        ],
        "operationId": "get_v1_utils_qr",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Generators",
        "parameters": [
          {
            "name": "data",
            "in": "query",
            "required": true,
            "description": "The text/URL to encode.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Square size in pixels (32–1000).",
            "schema": {
              "default": 200,
              "type": "integer",
              "minimum": 32,
              "maximum": 1000
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output format.",
            "schema": {
              "default": "svg",
              "type": "string",
              "enum": [
                "svg",
                "png"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The QR code image (proxied from api.qrserver.com).",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/avatar": {
      "get": {
        "summary": "Generate a deterministic avatar from a seed (DiceBear).",
        "description": "Generate a deterministic avatar from a seed (DiceBear).",
        "tags": [
          "Utils",
          "Utils: Generators"
        ],
        "operationId": "get_v1_utils_avatar",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Generators",
        "parameters": [
          {
            "name": "seed",
            "in": "query",
            "required": false,
            "description": "Deterministic seed — same seed, same avatar.",
            "schema": {
              "default": "cheapass",
              "type": "string"
            }
          },
          {
            "name": "style",
            "in": "query",
            "required": false,
            "description": "DiceBear style id (e.g. pixel-art, bottts, identicon).",
            "schema": {
              "default": "pixel-art",
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output format.",
            "schema": {
              "default": "svg",
              "type": "string",
              "enum": [
                "svg",
                "png"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The avatar image (DiceBear 9.x).",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/chart": {
      "post": {
        "summary": "Render a Chart.js spec to a PNG/SVG image (self-hosted QuickChart).",
        "description": "Render a Chart.js spec to a PNG/SVG image (self-hosted QuickChart).",
        "tags": [
          "Utils",
          "Utils: Generators"
        ],
        "operationId": "post_v1_utils_chart",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Generators",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "chart": {
                    "description": "A Chart.js configuration object.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "format": {
                    "description": "Output image format.",
                    "default": "png",
                    "type": "string",
                    "enum": [
                      "png",
                      "svg"
                    ]
                  },
                  "width": {
                    "description": "Image width in pixels.",
                    "default": 500,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "height": {
                    "description": "Image height in pixels.",
                    "default": 300,
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "chart",
                  "format",
                  "width",
                  "height"
                ],
                "additionalProperties": false
              },
              "example": {
                "chart": {
                  "type": "bar",
                  "data": {
                    "labels": [
                      "a",
                      "b"
                    ],
                    "datasets": [
                      {
                        "data": [
                          1,
                          2
                        ]
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rendered chart (QuickChart).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/shortlink": {
      "post": {
        "summary": "[coming soon] Create a short link for a destination URL. (Coming soon — returns 501 until the click-tracking store lands; the dedicated links/* product will own this.)",
        "description": "Create a short link for a destination URL. (Coming soon — returns 501 until the click-tracking store lands; the dedicated links/* product will own this.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Utils",
          "Utils: Generators"
        ],
        "operationId": "post_v1_utils_shortlink",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Generators",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "Destination URL.",
                    "type": "string",
                    "format": "uri"
                  },
                  "slug": {
                    "description": "Preferred short slug (optional).",
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com/a/very/long/path"
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/utils/email-validate": {
      "get": {
        "summary": "Validate an email — format, MX record, and disposable-domain check.",
        "description": "Validate an email — format, MX record, and disposable-domain check.",
        "tags": [
          "Utils",
          "Utils: Validation & lookup"
        ],
        "operationId": "get_v1_utils_email-validate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Validation & lookup",
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "required": true,
            "description": "The email address to validate.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "email": {
                      "description": "Echo of the input.",
                      "type": "string"
                    },
                    "domain": {
                      "description": "The domain part, if parseable.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "format": {
                      "description": "Regex format check.",
                      "type": "boolean"
                    },
                    "mx": {
                      "description": "Domain has MX records (DoH lookup, best-effort).",
                      "type": "boolean"
                    },
                    "disposable": {
                      "description": "Domain is a known throwaway provider (best-effort list).",
                      "type": "boolean"
                    },
                    "valid": {
                      "description": "format && mx && !disposable.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "email",
                    "domain",
                    "format",
                    "mx",
                    "disposable",
                    "valid"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/whois": {
      "get": {
        "summary": "Domain registration data via RDAP.",
        "description": "Domain registration data via RDAP.",
        "tags": [
          "Utils",
          "Utils: Validation & lookup"
        ],
        "operationId": "get_v1_utils_whois",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Validation & lookup",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "description": "Domain to look up (RDAP).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "domain": {
                      "description": "Canonical domain (ldhName), or the input domain when RDAP omits it.",
                      "type": "string"
                    },
                    "registrar": {
                      "description": "Registrar name, when RDAP exposes it.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "created": {
                      "description": "Registration date (ISO).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updated": {
                      "description": "Last-changed date (ISO).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expires": {
                      "description": "Expiration date (ISO).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "status": {
                      "description": "RDAP status flags.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "nameservers": {
                      "description": "Nameserver hostnames.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "domain",
                    "registrar",
                    "created",
                    "updated",
                    "expires",
                    "status",
                    "nameservers"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/dns": {
      "get": {
        "summary": "DNS record lookup (A/AAAA/MX/TXT/NS/CNAME) over DoH.",
        "description": "DNS record lookup (A/AAAA/MX/TXT/NS/CNAME) over DoH.",
        "tags": [
          "Utils",
          "Utils: Validation & lookup"
        ],
        "operationId": "get_v1_utils_dns",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Validation & lookup",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Hostname to resolve.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Record type (A, AAAA, MX, TXT, NS, CNAME…).",
            "schema": {
              "default": "A",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "name": {
                      "description": "Echo of the query name.",
                      "type": "string"
                    },
                    "type": {
                      "description": "Echo of the query type.",
                      "type": "string"
                    },
                    "records": {
                      "description": "Answers from Cloudflare DoH.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "description": "Record name.",
                            "type": "string"
                          },
                          "type": {
                            "description": "Numeric DNS record type code.",
                            "type": "number"
                          },
                          "ttl": {
                            "description": "Time-to-live in seconds.",
                            "type": "number"
                          },
                          "data": {
                            "description": "Record data.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "name",
                          "type",
                          "ttl",
                          "data"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "name",
                    "type",
                    "records"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/favicon": {
      "get": {
        "summary": "Resolve and return a site's favicon as an image (Google S2). ?size= 16–256.",
        "description": "Resolve and return a site's favicon as an image (Google S2). ?size= 16–256.",
        "tags": [
          "Utils",
          "Utils: Validation & lookup"
        ],
        "operationId": "get_v1_utils_favicon",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Validation & lookup",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "description": "Site domain (scheme/path tolerated, stripped).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Icon size in pixels (16–256).",
            "schema": {
              "default": 64,
              "type": "integer",
              "minimum": 16,
              "maximum": 256
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The site's favicon (Google S2 service).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/hash": {
      "post": {
        "summary": "Hash a string with the SHA family (sha1, sha256, sha384, sha512) via Web Crypto.",
        "description": "Hash a string with the SHA family (sha1, sha256, sha384, sha512) via Web Crypto.",
        "tags": [
          "Utils",
          "Utils: Encoding & crypto"
        ],
        "operationId": "post_v1_utils_hash",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Encoding & crypto",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "The string to hash (UTF-8).",
                    "type": "string"
                  },
                  "algorithm": {
                    "description": "SHA family only — Web Crypto has no MD5, so neither do we.",
                    "default": "sha256",
                    "type": "string",
                    "enum": [
                      "sha1",
                      "sha256",
                      "sha384",
                      "sha512"
                    ]
                  }
                },
                "required": [
                  "text",
                  "algorithm"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "hello",
                "algorithm": "sha256"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "algorithm": {
                      "description": "The algorithm used.",
                      "type": "string"
                    },
                    "hex": {
                      "description": "Hex-encoded digest.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "algorithm",
                    "hex"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/base64": {
      "post": {
        "summary": "Base64 encode or decode.",
        "description": "Base64 encode or decode.",
        "tags": [
          "Utils",
          "Utils: Encoding & crypto"
        ],
        "operationId": "post_v1_utils_base64",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Encoding & crypto",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Input string (UTF-8 safe).",
                    "type": "string"
                  },
                  "mode": {
                    "description": "Direction.",
                    "default": "encode",
                    "type": "string",
                    "enum": [
                      "encode",
                      "decode"
                    ]
                  }
                },
                "required": [
                  "text",
                  "mode"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "hello",
                "mode": "encode"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "mode": {
                      "description": "The mode applied.",
                      "type": "string"
                    },
                    "result": {
                      "description": "The encoded/decoded output.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "mode",
                    "result"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/jwt-decode": {
      "post": {
        "summary": "Decode a JWT's header and payload (no signature verification).",
        "description": "Decode a JWT's header and payload (no signature verification).",
        "tags": [
          "Utils",
          "Utils: Encoding & crypto"
        ],
        "operationId": "post_v1_utils_jwt-decode",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Encoding & crypto",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The JWT (header.payload.signature).",
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "token"
                ],
                "additionalProperties": false
              },
              "example": {
                "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.sig"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "header": {
                      "description": "Decoded JOSE header.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "payload": {
                      "description": "Decoded claims.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "signatureVerified": {
                      "description": "Always false — we decode, we don't verify.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "header",
                    "payload",
                    "signatureVerified"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/slug": {
      "post": {
        "summary": "Slugify a string (URL-safe).",
        "description": "Slugify a string (URL-safe).",
        "tags": [
          "Utils",
          "Utils: Text"
        ],
        "operationId": "post_v1_utils_slug",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Text",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "The string to slugify.",
                    "type": "string"
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "Hello, World!"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "description": "Lowercase, URL-safe, ≤200 chars.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "slug"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/markdown-render": {
      "post": {
        "summary": "Render markdown to sanitized HTML.",
        "description": "Render markdown to sanitized HTML.",
        "tags": [
          "Utils",
          "Utils: Text"
        ],
        "operationId": "post_v1_utils_markdown-render",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Text",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "markdown": {
                    "description": "Markdown source.",
                    "type": "string"
                  }
                },
                "required": [
                  "markdown"
                ],
                "additionalProperties": false
              },
              "example": {
                "markdown": "# Hi\n\nSome **bold** text."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "html": {
                      "description": "Sanitized HTML (safe subset; raw HTML is escaped).",
                      "type": "string"
                    }
                  },
                  "required": [
                    "html"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/utils/profanity": {
      "post": {
        "summary": "Detect and optionally mask profanity in text.",
        "description": "Detect and optionally mask profanity in text.",
        "tags": [
          "Utils",
          "Utils: Text"
        ],
        "operationId": "post_v1_utils_profanity",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "utils",
        "x-cheapass-group": "Text",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to scan.",
                    "type": "string"
                  },
                  "mask": {
                    "description": "Replace matches with asterisks in `cleaned`.",
                    "default": true,
                    "type": "boolean"
                  }
                },
                "required": [
                  "text",
                  "mask"
                ],
                "additionalProperties": false
              },
              "example": {
                "text": "well damn",
                "mask": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "hasProfanity": {
                      "description": "Any match found.",
                      "type": "boolean"
                    },
                    "matches": {
                      "description": "Distinct matched words (lowercased).",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "cleaned": {
                      "description": "Input with matches masked (or untouched when mask=false).",
                      "type": "string"
                    }
                  },
                  "required": [
                    "hasProfanity",
                    "matches",
                    "cleaned"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/weather-alerts": {
      "get": {
        "summary": "[coming soon] Active NWS weather alerts by area (US National Weather Service).",
        "description": "Active NWS weather alerts by area (US National Weather Service).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_weather-alerts",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "required": false,
            "description": "Two-letter US state/area code to filter alerts by (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/hurricanes": {
      "get": {
        "summary": "[coming soon] Active tropical cyclones and advisories (NOAA NHC).",
        "description": "Active tropical cyclones and advisories (NOAA NHC).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_hurricanes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/wildfires": {
      "get": {
        "summary": "[coming soon] Satellite-detected active fire hotspots (NASA FIRMS).",
        "description": "Satellite-detected active fire hotspots (NASA FIRMS).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_wildfires",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "required": false,
            "description": "Area filter (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Lookback window in days (optional).",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/volcanoes": {
      "get": {
        "summary": "[coming soon] Current volcanic eruptions (Smithsonian GVP).",
        "description": "Current volcanic eruptions (Smithsonian GVP).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_volcanoes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/earthquakes": {
      "get": {
        "summary": "[coming soon] Real-time earthquakes over a time window (USGS feeds).",
        "description": "Real-time earthquakes over a time window (USGS feeds).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_earthquakes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "Time window to query over.",
            "schema": {
              "default": "day",
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week",
                "month"
              ]
            }
          },
          {
            "name": "minMagnitude",
            "in": "query",
            "required": false,
            "description": "Minimum magnitude to include (optional).",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/tsunamis": {
      "get": {
        "summary": "[coming soon] Tsunami warnings and advisories (NOAA PTWC).",
        "description": "Tsunami warnings and advisories (NOAA PTWC).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_tsunamis",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/natural-events": {
      "get": {
        "summary": "[coming soon] Combined open natural-event stream — fires, storms, volcanoes, floods (NASA EONET).",
        "description": "Combined open natural-event stream — fires, storms, volcanoes, floods (NASA EONET).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Natural hazards"
        ],
        "operationId": "get_v1_events_natural-events",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Natural hazards",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Event status filter.",
            "schema": {
              "default": "open",
              "type": "string",
              "enum": [
                "open",
                "closed"
              ]
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "EONET category filter (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/space-weather": {
      "get": {
        "summary": "[coming soon] Solar flares, geomagnetic storms, Kp index, aurora forecasts (NOAA SWPC).",
        "description": "Solar flares, geomagnetic storms, Kp index, aurora forecasts (NOAA SWPC).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Space & sky"
        ],
        "operationId": "get_v1_events_space-weather",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Space & sky",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/iss-position": {
      "get": {
        "summary": "[coming soon] Current International Space Station position and velocity (Where The ISS At).",
        "description": "Current International Space Station position and velocity (Where The ISS At).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Space & sky"
        ],
        "operationId": "get_v1_events_iss-position",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Space & sky",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/launches": {
      "get": {
        "summary": "[coming soon] Upcoming and recent rocket launches (Launch Library 2).",
        "description": "Upcoming and recent rocket launches (Launch Library 2).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Space & sky"
        ],
        "operationId": "get_v1_events_launches",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Space & sky",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "upcoming",
            "in": "query",
            "required": false,
            "description": "Only upcoming launches when \"true\" (optional).",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max results to return (optional).",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/satellite-passes": {
      "get": {
        "summary": "[coming soon] Visible satellite passes for a location (CelesTrak TLE + SGP4).",
        "description": "Visible satellite passes for a location (CelesTrak TLE + SGP4).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Space & sky"
        ],
        "operationId": "get_v1_events_satellite-passes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Space & sky",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Observer latitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "description": "Observer longitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "satId",
            "in": "query",
            "required": false,
            "description": "Specific satellite NORAD id to filter by (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/asteroids": {
      "get": {
        "summary": "[coming soon] Near-earth objects and close approaches (NASA NeoWs).",
        "description": "Near-earth objects and close approaches (NASA NeoWs).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Space & sky"
        ],
        "operationId": "get_v1_events_asteroids",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Space & sky",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": false,
            "description": "Start date (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": false,
            "description": "End date (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/conflict": {
      "get": {
        "summary": "[coming soon] Geolocated world-news events with actor/theme tagging (GDELT).",
        "description": "Geolocated world-news events with actor/theme tagging (GDELT).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Geopolitics & internet"
        ],
        "operationId": "get_v1_events_conflict",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Geopolitics & internet",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Free-text filter (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxrecords",
            "in": "query",
            "required": false,
            "description": "Max records to return (optional).",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/internet-health": {
      "get": {
        "summary": "[coming soon] Internet traffic, BGP, DDoS, and country outage signals (Cloudflare Radar).",
        "description": "Internet traffic, BGP, DDoS, and country outage signals (Cloudflare Radar).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Geopolitics & internet"
        ],
        "operationId": "get_v1_events_internet-health",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Geopolitics & internet",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "required": false,
            "description": "Metric to query (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location",
            "in": "query",
            "required": false,
            "description": "Location filter, e.g. a country code (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/bgp": {
      "get": {
        "summary": "[coming soon] BGP routing and ASN/prefix info (RIPEstat / BGPview).",
        "description": "BGP routing and ASN/prefix info (RIPEstat / BGPview).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Geopolitics & internet"
        ],
        "operationId": "get_v1_events_bgp",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Geopolitics & internet",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "description": "ASN to look up (alternative to prefix).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "prefix",
            "in": "query",
            "required": false,
            "description": "IP prefix to look up (alternative to asn).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/airport-status": {
      "get": {
        "summary": "[coming soon] US airport delays, ground stops, and closures (FAA).",
        "description": "US airport delays, ground stops, and closures (FAA).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Aviation & maritime"
        ],
        "operationId": "get_v1_events_airport-status",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Aviation & maritime",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "airport",
            "in": "query",
            "required": false,
            "description": "Airport code to look up (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/ships": {
      "get": {
        "summary": "[coming soon] AIS vessel positions in US waters (MarineCadastre).",
        "description": "AIS vessel positions in US waters (MarineCadastre).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Aviation & maritime"
        ],
        "operationId": "get_v1_events_ships",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Aviation & maritime",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "bbox",
            "in": "query",
            "required": false,
            "description": "Bounding box filter, e.g. \"minLng,minLat,maxLng,maxLat\" (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/events/subscribe": {
      "post": {
        "summary": "[coming soon] Register a webhook to receive new events from a stream as they appear.",
        "description": "Register a webhook to receive new events from a stream as they appear.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Events",
          "Events: Delivery"
        ],
        "operationId": "post_v1_events_subscribe",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "events",
        "x-cheapass-group": "Delivery",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "stream": {
                    "description": "Which event stream to subscribe to (endpoint name, e.g. \"earthquakes\").",
                    "type": "string",
                    "minLength": 1
                  },
                  "filter": {
                    "description": "Stream-specific filter to narrow delivered events (optional).",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "webhookUrl": {
                    "description": "Webhook URL to receive new events.",
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "stream",
                  "webhookUrl"
                ],
                "additionalProperties": false
              },
              "example": {
                "stream": "earthquakes",
                "webhookUrl": "https://example.com/webhooks/events"
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/transit/agencies": {
      "get": {
        "summary": "[coming soon] List covered transit agencies.",
        "description": "List covered transit agencies.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Transit"
        ],
        "operationId": "get_v1_transit_agencies",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "transit",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "required": false,
            "description": "Filter agencies by area (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/transit/routes": {
      "get": {
        "summary": "[coming soon] Routes for an agency.",
        "description": "Routes for an agency.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Transit"
        ],
        "operationId": "get_v1_transit_routes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "transit",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "agencyId",
            "in": "query",
            "required": true,
            "description": "The agency to list routes for.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/transit/stops": {
      "get": {
        "summary": "[coming soon] Stops near a point or on a route.",
        "description": "Stops near a point or on a route.\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Transit"
        ],
        "operationId": "get_v1_transit_stops",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "transit",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude, for a stops-near-point query (pair with lng/radius).",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude, for a stops-near-point query (pair with lat/radius).",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "radius",
            "in": "query",
            "required": false,
            "description": "Search radius in meters, for a stops-near-point query.",
            "schema": {
              "type": "number",
              "exclusiveMinimum": 0
            }
          },
          {
            "name": "routeId",
            "in": "query",
            "required": false,
            "description": "Alternative to lat/lng/radius — list stops on this route instead.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/transit/realtime": {
      "get": {
        "summary": "[coming soon] Real-time vehicle positions, trip updates, and service alerts (GTFS-RT).",
        "description": "Real-time vehicle positions, trip updates, and service alerts (GTFS-RT).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Transit"
        ],
        "operationId": "get_v1_transit_realtime",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "transit",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "agencyId",
            "in": "query",
            "required": false,
            "description": "Filter by agency (alternative to routeId).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "routeId",
            "in": "query",
            "required": false,
            "description": "Filter by route (alternative to agencyId).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/transit/plan": {
      "get": {
        "summary": "[coming soon] Plan a multimodal trip between two points (OpenTripPlanner).",
        "description": "Plan a multimodal trip between two points (OpenTripPlanner).\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Transit"
        ],
        "operationId": "get_v1_transit_plan",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "transit",
        "x-cheapass-status": "coming_soon",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "Origin coordinates, \"lat,lng\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Destination coordinates, \"lat,lng\".",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "Departure/arrival time (optional).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "modes",
            "in": "query",
            "required": false,
            "description": "Comma-separated travel modes to allow (optional).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/links/shorten": {
      "post": {
        "summary": "[coming soon] Create a short link. (Coming soon — 501 today.)",
        "description": "Create a short link. (Coming soon — 501 today.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Links"
        ],
        "operationId": "post_v1_links_shorten",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "links",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "description": "Destination URL to shorten.",
                    "type": "string",
                    "format": "uri"
                  },
                  "slug": {
                    "description": "Preferred short slug (optional).",
                    "type": "string"
                  },
                  "domain": {
                    "description": "Custom domain to serve the short link from (optional).",
                    "type": "string"
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com/a/very/long/path"
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/links": {
      "get": {
        "summary": "[coming soon] List your short links with click counts. (Coming soon — 501 today.)",
        "description": "List your short links with click counts. (Coming soon — 501 today.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "Links"
        ],
        "operationId": "get_v1_links",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "links",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/og/image": {
      "get": {
        "summary": "Render a 1200×630 social-card PNG from query params (title, subtitle, theme). Accepts ?key= so the URL works inside an og:image meta tag. Cached by exact params.",
        "description": "Render a 1200×630 social-card PNG from query params (title, subtitle, theme). Accepts ?key= so the URL works inside an og:image meta tag. Cached by exact params.",
        "tags": [
          "OG Images"
        ],
        "operationId": "get_v1_og_image",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "og",
        "parameters": [
          {
            "name": "title",
            "in": "query",
            "required": true,
            "description": "The big line.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "subtitle",
            "in": "query",
            "required": false,
            "description": "The smaller line under it.",
            "schema": {
              "type": "string",
              "maxLength": 300
            }
          },
          {
            "name": "theme",
            "in": "query",
            "required": false,
            "description": "Default template theme.",
            "schema": {
              "default": "light",
              "type": "string",
              "enum": [
                "light",
                "dark"
              ]
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": false,
            "description": "API key as a query param — for og:image meta tags, where request headers are impossible. Prefer the Authorization header everywhere else.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A 1200×630 PNG. Renders are cached by their exact parameters — the same URL always serves the same bytes, so crawlers can treat it as a static image.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/og/render": {
      "post": {
        "summary": "Render a card from a full { layers: [...] } stack — background, images, text, badges. Cached by the exact spec.",
        "description": "Render a card from a full { layers: [...] } stack — background, images, text, badges. Cached by the exact spec.",
        "tags": [
          "OG Images"
        ],
        "operationId": "post_v1_og_render",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "og",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "layers": {
                    "description": "Bottom-up layer stack: background, image, text, badge.",
                    "minItems": 1,
                    "maxItems": 12,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "background"
                            },
                            "color": {
                              "description": "Solid CSS color, e.g. #131311.",
                              "type": "string"
                            },
                            "gradient": {
                              "description": "CSS gradient, e.g. linear-gradient(0deg, #0a0a0a, #141414). Wins over color.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "image"
                            },
                            "url": {
                              "description": "Public http(s) image URL. Fills the canvas unless positioned.",
                              "type": "string",
                              "format": "uri"
                            },
                            "fit": {
                              "description": "object-fit (default cover).",
                              "type": "string",
                              "enum": [
                                "cover",
                                "contain"
                              ]
                            },
                            "x": {
                              "description": "Left offset in px — providing x/y/width positions the image.",
                              "type": "number"
                            },
                            "y": {
                              "type": "number"
                            },
                            "width": {
                              "type": "number"
                            },
                            "height": {
                              "type": "number"
                            },
                            "filter": {
                              "description": "CSS filter, e.g. grayscale(100%).",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type",
                            "url"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "text"
                            },
                            "content": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 400
                            },
                            "size": {
                              "description": "Font size in px (default 48).",
                              "type": "number"
                            },
                            "weight": {
                              "anyOf": [
                                {
                                  "type": "number",
                                  "const": 400
                                },
                                {
                                  "type": "number",
                                  "const": 700
                                }
                              ]
                            },
                            "color": {
                              "type": "string"
                            },
                            "x": {
                              "description": "Absolute position; omit x/y to flow in a centered column.",
                              "type": "number"
                            },
                            "y": {
                              "type": "number"
                            },
                            "letterSpacing": {
                              "type": "number"
                            },
                            "maxWidth": {
                              "type": "number"
                            }
                          },
                          "required": [
                            "type",
                            "content"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "badge"
                            },
                            "corner": {
                              "description": "Default bottom-right.",
                              "type": "string",
                              "enum": [
                                "top-left",
                                "top-right",
                                "bottom-left",
                                "bottom-right"
                              ]
                            },
                            "text": {
                              "type": "string",
                              "maxLength": 80
                            },
                            "imageUrl": {
                              "description": "Logo/image inside the badge box.",
                              "type": "string",
                              "format": "uri"
                            },
                            "imageWidth": {
                              "type": "number"
                            },
                            "imageHeight": {
                              "type": "number"
                            },
                            "background": {
                              "type": "string"
                            },
                            "color": {
                              "type": "string"
                            },
                            "border": {
                              "description": "CSS border (default 2px solid #131311).",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    }
                  },
                  "width": {
                    "default": 1200,
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 2000
                  },
                  "height": {
                    "default": 630,
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 2000
                  }
                },
                "required": [
                  "layers",
                  "width",
                  "height"
                ],
                "additionalProperties": false
              },
              "example": {
                "layers": [
                  {
                    "type": "background",
                    "color": "#131311"
                  },
                  {
                    "type": "text",
                    "content": "Hello",
                    "size": 72,
                    "color": "#F8F8F1"
                  },
                  {
                    "type": "badge",
                    "corner": "bottom-right",
                    "text": "example.dev",
                    "background": "#F8F8F1"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rendered PNG. Cached by the exact layer spec.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/og/templates": {
      "post": {
        "summary": "[coming soon] Save a reusable card template — a layer stack with named text slots. (Coming soon — 501 today.)",
        "description": "Save a reusable card template — a layer stack with named text slots. (Coming soon — 501 today.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "OG Images"
        ],
        "operationId": "post_v1_og_templates",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "og",
        "x-cheapass-status": "coming_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Template name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "layers": {
                    "description": "The saved layer stack; text layers become fillable slots.",
                    "minItems": 1,
                    "maxItems": 12,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "background"
                            },
                            "color": {
                              "description": "Solid CSS color, e.g. #131311.",
                              "type": "string"
                            },
                            "gradient": {
                              "description": "CSS gradient, e.g. linear-gradient(0deg, #0a0a0a, #141414). Wins over color.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "image"
                            },
                            "url": {
                              "description": "Public http(s) image URL. Fills the canvas unless positioned.",
                              "type": "string",
                              "format": "uri"
                            },
                            "fit": {
                              "description": "object-fit (default cover).",
                              "type": "string",
                              "enum": [
                                "cover",
                                "contain"
                              ]
                            },
                            "x": {
                              "description": "Left offset in px — providing x/y/width positions the image.",
                              "type": "number"
                            },
                            "y": {
                              "type": "number"
                            },
                            "width": {
                              "type": "number"
                            },
                            "height": {
                              "type": "number"
                            },
                            "filter": {
                              "description": "CSS filter, e.g. grayscale(100%).",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type",
                            "url"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "text"
                            },
                            "content": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 400
                            },
                            "size": {
                              "description": "Font size in px (default 48).",
                              "type": "number"
                            },
                            "weight": {
                              "anyOf": [
                                {
                                  "type": "number",
                                  "const": 400
                                },
                                {
                                  "type": "number",
                                  "const": 700
                                }
                              ]
                            },
                            "color": {
                              "type": "string"
                            },
                            "x": {
                              "description": "Absolute position; omit x/y to flow in a centered column.",
                              "type": "number"
                            },
                            "y": {
                              "type": "number"
                            },
                            "letterSpacing": {
                              "type": "number"
                            },
                            "maxWidth": {
                              "type": "number"
                            }
                          },
                          "required": [
                            "type",
                            "content"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "badge"
                            },
                            "corner": {
                              "description": "Default bottom-right.",
                              "type": "string",
                              "enum": [
                                "top-left",
                                "top-right",
                                "bottom-left",
                                "bottom-right"
                              ]
                            },
                            "text": {
                              "type": "string",
                              "maxLength": 80
                            },
                            "imageUrl": {
                              "description": "Logo/image inside the badge box.",
                              "type": "string",
                              "format": "uri"
                            },
                            "imageWidth": {
                              "type": "number"
                            },
                            "imageHeight": {
                              "type": "number"
                            },
                            "background": {
                              "type": "string"
                            },
                            "color": {
                              "type": "string"
                            },
                            "border": {
                              "description": "CSS border (default 2px solid #131311).",
                              "type": "string"
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    }
                  }
                },
                "required": [
                  "name",
                  "layers"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "article-card",
                "layers": [
                  {
                    "type": "background",
                    "color": "#131311"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      },
      "get": {
        "summary": "[coming soon] List your saved templates. (Coming soon — 501 today.)",
        "description": "List your saved templates. (Coming soon — 501 today.)\n\n_Coming soon — returns 501 until shipped._",
        "tags": [
          "OG Images"
        ],
        "operationId": "get_v1_og_templates",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "og",
        "x-cheapass-status": "coming_soon",
        "responses": {
          "501": {
            "description": "Not implemented yet (coming soon)."
          }
        }
      }
    },
    "/v1/trends/watch": {
      "post": {
        "summary": "Register terms to track. Idempotent on normalized term.",
        "description": "Register terms to track. Idempotent on normalized term.\n\n**Example:**\n\n```\n{ \"inserted\": 2, \"existing\": 0 }\n```",
        "tags": [
          "Trends",
          "Trends: Watchlist"
        ],
        "operationId": "post_v1_trends_watch",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Watchlist",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "terms": {
                    "description": "Terms to register for tracking (idempotent on normalized term).",
                    "minItems": 1,
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "description": "A term to track.",
                      "type": "string",
                      "minLength": 1
                    }
                  }
                },
                "required": [
                  "terms"
                ],
                "additionalProperties": false
              },
              "example": {
                "terms": [
                  "taylor swift",
                  "ai regulation"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "inserted": {
                      "description": "Newly-registered terms.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "existing": {
                      "description": "Terms that were already on the watchlist.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "inserted",
                    "existing"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/trends/top": {
      "get": {
        "summary": "Top movers by composite momentum for a window (24h|7d).",
        "description": "Top movers by composite momentum for a window (24h|7d).\n\n**Example:**\n\n```\n[{ \"term\": \"taylor swift\", \"composite\": 87.4, \"velocity\": 12.1, \"rank\": 1 }]\n```",
        "tags": [
          "Trends",
          "Trends: Reading"
        ],
        "operationId": "get_v1_trends_top",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Reading",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "Momentum window: 1h | 4h | 24h | 7d | 30d | yesterday | thisYear | lastYear | allTime. Defaults to \"7d\".",
            "schema": {
              "default": "7d",
              "type": "string",
              "enum": [
                "1h",
                "4h",
                "24h",
                "7d",
                "30d",
                "yesterday",
                "thisYear",
                "lastYear",
                "allTime"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max rows to return. Omit for the endpoint's own default.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Top movers by composite momentum, ranked ascending.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "term": {
                        "description": "The tracked term.",
                        "type": "string"
                      },
                      "composite": {
                        "description": "0–100 weighted composite momentum.",
                        "type": "number"
                      },
                      "velocity": {
                        "description": "Signed momentum delta vs. the prior period.",
                        "type": "number"
                      },
                      "rank": {
                        "description": "Rank within this window, 1 = highest composite.",
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "sampleSources": {
                        "description": "Signal sources that fed the composite.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "term",
                      "composite",
                      "velocity",
                      "rank",
                      "sampleSources"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/trends/term": {
      "get": {
        "summary": "Composite + per-source time series for one term.",
        "description": "Composite + per-source time series for one term.\n\n**Example:**\n\n```\n{ \"term\": \"taylor swift\", \"composite\": 87.4, \"series\": [] }\n```",
        "tags": [
          "Trends",
          "Trends: Reading"
        ],
        "operationId": "get_v1_trends_term",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Reading",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "The term to look up (must already be on the watchlist).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "Momentum window: 1h | 4h | 24h | 7d | 30d | yesterday | thisYear | lastYear | allTime. Defaults to \"7d\".",
            "schema": {
              "default": "7d",
              "type": "string",
              "enum": [
                "1h",
                "4h",
                "24h",
                "7d",
                "30d",
                "yesterday",
                "thisYear",
                "lastYear",
                "allTime"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "term": {
                      "description": "The tracked term (canonical form).",
                      "type": "string"
                    },
                    "composite": {
                      "description": "0–100 weighted composite momentum for the window (0 if not yet computed).",
                      "type": "number"
                    },
                    "velocity": {
                      "description": "Signed momentum delta vs. the prior period (0 if not yet computed).",
                      "type": "number"
                    },
                    "series": {
                      "description": "Per-source time series over the window.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "description": "Signal source id (e.g. gdelt, wikipedia).",
                            "type": "string"
                          },
                          "points": {
                            "description": "Time series, ascending by capturedAt.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "capturedAt": {
                                  "description": "Sample timestamp, ms since epoch.",
                                  "type": "number"
                                },
                                "value": {
                                  "description": "Normalized 0–100 source value at that timestamp.",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "capturedAt",
                                "value"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "source",
                          "points"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "term",
                    "composite",
                    "velocity",
                    "series"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/trends/rising": {
      "get": {
        "summary": "Currently-rising terms (not necessarily on the watchlist).",
        "description": "Currently-rising terms (not necessarily on the watchlist).\n\n**Example:**\n\n```\n[{ \"term\": \"quokka\", \"source\": \"rss\", \"approxTraffic\": 12 }]\n```",
        "tags": [
          "Trends",
          "Trends: Discovery"
        ],
        "operationId": "get_v1_trends_rising",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Discovery",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max rows to return. Omit for the endpoint's own default.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Deduplicated, currently-rising terms, most recent discovery first.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "term": {
                        "description": "The rising term (not necessarily on the watchlist).",
                        "type": "string"
                      },
                      "source": {
                        "description": "Discovery source, e.g. \"rss\" or \"wikipedia\".",
                        "type": "string"
                      },
                      "approxTraffic": {
                        "description": "Discovery source's own popularity signal, when it reports one (field is absent otherwise).",
                        "type": "number"
                      }
                    },
                    "required": [
                      "term",
                      "source"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/trends/topics": {
      "get": {
        "summary": "Ranked content-derived topics. Filter by category, kind, window, and the sources trends derive from (?sources= recomputes scores from that subset).",
        "description": "Ranked content-derived topics. Filter by category, kind, window, and the sources trends derive from (?sources= recomputes scores from that subset).\n\n**Example:**\n\n```\n[{ \"topic\": \"airline seat fees\", \"kind\": \"theme\", \"category\": \"consumer\", \"composite\": 87.2, \"velocity\": 12.4, \"rank\": 1, \"sources\": [{ \"source\": \"rss\", \"composite\": 87.2, \"mentions\": 14 }] }]\n```",
        "tags": [
          "Trends",
          "Trends: Topics"
        ],
        "operationId": "get_v1_trends_topics",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Topics",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "Topic window: 24h | 7d | 30d. Defaults to \"24h\".",
            "schema": {
              "default": "24h",
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ]
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by category: cultural | consumer | political | tech | business.",
            "schema": {
              "type": "string",
              "enum": [
                "cultural",
                "consumer",
                "political",
                "tech",
                "business"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Filter by kind: theme | entity | product | tag.",
            "schema": {
              "type": "string",
              "enum": [
                "theme",
                "entity",
                "product",
                "tag"
              ]
            }
          },
          {
            "name": "sources",
            "in": "query",
            "required": false,
            "description": "Comma-separated doc-source ids to recompute topic scores from (e.g. \"rss\"). The literal \"all\" and unknown ids are rejected.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max rows to return. Omit for the endpoint's own default.",
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Ranked content-derived topics.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "topic": {
                        "description": "Canonical topic name.",
                        "type": "string"
                      },
                      "kind": {
                        "description": "Topic kind.",
                        "type": "string",
                        "enum": [
                          "theme",
                          "entity",
                          "product",
                          "tag"
                        ]
                      },
                      "category": {
                        "description": "Topic category.",
                        "type": "string",
                        "enum": [
                          "cultural",
                          "consumer",
                          "political",
                          "tech",
                          "business"
                        ]
                      },
                      "aliases": {
                        "description": "Known aliases for this topic.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "composite": {
                        "description": "0–100 momentum score (recomputed from ?sources= when given).",
                        "type": "number"
                      },
                      "velocity": {
                        "description": "Signed momentum delta vs. the prior period.",
                        "type": "number"
                      },
                      "rank": {
                        "description": "Rank within the requested cohort.",
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "sources": {
                        "description": "Per-source momentum breakdown for this topic.",
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "description": "Doc-source id this row's momentum was computed from.",
                              "type": "string"
                            },
                            "composite": {
                              "description": "0–100 momentum score within this (window, source) cohort.",
                              "type": "number"
                            },
                            "mentions": {
                              "description": "Mention count in the current window.",
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "source",
                            "composite",
                            "mentions"
                          ],
                          "additionalProperties": false
                        }
                      }
                    },
                    "required": [
                      "topic",
                      "kind",
                      "category",
                      "aliases",
                      "composite",
                      "velocity",
                      "rank",
                      "sources"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/trends/topics/detail": {
      "get": {
        "summary": "One topic (canonical name or alias): metadata, per-source momentum across windows, hourly mention series.",
        "description": "One topic (canonical name or alias): metadata, per-source momentum across windows, hourly mention series.\n\n**Example:**\n\n```\n{ \"topic\": \"airline seat fees\", \"kind\": \"theme\", \"category\": \"consumer\", \"momentum\": [], \"series\": [] }\n```",
        "tags": [
          "Trends",
          "Trends: Topics"
        ],
        "operationId": "get_v1_trends_topics_detail",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "trends",
        "x-cheapass-group": "Topics",
        "parameters": [
          {
            "name": "topic",
            "in": "query",
            "required": true,
            "description": "Topic canonical name or a known alias.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "topic": {
                      "description": "Canonical topic name.",
                      "type": "string"
                    },
                    "kind": {
                      "description": "Topic kind.",
                      "type": "string",
                      "enum": [
                        "theme",
                        "entity",
                        "product",
                        "tag"
                      ]
                    },
                    "category": {
                      "description": "Topic category.",
                      "type": "string",
                      "enum": [
                        "cultural",
                        "consumer",
                        "political",
                        "tech",
                        "business"
                      ]
                    },
                    "aliases": {
                      "description": "Known aliases for this topic.",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "firstSeenAt": {
                      "description": "First-seen timestamp, ms since epoch.",
                      "type": "number"
                    },
                    "lastMentionAt": {
                      "description": "Most recent mention timestamp, ms since epoch.",
                      "type": "number"
                    },
                    "momentum": {
                      "description": "Per-(window, source) momentum rows, including the \"all\" blend.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "window": {
                            "description": "The window this momentum row covers.",
                            "type": "string",
                            "enum": [
                              "24h",
                              "7d",
                              "30d"
                            ]
                          },
                          "source": {
                            "description": "Doc-source id, or \"all\" for the unfiltered blend.",
                            "type": "string"
                          },
                          "composite": {
                            "description": "0–100 momentum score within this (window, source) cohort.",
                            "type": "number"
                          },
                          "velocity": {
                            "description": "Signed momentum delta vs. the prior period.",
                            "type": "number"
                          },
                          "rank": {
                            "description": "Rank within this (window, source) cohort.",
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "mentions": {
                            "description": "Mention count in the current window.",
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "window",
                          "source",
                          "composite",
                          "velocity",
                          "rank",
                          "mentions"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "series": {
                      "description": "Per-source hourly mention series, last 7 days.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "description": "Doc-source id.",
                            "type": "string"
                          },
                          "points": {
                            "description": "Hourly mention buckets, ascending by bucketStart, last 7 days.",
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "bucketStart": {
                                  "description": "UTC-hour bucket start, ms since epoch.",
                                  "type": "number"
                                },
                                "mentions": {
                                  "description": "Mentions in that hour bucket.",
                                  "type": "integer",
                                  "minimum": 0,
                                  "maximum": 9007199254740991
                                }
                              },
                              "required": [
                                "bucketStart",
                                "mentions"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "source",
                          "points"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "topic",
                    "kind",
                    "category",
                    "aliases",
                    "firstSeenAt",
                    "lastMentionAt",
                    "momentum",
                    "series"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/leagues": {
      "get": {
        "summary": "Every tracked league: slug, sport, upstream source, live-game count.",
        "description": "Every tracked league: slug, sport, upstream source, live-game count.\n\n**Example:**\n\n```\n[{ \"slug\": \"mlb\", \"name\": \"Major League Baseball\", \"sport\": \"baseball\", \"source\": \"mlb\", \"liveGames\": 6 }]\n```\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Reference"
        ],
        "operationId": "get_v1_sports_leagues",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Reference",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "slug": {
                        "description": "League slug.",
                        "type": "string"
                      },
                      "name": {
                        "description": "League display name.",
                        "type": "string"
                      },
                      "sport": {
                        "description": "Sport category (e.g. \"baseball\", \"soccer\").",
                        "type": "string"
                      },
                      "source": {
                        "description": "Primary upstream adapter id (\"espn\" | \"mlb\" | \"nhl\").",
                        "type": "string"
                      },
                      "liveGames": {
                        "description": "Number of games currently live in this league.",
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 9007199254740991
                      },
                      "lastSuccessAt": {
                        "description": "Ms-epoch of the league's last successful poll, or null if never polled.",
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "slug",
                      "name",
                      "sport",
                      "source",
                      "liveGames",
                      "lastSuccessAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/scoreboard": {
      "get": {
        "summary": "Scoreboard for a date (default: the current window). Normalized envelope regardless of upstream.",
        "description": "Scoreboard for a date (default: the current window). Normalized envelope regardless of upstream.\n\n**Example:**\n\n```\n{ \"league\": \"mlb\", \"games\": [{ \"gameId\": \"824659\", \"status\": \"final\", \"home\": { \"name\": \"Chicago Cubs\", \"score\": 1 }, \"away\": { \"name\": \"St. Louis Cardinals\", \"score\": 17 } }] }\n```\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Scores"
        ],
        "operationId": "get_v1_sports__league_scoreboard",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Scores",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Historical or future date to fetch (YYYY-MM-DD). Cached forever once fetched for a past date. Omit for the default current window (UTC yesterday + today).",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "league": {
                      "description": "League slug.",
                      "type": "string"
                    },
                    "date": {
                      "description": "The requested date (YYYY-MM-DD), or null for the default current window.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "games": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "league": {
                            "description": "League slug.",
                            "type": "string"
                          },
                          "gameId": {
                            "description": "Upstream game id — stable within a league, opaque otherwise.",
                            "type": "string"
                          },
                          "date": {
                            "description": "League-local official date, YYYY-MM-DD.",
                            "type": "string"
                          },
                          "startTime": {
                            "description": "Scheduled start, ISO 8601 UTC.",
                            "type": "string"
                          },
                          "status": {
                            "description": "Game status.",
                            "type": "string",
                            "enum": [
                              "scheduled",
                              "live",
                              "final"
                            ]
                          },
                          "detail": {
                            "description": "Human status line as the upstream renders it (\"Top 5th\", \"FT-Pens\"), or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "period": {
                            "description": "Current period/inning/quarter, or null.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "clock": {
                            "description": "Game clock, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "home": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "Upstream team id.",
                                "type": "string"
                              },
                              "name": {
                                "description": "Team name.",
                                "type": "string"
                              },
                              "abbreviation": {
                                "description": "Team abbreviation, when the upstream provides one.",
                                "type": "string"
                              },
                              "score": {
                                "description": "Current score, once the game has started.",
                                "type": "number"
                              },
                              "logo": {
                                "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                                "type": "string"
                              },
                              "record": {
                                "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": false
                          },
                          "away": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "Upstream team id.",
                                "type": "string"
                              },
                              "name": {
                                "description": "Team name.",
                                "type": "string"
                              },
                              "abbreviation": {
                                "description": "Team abbreviation, when the upstream provides one.",
                                "type": "string"
                              },
                              "score": {
                                "description": "Current score, once the game has started.",
                                "type": "number"
                              },
                              "logo": {
                                "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                                "type": "string"
                              },
                              "record": {
                                "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": false
                          },
                          "venue": {
                            "description": "Venue name, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "description": "Which upstream adapter produced this row (\"espn\" | \"mlb\" | \"nhl\").",
                            "type": "string"
                          },
                          "cachedAt": {
                            "description": "ISO timestamp this row was last confirmed current.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "league",
                          "gameId",
                          "date",
                          "startTime",
                          "status",
                          "detail",
                          "period",
                          "clock",
                          "home",
                          "away",
                          "venue",
                          "source",
                          "cachedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cachedAt": {
                      "description": "ISO timestamp of the freshest game in this response, or null when there are no games.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "league",
                    "date",
                    "games",
                    "cachedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/scoreboard/live": {
      "get": {
        "summary": "Only in-progress games. Throttled to a new snapshot every ~10s on Sports Scores; streamed as fast as scores arrive on Live Sports Scores.",
        "description": "Only in-progress games. Throttled to a new snapshot every ~10s on Sports Scores; streamed as fast as scores arrive on Live Sports Scores.\n\n**Example:**\n\n```\n{ \"league\": \"worldcup\", \"games\": [{ \"gameId\": \"733839\", \"status\": \"live\", \"clock\": \"73'\", \"period\": 2 }] }\n```\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Scores"
        ],
        "operationId": "get_v1_sports__league_scoreboard_live",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Scores",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "league": {
                      "description": "League slug.",
                      "type": "string"
                    },
                    "games": {
                      "description": "Only in-progress games — may be empty.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "league": {
                            "description": "League slug.",
                            "type": "string"
                          },
                          "gameId": {
                            "description": "Upstream game id — stable within a league, opaque otherwise.",
                            "type": "string"
                          },
                          "date": {
                            "description": "League-local official date, YYYY-MM-DD.",
                            "type": "string"
                          },
                          "startTime": {
                            "description": "Scheduled start, ISO 8601 UTC.",
                            "type": "string"
                          },
                          "status": {
                            "description": "Game status.",
                            "type": "string",
                            "enum": [
                              "scheduled",
                              "live",
                              "final"
                            ]
                          },
                          "detail": {
                            "description": "Human status line as the upstream renders it (\"Top 5th\", \"FT-Pens\"), or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "period": {
                            "description": "Current period/inning/quarter, or null.",
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "clock": {
                            "description": "Game clock, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "home": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "Upstream team id.",
                                "type": "string"
                              },
                              "name": {
                                "description": "Team name.",
                                "type": "string"
                              },
                              "abbreviation": {
                                "description": "Team abbreviation, when the upstream provides one.",
                                "type": "string"
                              },
                              "score": {
                                "description": "Current score, once the game has started.",
                                "type": "number"
                              },
                              "logo": {
                                "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                                "type": "string"
                              },
                              "record": {
                                "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": false
                          },
                          "away": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "Upstream team id.",
                                "type": "string"
                              },
                              "name": {
                                "description": "Team name.",
                                "type": "string"
                              },
                              "abbreviation": {
                                "description": "Team abbreviation, when the upstream provides one.",
                                "type": "string"
                              },
                              "score": {
                                "description": "Current score, once the game has started.",
                                "type": "number"
                              },
                              "logo": {
                                "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                                "type": "string"
                              },
                              "record": {
                                "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": false
                          },
                          "venue": {
                            "description": "Venue name, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "description": "Which upstream adapter produced this row (\"espn\" | \"mlb\" | \"nhl\").",
                            "type": "string"
                          },
                          "cachedAt": {
                            "description": "ISO timestamp this row was last confirmed current.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "league",
                          "gameId",
                          "date",
                          "startTime",
                          "status",
                          "detail",
                          "period",
                          "clock",
                          "home",
                          "away",
                          "venue",
                          "source",
                          "cachedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "league",
                    "games"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/games/{id}/boxscore": {
      "get": {
        "summary": "Box score, fetched lazily and cached (live: 30s TTL; finals: forever). Compact, source-flavored shape.",
        "description": "Box score, fetched lazily and cached (live: 30s TTL; finals: forever). Compact, source-flavored shape.\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Game detail"
        ],
        "operationId": "get_v1_sports__league_games__id_boxscore",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Game detail",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Upstream game id, from the scoreboard endpoint's `gameId` field.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "description": "Compact, source-flavored box score payload — shape varies per adapter/sport; not normalized (deep stats differ too much across sports to unify in v1)."
                    },
                    "source": {
                      "description": "Which upstream adapter served this payload.",
                      "type": "string"
                    },
                    "cachedAt": {
                      "description": "ISO timestamp this payload was fetched/cached.",
                      "type": "string"
                    },
                    "stale": {
                      "description": "True if this is a stale cached copy served because a fresh fetch failed.",
                      "type": "boolean"
                    },
                    "game": {
                      "type": "object",
                      "properties": {
                        "gameId": {
                          "description": "Upstream game id.",
                          "type": "string"
                        },
                        "status": {
                          "description": "Game status.",
                          "type": "string",
                          "enum": [
                            "scheduled",
                            "live",
                            "final"
                          ]
                        },
                        "home": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "description": "Upstream team id.",
                              "type": "string"
                            },
                            "name": {
                              "description": "Team name.",
                              "type": "string"
                            },
                            "abbreviation": {
                              "description": "Team abbreviation, when the upstream provides one.",
                              "type": "string"
                            },
                            "score": {
                              "description": "Current score, once the game has started.",
                              "type": "number"
                            },
                            "logo": {
                              "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                              "type": "string"
                            },
                            "record": {
                              "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "name"
                          ],
                          "additionalProperties": false
                        },
                        "away": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "description": "Upstream team id.",
                              "type": "string"
                            },
                            "name": {
                              "description": "Team name.",
                              "type": "string"
                            },
                            "abbreviation": {
                              "description": "Team abbreviation, when the upstream provides one.",
                              "type": "string"
                            },
                            "score": {
                              "description": "Current score, once the game has started.",
                              "type": "number"
                            },
                            "logo": {
                              "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                              "type": "string"
                            },
                            "record": {
                              "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "name"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "gameId",
                        "status",
                        "home",
                        "away"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data",
                    "source",
                    "cachedAt",
                    "stale",
                    "game"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/games/{id}/playbyplay": {
      "get": {
        "summary": "Play-by-play / match commentary, one compact row per play. Same lazy caching as box scores.",
        "description": "Play-by-play / match commentary, one compact row per play. Same lazy caching as box scores.\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Game detail"
        ],
        "operationId": "get_v1_sports__league_games__id_playbyplay",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Game detail",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Upstream game id, from the scoreboard endpoint's `gameId` field.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "description": "Compact play-by-play payload, one row per play — shape varies per adapter/sport; not normalized."
                    },
                    "source": {
                      "description": "Which upstream adapter served this payload.",
                      "type": "string"
                    },
                    "cachedAt": {
                      "description": "ISO timestamp this payload was fetched/cached.",
                      "type": "string"
                    },
                    "stale": {
                      "description": "True if this is a stale cached copy served because a fresh fetch failed.",
                      "type": "boolean"
                    },
                    "game": {
                      "type": "object",
                      "properties": {
                        "gameId": {
                          "description": "Upstream game id.",
                          "type": "string"
                        },
                        "status": {
                          "description": "Game status.",
                          "type": "string",
                          "enum": [
                            "scheduled",
                            "live",
                            "final"
                          ]
                        },
                        "home": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "description": "Upstream team id.",
                              "type": "string"
                            },
                            "name": {
                              "description": "Team name.",
                              "type": "string"
                            },
                            "abbreviation": {
                              "description": "Team abbreviation, when the upstream provides one.",
                              "type": "string"
                            },
                            "score": {
                              "description": "Current score, once the game has started.",
                              "type": "number"
                            },
                            "logo": {
                              "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                              "type": "string"
                            },
                            "record": {
                              "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "name"
                          ],
                          "additionalProperties": false
                        },
                        "away": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "description": "Upstream team id.",
                              "type": "string"
                            },
                            "name": {
                              "description": "Team name.",
                              "type": "string"
                            },
                            "abbreviation": {
                              "description": "Team abbreviation, when the upstream provides one.",
                              "type": "string"
                            },
                            "score": {
                              "description": "Current score, once the game has started.",
                              "type": "number"
                            },
                            "logo": {
                              "description": "Logo URL, when the upstream has one — rewritten to serve from our own CDN, never the upstream's URL.",
                              "type": "string"
                            },
                            "record": {
                              "description": "Win-loss record as the upstream renders it (e.g. \"46-39\"), when known.",
                              "type": "string"
                            }
                          },
                          "required": [
                            "id",
                            "name"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "gameId",
                        "status",
                        "home",
                        "away"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data",
                    "source",
                    "cachedAt",
                    "stale",
                    "game"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/standings": {
      "get": {
        "summary": "League table / division standings. Cached 6h — standings move slowly, unlike scores.",
        "description": "League table / division standings. Cached 6h — standings move slowly, unlike scores.\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Reference"
        ],
        "operationId": "get_v1_sports__league_standings",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Reference",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "league": {
                      "description": "League slug.",
                      "type": "string"
                    },
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "description": "Division/conference/table name (\"AL East\", \"Eastern Conference\").",
                            "type": "string"
                          },
                          "rows": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "teamId": {
                                  "description": "Upstream team id.",
                                  "type": "string"
                                },
                                "name": {
                                  "description": "Team name.",
                                  "type": "string"
                                },
                                "abbreviation": {
                                  "description": "Team abbreviation, when known.",
                                  "type": "string"
                                },
                                "wins": {
                                  "description": "Wins.",
                                  "type": "number"
                                },
                                "losses": {
                                  "description": "Losses.",
                                  "type": "number"
                                },
                                "otLosses": {
                                  "description": "Overtime losses (NHL), when the league tracks them.",
                                  "type": "number"
                                },
                                "ties": {
                                  "description": "Ties/draws (soccer, NFL), when the league tracks them.",
                                  "type": "number"
                                },
                                "points": {
                                  "description": "League points (soccer tables), when applicable.",
                                  "type": "number"
                                },
                                "pct": {
                                  "description": "Win percentage as the upstream renders it, when known.",
                                  "type": "string"
                                },
                                "gamesBack": {
                                  "description": "Games back from the division/table leader (e.g. \"3.5\"), when known.",
                                  "type": "string"
                                },
                                "rank": {
                                  "description": "Table position, when the upstream ranks it.",
                                  "type": "number"
                                }
                              },
                              "required": [
                                "teamId",
                                "name",
                                "wins",
                                "losses"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "name",
                          "rows"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "description": "Which upstream adapter served this payload.",
                      "type": "string"
                    },
                    "cachedAt": {
                      "description": "ISO timestamp this payload was fetched/cached.",
                      "type": "string"
                    },
                    "stale": {
                      "description": "True if this is a stale cached copy served because a fresh fetch failed.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "league",
                    "groups",
                    "source",
                    "cachedAt",
                    "stale"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/teams": {
      "get": {
        "summary": "Teams in a league, with logos where the upstream provides them. Cached 24h.",
        "description": "Teams in a league, with logos where the upstream provides them. Cached 24h.\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Reference"
        ],
        "operationId": "get_v1_sports__league_teams",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Reference",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "league": {
                      "description": "League slug.",
                      "type": "string"
                    },
                    "teams": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "Upstream team id.",
                            "type": "string"
                          },
                          "name": {
                            "description": "Team name.",
                            "type": "string"
                          },
                          "abbreviation": {
                            "description": "Team abbreviation, when known.",
                            "type": "string"
                          },
                          "location": {
                            "description": "Team's city/region, when the upstream provides one.",
                            "type": "string"
                          },
                          "logo": {
                            "description": "Logo URL — the raw upstream URL (not rewritten to our CDN, unlike game envelopes' home/away.logo).",
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "description": "Which upstream adapter served this payload.",
                      "type": "string"
                    },
                    "cachedAt": {
                      "description": "ISO timestamp this payload was fetched/cached.",
                      "type": "string"
                    },
                    "stale": {
                      "description": "True if this is a stale cached copy served because a fresh fetch failed.",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "league",
                    "teams",
                    "source",
                    "cachedAt",
                    "stale"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/{league}/teams/{id}": {
      "get": {
        "summary": "One team, by upstream id or abbreviation (mlb/teams/CHC works).",
        "description": "One team, by upstream id or abbreviation (mlb/teams/CHC works).\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: Reference"
        ],
        "operationId": "get_v1_sports__league_teams__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "Reference",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Team id or abbreviation (upstream id, or e.g. \"CHC\" for the Cubs — abbreviation works too).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "league": {
                      "description": "League slug.",
                      "type": "string"
                    },
                    "team": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Upstream team id.",
                          "type": "string"
                        },
                        "name": {
                          "description": "Team name.",
                          "type": "string"
                        },
                        "abbreviation": {
                          "description": "Team abbreviation, when known.",
                          "type": "string"
                        },
                        "location": {
                          "description": "Team's city/region, when the upstream provides one.",
                          "type": "string"
                        },
                        "logo": {
                          "description": "Logo URL — the raw upstream URL (not rewritten to our CDN, unlike game envelopes' home/away.logo).",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    "source": {
                      "description": "Which upstream adapter served this payload.",
                      "type": "string"
                    },
                    "cachedAt": {
                      "description": "ISO timestamp this payload was fetched/cached.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "league",
                    "team",
                    "source",
                    "cachedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/news": {
      "get": {
        "summary": "Sports headlines across all sources: headline + summary + canonical link + attribution. Never full bodies — that's the sources' explicit ceiling, so it's ours too.",
        "description": "Sports headlines across all sources: headline + summary + canonical link + attribution. Never full bodies — that's the sources' explicit ceiling, so it's ours too.\n\n**Example:**\n\n```\n{ \"items\": [{ \"title\": \"…\", \"source\": \"bbc\", \"attribution\": \"BBC Sport\", \"sourceUrl\": \"https://www.bbc.co.uk/sport/…\" }] }\n```\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: News"
        ],
        "operationId": "get_v1_sports_news",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "News",
        "parameters": [
          {
            "name": "sources",
            "in": "query",
            "required": false,
            "description": "Comma-separated source ids to filter to (e.g. \"yahoo,bbc,foxsports,espn\"). Loose passthrough — split/trimmed/lowercased downstream; an unrecognized id just yields no matches for that token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max items to return (1-100). Defaults to 30 — also the old code's fallback for non-numeric input or \"0\". Out-of-range and fractional values were silently clamped/truncated downstream before; all now rejected instead (same clamp/truncate->reject class as GET /v1/feeds/items' `limit`).",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "category": {
                      "description": "Resolved feed-category slug (\"sports\" for the umbrella feed).",
                      "type": "string"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "description": "Headline.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short summary, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp.",
                            "type": "string"
                          },
                          "sourceUrl": {
                            "description": "Canonical link to the full story, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "description": "Stable source id derived from the feed hostname (\"yahoo\" | \"bbc\" | \"foxsports\" | \"espn\" | a derived second-level domain).",
                            "type": "string"
                          },
                          "attribution": {
                            "description": "The feed's own title — mandatory attribution.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "title",
                          "summary",
                          "publishedAt",
                          "sourceUrl",
                          "source",
                          "attribution"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "category",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/sports/news/{league}": {
      "get": {
        "summary": "Headlines filtered to one league's feeds (mlb, nfl, nba, nhl, soccer, college).",
        "description": "Headlines filtered to one league's feeds (mlb, nfl, nba, nhl, soccer, college).\n\n_Free tier only — the upstream license is non-commercial, so this endpoint is served free and never metered._",
        "tags": [
          "Sports",
          "Sports: News"
        ],
        "operationId": "get_v1_sports_news__league",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "sports",
        "x-cheapass-group": "News",
        "parameters": [
          {
            "name": "league",
            "in": "path",
            "required": true,
            "description": "League slug (e.g. \"mlb\", \"nhl\", \"nfl\", \"nba\", \"epl\", \"worldcup\"). See GET /v1/sports/leagues for the full tracked list (40+).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "sources",
            "in": "query",
            "required": false,
            "description": "Comma-separated source ids to filter to (e.g. \"yahoo,bbc,foxsports,espn\"). Loose passthrough — split/trimmed/lowercased downstream; an unrecognized id just yields no matches for that token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max items to return (1-100). Defaults to 30 — also the old code's fallback for non-numeric input or \"0\". Out-of-range and fractional values were silently clamped/truncated downstream before; all now rejected instead (same clamp/truncate->reject class as GET /v1/feeds/items' `limit`).",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "category": {
                      "description": "Resolved feed-category slug (\"sports-<league>\").",
                      "type": "string"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "description": "Headline.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "Short summary, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "publishedAt": {
                            "description": "ISO publish timestamp.",
                            "type": "string"
                          },
                          "sourceUrl": {
                            "description": "Canonical link to the full story, or null.",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "source": {
                            "description": "Stable source id derived from the feed hostname (\"yahoo\" | \"bbc\" | \"foxsports\" | \"espn\" | a derived second-level domain).",
                            "type": "string"
                          },
                          "attribution": {
                            "description": "The feed's own title — mandatory attribution.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "title",
                          "summary",
                          "publishedAt",
                          "sourceUrl",
                          "source",
                          "attribution"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "category",
                    "items"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/ops": {
      "get": {
        "summary": "The machine-readable op catalog: every op, its engine, output kind, and typed params. Public — this is documentation.",
        "description": "The machine-readable op catalog: every op, its engine, output kind, and typed params. Public — this is documentation.",
        "tags": [
          "CV",
          "CV: Catalog"
        ],
        "operationId": "get_v1_cv_ops",
        "security": [],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Catalog",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Every catalog op, machine-readable — the same data PRODUCTS/docs render from.",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Op id — the path segment, e.g. \"blur-score\".",
                        "type": "string"
                      },
                      "engine": {
                        "description": "Which render engine executes this op.",
                        "type": "string",
                        "enum": [
                          "opencv",
                          "sharp",
                          "video"
                        ]
                      },
                      "kind": {
                        "description": "Whether this op returns image bytes or a JSON payload.",
                        "type": "string",
                        "enum": [
                          "image",
                          "json"
                        ]
                      },
                      "group": {
                        "description": "Docs grouping (e.g. \"Detect\", \"Motion\", \"Media\", \"Video\").",
                        "type": "string"
                      },
                      "description": {
                        "description": "What the op does.",
                        "type": "string"
                      },
                      "takesRef": {
                        "description": "True for two-image ops (adds ?ref=).",
                        "type": "boolean"
                      },
                      "params": {
                        "description": "The op's typed param declarations, verbatim from the catalog.",
                        "type": "array",
                        "items": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        }
                      },
                      "path": {
                        "description": "The op's own GET path.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "engine",
                      "kind",
                      "group",
                      "description",
                      "takesRef",
                      "params",
                      "path"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/blur-score": {
      "get": {
        "summary": "Sharpness score (variance of Laplacian) with a plain verdict.",
        "description": "Sharpness score (variance of Laplacian) with a plain verdict.\n\n**Example:**\n\n```\n{ \"score\": 812.44, \"verdict\": \"sharp\" }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_blur-score",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Sharpness score (variance of Laplacian) with a plain verdict. Example: { \"score\": 812.44, \"verdict\": \"sharp\" } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/detect-bounds": {
      "get": {
        "summary": "Content bounding box as fractional coordinates, via Canny edges + contours + Hough lines.",
        "description": "Content bounding box as fractional coordinates, via Canny edges + contours + Hough lines.\n\n**Example:**\n\n```\n{ \"found\": true, \"x\": 0.08, \"y\": 0.11, \"w\": 0.84, \"h\": 0.62, \"confidence\": 0.9 }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_detect-bounds",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Content bounding box as fractional coordinates, via Canny edges + contours + Hough lines. Example: { \"found\": true, \"x\": 0.08, \"y\": 0.11, \"w\": 0.84, \"h\": 0.62, \"confidence\": 0.9 } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/smart-trim": {
      "get": {
        "summary": "Crop to detected content with even padding; declines (JSON) when already tight.",
        "description": "Crop to detected content with even padding; declines (JSON) when already tight.\n\n**Example:**\n\n```\n{ \"trimmed\": false, \"reason\": \"already-tight\" }\n```",
        "tags": [
          "CV",
          "CV: Transform"
        ],
        "operationId": "get_v1_cv_smart-trim",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Transform",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "pad",
            "in": "query",
            "required": false,
            "description": "Even padding fraction",
            "schema": {
              "default": 0.04,
              "type": "number",
              "minimum": 0,
              "maximum": 0.25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crop to detected content with even padding; declines (JSON) when already tight.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/contours": {
      "get": {
        "summary": "External contours: bounding boxes, areas, vertex counts (largest first).",
        "description": "External contours: bounding boxes, areas, vertex counts (largest first).",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_contours",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "min-area",
            "in": "query",
            "required": false,
            "description": "Ignore contours below this fraction of image area",
            "schema": {
              "default": 0.001,
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max contours returned",
            "schema": {
              "default": 25,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "External contours: bounding boxes, areas, vertex counts (largest first). Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/hough-lines": {
      "get": {
        "summary": "Straight line segments (probabilistic Hough), endpoints in fractional coords.",
        "description": "Straight line segments (probabilistic Hough), endpoints in fractional coords.",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_hough-lines",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "min-length",
            "in": "query",
            "required": false,
            "description": "Min segment length as fraction of the long side",
            "schema": {
              "default": 0.15,
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max lines returned",
            "schema": {
              "default": 50,
              "type": "number",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Straight line segments (probabilistic Hough), endpoints in fractional coords. Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/hough-circles": {
      "get": {
        "summary": "Circles (Hough transform): center + radius in fractional coords.",
        "description": "Circles (Hough transform): center + radius in fractional coords.",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_hough-circles",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max circles returned",
            "schema": {
              "default": 25,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Circles (Hough transform): center + radius in fractional coords. Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/corners": {
      "get": {
        "summary": "Strong corners (Shi–Tomasi) as fractional points.",
        "description": "Strong corners (Shi–Tomasi) as fractional points.",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_corners",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max corners returned",
            "schema": {
              "default": 100,
              "type": "number",
              "minimum": 1,
              "maximum": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Strong corners (Shi–Tomasi) as fractional points. Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/histogram": {
      "get": {
        "summary": "Per-channel 16-bin intensity histograms (fractions).",
        "description": "Per-channel 16-bin intensity histograms (fractions).",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_histogram",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Per-channel 16-bin intensity histograms (fractions). Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/dominant-colors": {
      "get": {
        "summary": "K-means dominant colors with population share.",
        "description": "K-means dominant colors with population share.\n\n**Example:**\n\n```\n{ \"colors\": [{ \"hex\": \"#f3f4f4\", \"share\": 0.55 }] }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_dominant-colors",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Number of colors",
            "schema": {
              "default": 5,
              "type": "number",
              "minimum": 1,
              "maximum": 12
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "K-means dominant colors with population share. Example: { \"colors\": [{ \"hex\": \"#f3f4f4\", \"share\": 0.55 }] } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/phash": {
      "get": {
        "summary": "64-bit perceptual hash (DCT) as hex — stable under resize/re-encode.",
        "description": "64-bit perceptual hash (DCT) as hex — stable under resize/re-encode.\n\n**Example:**\n\n```\n{ \"phash\": \"3c1ee3e2c3f83c09\" }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_phash",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "64-bit perceptual hash (DCT) as hex — stable under resize/re-encode. Example: { \"phash\": \"3c1ee3e2c3f83c09\" } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/compare": {
      "get": {
        "summary": "Similarity of src vs ref: pHash Hamming distance + histogram correlation.",
        "description": "Similarity of src vs ref: pHash Hamming distance + histogram correlation.\n\n**Example:**\n\n```\n{ \"phashDistance\": 4, \"histogramCorrelation\": 1.0, \"likelySame\": true }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_compare",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": true,
            "description": "Second image URL for two-image ops (compare/template-match/Motion group) — same constraints as src. For Motion, src is the BEFORE frame and ref is the AFTER.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Similarity of src vs ref: pHash Hamming distance + histogram correlation. Example: { \"phashDistance\": 4, \"histogramCorrelation\": 1.0, \"likelySame\": true } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/template-match": {
      "get": {
        "summary": "Find the ref image inside src (normalized cross-correlation).",
        "description": "Find the ref image inside src (normalized cross-correlation).\n\n**Example:**\n\n```\n{ \"found\": true, \"score\": 1.0, \"x\": 0.31, \"y\": 0.33, \"w\": 0.12, \"h\": 0.13 }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_template-match",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": true,
            "description": "Second image URL for two-image ops (compare/template-match/Motion group) — same constraints as src. For Motion, src is the BEFORE frame and ref is the AFTER.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Find the ref image inside src (normalized cross-correlation). Example: { \"found\": true, \"score\": 1.0, \"x\": 0.31, \"y\": 0.33, \"w\": 0.12, \"h\": 0.13 } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/qr-decode": {
      "get": {
        "summary": "Detect + decode QR codes.",
        "description": "Detect + decode QR codes.\n\n**Example:**\n\n```\n{ \"codes\": [{ \"value\": \"https://example.com\", \"x\": 0.1, \"y\": 0.1, \"w\": 0.3, \"h\": 0.3 }] }\n```",
        "tags": [
          "CV",
          "CV: Detect"
        ],
        "operationId": "get_v1_cv_qr-decode",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Detect",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Detect + decode QR codes. Example: { \"codes\": [{ \"value\": \"https://example.com\", \"x\": 0.1, \"y\": 0.1, \"w\": 0.3, \"h\": 0.3 }] } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/optical-flow": {
      "get": {
        "summary": "Dense optical flow (Farnebäck) from src to ref: overall magnitude, dominant direction, and a coarse vector grid.",
        "description": "Dense optical flow (Farnebäck) from src to ref: overall magnitude, dominant direction, and a coarse vector grid.\n\n**Example:**\n\n```\n{ \"meanMagnitude\": 0.011, \"maxMagnitude\": 0.187, \"direction\": 114.1, \"grid\": 8, \"vectors\": [] }\n```",
        "tags": [
          "CV",
          "CV: Motion"
        ],
        "operationId": "get_v1_cv_optical-flow",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Motion",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": true,
            "description": "Second image URL for two-image ops (compare/template-match/Motion group) — same constraints as src. For Motion, src is the BEFORE frame and ref is the AFTER.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "grid",
            "in": "query",
            "required": false,
            "description": "Vector grid size per axis",
            "schema": {
              "default": 8,
              "type": "number",
              "minimum": 4,
              "maximum": 16
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Dense optical flow (Farnebäck) from src to ref: overall magnitude, dominant direction, and a coarse vector grid. Example: { \"meanMagnitude\": 0.011, \"maxMagnitude\": 0.187, \"direction\": 114.1, \"grid\": 8, \"vectors\": [] } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/motion-score": {
      "get": {
        "summary": "How much changed between two frames: changed-pixel fraction + bounding boxes of the changed regions.",
        "description": "How much changed between two frames: changed-pixel fraction + bounding boxes of the changed regions.\n\n**Example:**\n\n```\n{ \"score\": 0.0985, \"moving\": true, \"regions\": [{ \"x\": 0.24, \"y\": 0.32, \"w\": 0.27, \"h\": 0.36 }] }\n```",
        "tags": [
          "CV",
          "CV: Motion"
        ],
        "operationId": "get_v1_cv_motion-score",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Motion",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": true,
            "description": "Second image URL for two-image ops (compare/template-match/Motion group) — same constraints as src. For Motion, src is the BEFORE frame and ref is the AFTER.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "sensitivity",
            "in": "query",
            "required": false,
            "description": "Per-pixel change threshold (lower = more sensitive)",
            "schema": {
              "default": 25,
              "type": "number",
              "minimum": 5,
              "maximum": 120
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max regions returned",
            "schema": {
              "default": 10,
              "type": "number",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "How much changed between two frames: changed-pixel fraction + bounding boxes of the changed regions. Example: { \"score\": 0.0985, \"moving\": true, \"regions\": [{ \"x\": 0.24, \"y\": 0.32, \"w\": 0.27, \"h\": 0.36 }] } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/frame-diff": {
      "get": {
        "summary": "The changed-pixels mask between two frames (white on black).",
        "description": "The changed-pixels mask between two frames (white on black).",
        "tags": [
          "CV",
          "CV: Motion"
        ],
        "operationId": "get_v1_cv_frame-diff",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Motion",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ref",
            "in": "query",
            "required": true,
            "description": "Second image URL for two-image ops (compare/template-match/Motion group) — same constraints as src. For Motion, src is the BEFORE frame and ref is the AFTER.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "sensitivity",
            "in": "query",
            "required": false,
            "description": "Per-pixel change threshold (lower = more sensitive)",
            "schema": {
              "default": 25,
              "type": "number",
              "minimum": 5,
              "maximum": 120
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The changed-pixels mask between two frames (white on black).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/canny": {
      "get": {
        "summary": "Canny edge map (white edges on black).",
        "description": "Canny edge map (white edges on black).",
        "tags": [
          "CV",
          "CV: Edges"
        ],
        "operationId": "get_v1_cv_canny",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Edges",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "low",
            "in": "query",
            "required": false,
            "description": "Lower hysteresis threshold",
            "schema": {
              "default": 50,
              "type": "number",
              "minimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "high",
            "in": "query",
            "required": false,
            "description": "Upper hysteresis threshold",
            "schema": {
              "default": 150,
              "type": "number",
              "minimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Canny edge map (white edges on black).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/sobel": {
      "get": {
        "summary": "Sobel gradient magnitude.",
        "description": "Sobel gradient magnitude.",
        "tags": [
          "CV",
          "CV: Edges"
        ],
        "operationId": "get_v1_cv_sobel",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Edges",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sobel gradient magnitude.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/threshold": {
      "get": {
        "summary": "Binary threshold (Otsu when no value given).",
        "description": "Binary threshold (Otsu when no value given).",
        "tags": [
          "CV",
          "CV: Tone"
        ],
        "operationId": "get_v1_cv_threshold",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Tone",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "value",
            "in": "query",
            "required": false,
            "description": "Threshold 0–255; omit for Otsu",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 255
            }
          },
          {
            "name": "invert",
            "in": "query",
            "required": false,
            "description": "Invert the result (\"true\"/\"1\" enables; anything else is treated as false by the engine)",
            "schema": {
              "default": "false",
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Binary threshold (Otsu when no value given).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/adaptive-threshold": {
      "get": {
        "summary": "Adaptive Gaussian threshold — survives uneven lighting.",
        "description": "Adaptive Gaussian threshold — survives uneven lighting.",
        "tags": [
          "CV",
          "CV: Tone"
        ],
        "operationId": "get_v1_cv_adaptive-threshold",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Tone",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "block",
            "in": "query",
            "required": false,
            "description": "Neighborhood size (odd)",
            "schema": {
              "default": 21,
              "type": "number",
              "minimum": 3,
              "maximum": 99
            }
          },
          {
            "name": "c",
            "in": "query",
            "required": false,
            "description": "Constant subtracted from mean",
            "schema": {
              "default": 5,
              "type": "number",
              "minimum": -50,
              "maximum": 50
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Adaptive Gaussian threshold — survives uneven lighting.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/clahe": {
      "get": {
        "summary": "Contrast-limited adaptive histogram equalization.",
        "description": "Contrast-limited adaptive histogram equalization.",
        "tags": [
          "CV",
          "CV: Tone"
        ],
        "operationId": "get_v1_cv_clahe",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Tone",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "clip",
            "in": "query",
            "required": false,
            "description": "Clip limit",
            "schema": {
              "default": 2,
              "type": "number",
              "minimum": 0.5,
              "maximum": 10
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contrast-limited adaptive histogram equalization.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/equalize": {
      "get": {
        "summary": "Global histogram equalization (luminance).",
        "description": "Global histogram equalization (luminance).",
        "tags": [
          "CV",
          "CV: Tone"
        ],
        "operationId": "get_v1_cv_equalize",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Tone",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Global histogram equalization (luminance).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/erode": {
      "get": {
        "summary": "Morphological erosion.",
        "description": "Morphological erosion.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_erode",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Kernel size",
            "schema": {
              "default": 3,
              "type": "number",
              "minimum": 1,
              "maximum": 31
            }
          },
          {
            "name": "iterations",
            "in": "query",
            "required": false,
            "description": "Iterations",
            "schema": {
              "default": 1,
              "type": "number",
              "minimum": 1,
              "maximum": 10
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Morphological erosion.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/dilate": {
      "get": {
        "summary": "Morphological dilation.",
        "description": "Morphological dilation.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_dilate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Kernel size",
            "schema": {
              "default": 3,
              "type": "number",
              "minimum": 1,
              "maximum": 31
            }
          },
          {
            "name": "iterations",
            "in": "query",
            "required": false,
            "description": "Iterations",
            "schema": {
              "default": 1,
              "type": "number",
              "minimum": 1,
              "maximum": 10
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Morphological dilation.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/morph-open": {
      "get": {
        "summary": "Opening (erode then dilate) — removes specks.",
        "description": "Opening (erode then dilate) — removes specks.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_morph-open",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Kernel size",
            "schema": {
              "default": 3,
              "type": "number",
              "minimum": 1,
              "maximum": 31
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Opening (erode then dilate) — removes specks.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/morph-close": {
      "get": {
        "summary": "Closing (dilate then erode) — fills pinholes.",
        "description": "Closing (dilate then erode) — fills pinholes.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_morph-close",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Kernel size",
            "schema": {
              "default": 3,
              "type": "number",
              "minimum": 1,
              "maximum": 31
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Closing (dilate then erode) — fills pinholes.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/denoise": {
      "get": {
        "summary": "Non-local-means color denoising.",
        "description": "Non-local-means color denoising.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_denoise",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "strength",
            "in": "query",
            "required": false,
            "description": "Filter strength",
            "schema": {
              "default": 10,
              "type": "number",
              "minimum": 1,
              "maximum": 30
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Non-local-means color denoising.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/blur-bilateral": {
      "get": {
        "summary": "Edge-preserving bilateral smoothing.",
        "description": "Edge-preserving bilateral smoothing.",
        "tags": [
          "CV",
          "CV: Morphology"
        ],
        "operationId": "get_v1_cv_blur-bilateral",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Morphology",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "strength",
            "in": "query",
            "required": false,
            "description": "Sigma",
            "schema": {
              "default": 75,
              "type": "number",
              "minimum": 5,
              "maximum": 200
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Edge-preserving bilateral smoothing.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/deskew": {
      "get": {
        "summary": "Detect the dominant text/content angle and rotate it level.",
        "description": "Detect the dominant text/content angle and rotate it level.",
        "tags": [
          "CV",
          "CV: Geometry"
        ],
        "operationId": "get_v1_cv_deskew",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Geometry",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detect the dominant text/content angle and rotate it level.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/perspective-correct": {
      "get": {
        "summary": "Find the largest quadrilateral (document/screen) and warp it to a straight-on rectangle.",
        "description": "Find the largest quadrilateral (document/screen) and warp it to a straight-on rectangle.",
        "tags": [
          "CV",
          "CV: Geometry"
        ],
        "operationId": "get_v1_cv_perspective-correct",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Geometry",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Find the largest quadrilateral (document/screen) and warp it to a straight-on rectangle.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/pixelate": {
      "get": {
        "summary": "Mosaic pixelation (privacy/effect).",
        "description": "Mosaic pixelation (privacy/effect).",
        "tags": [
          "CV",
          "CV: Geometry"
        ],
        "operationId": "get_v1_cv_pixelate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Geometry",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "Blocks across the long side",
            "schema": {
              "default": 24,
              "type": "number",
              "minimum": 2,
              "maximum": 200
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mosaic pixelation (privacy/effect).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/redact": {
      "get": {
        "summary": "Pixelate one rectangle (fractional coords) — receipts, faces, keys.",
        "description": "Pixelate one rectangle (fractional coords) — receipts, faces, keys.",
        "tags": [
          "CV",
          "CV: Geometry"
        ],
        "operationId": "get_v1_cv_redact",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Geometry",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "x",
            "in": "query",
            "required": true,
            "description": "Left edge (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "y",
            "in": "query",
            "required": true,
            "description": "Top edge (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "w",
            "in": "query",
            "required": true,
            "description": "Width (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "h",
            "in": "query",
            "required": true,
            "description": "Height (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pixelate one rectangle (fractional coords) — receipts, faces, keys.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/resize": {
      "get": {
        "summary": "Resize with fit modes; never upscales unless asked.",
        "description": "Resize with fit modes; never upscales unless asked.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_resize",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "w",
            "in": "query",
            "required": false,
            "description": "Target width px",
            "schema": {
              "type": "number",
              "minimum": 1,
              "maximum": 8192
            }
          },
          {
            "name": "h",
            "in": "query",
            "required": false,
            "description": "Target height px",
            "schema": {
              "type": "number",
              "minimum": 1,
              "maximum": 8192
            }
          },
          {
            "name": "fit",
            "in": "query",
            "required": false,
            "description": "Fit mode",
            "schema": {
              "default": "inside",
              "type": "string",
              "enum": [
                "cover",
                "contain",
                "inside",
                "outside",
                "fill"
              ]
            }
          },
          {
            "name": "upscale",
            "in": "query",
            "required": false,
            "description": "Allow enlarging (\"true\"/\"1\" enables; anything else is treated as false by the engine)",
            "schema": {
              "default": "false",
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resize with fit modes; never upscales unless asked.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/convert": {
      "get": {
        "summary": "Re-encode to png/jpeg/webp/avif at a quality (metadata stripped).",
        "description": "Re-encode to png/jpeg/webp/avif at a quality (metadata stripped).",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_convert",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "webp",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Re-encode to png/jpeg/webp/avif at a quality (metadata stripped).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/crop": {
      "get": {
        "summary": "Crop to a rectangle in fractional coordinates.",
        "description": "Crop to a rectangle in fractional coordinates.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_crop",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "x",
            "in": "query",
            "required": true,
            "description": "Left edge (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "y",
            "in": "query",
            "required": true,
            "description": "Top edge (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "w",
            "in": "query",
            "required": true,
            "description": "Width (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "h",
            "in": "query",
            "required": true,
            "description": "Height (fraction)",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crop to a rectangle in fractional coordinates.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/pad": {
      "get": {
        "summary": "Extend the canvas to an exact aspect ratio on a background color.",
        "description": "Extend the canvas to an exact aspect ratio on a background color.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_pad",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "ratio",
            "in": "query",
            "required": true,
            "description": "Target ratio, e.g. \"16:9\"",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "description": "CSS color",
            "schema": {
              "default": "#ffffff",
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Extend the canvas to an exact aspect ratio on a background color.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/trim": {
      "get": {
        "summary": "Fast background trim (libvips) — uniform borders only; use smart-trim for textured paper.",
        "description": "Fast background trim (libvips) — uniform borders only; use smart-trim for textured paper.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_trim",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "tolerance",
            "in": "query",
            "required": false,
            "description": "Background tolerance",
            "schema": {
              "default": 10,
              "type": "number",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fast background trim (libvips) — uniform borders only; use smart-trim for textured paper.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/rotate": {
      "get": {
        "summary": "Rotate by degrees (canvas grows; background fills corners).",
        "description": "Rotate by degrees (canvas grows; background fills corners).",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_rotate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "degrees",
            "in": "query",
            "required": true,
            "description": "Clockwise degrees",
            "schema": {
              "type": "number",
              "minimum": -360,
              "maximum": 360
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "description": "CSS color",
            "schema": {
              "default": "#ffffff",
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotate by degrees (canvas grows; background fills corners).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/flip": {
      "get": {
        "summary": "Mirror vertically (flip) and/or horizontally (flop).",
        "description": "Mirror vertically (flip) and/or horizontally (flop).",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_flip",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "vertical",
            "in": "query",
            "required": false,
            "description": "Flip top-to-bottom (\"true\"/\"1\" enables; anything else is treated as false by the engine)",
            "schema": {
              "default": "false",
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "horizontal",
            "in": "query",
            "required": false,
            "description": "Mirror left-to-right (\"true\"/\"1\" enables; anything else is treated as false by the engine)",
            "schema": {
              "default": "true",
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mirror vertically (flip) and/or horizontally (flop).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/blur": {
      "get": {
        "summary": "Gaussian blur.",
        "description": "Gaussian blur.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_blur",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "sigma",
            "in": "query",
            "required": false,
            "description": "Blur sigma",
            "schema": {
              "default": 8,
              "type": "number",
              "minimum": 0.3,
              "maximum": 100
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gaussian blur.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/sharpen": {
      "get": {
        "summary": "Unsharp mask.",
        "description": "Unsharp mask.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_sharpen",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "sigma",
            "in": "query",
            "required": false,
            "description": "Sharpen sigma",
            "schema": {
              "default": 1,
              "type": "number",
              "minimum": 0.3,
              "maximum": 10
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Unsharp mask.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/grayscale": {
      "get": {
        "summary": "Convert to grayscale.",
        "description": "Convert to grayscale.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_grayscale",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Convert to grayscale.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/negate": {
      "get": {
        "summary": "Invert colors.",
        "description": "Invert colors.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_negate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invert colors.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/tint": {
      "get": {
        "summary": "Tint via a color while preserving luminance.",
        "description": "Tint via a color while preserving luminance.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_tint",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "color",
            "in": "query",
            "required": true,
            "description": "CSS color",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tint via a color while preserving luminance.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/modulate": {
      "get": {
        "summary": "Adjust brightness / saturation / hue-rotation.",
        "description": "Adjust brightness / saturation / hue-rotation.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_modulate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "brightness",
            "in": "query",
            "required": false,
            "description": "Multiplier",
            "schema": {
              "default": 1,
              "type": "number",
              "minimum": 0,
              "maximum": 5
            }
          },
          {
            "name": "saturation",
            "in": "query",
            "required": false,
            "description": "Multiplier",
            "schema": {
              "default": 1,
              "type": "number",
              "minimum": 0,
              "maximum": 5
            }
          },
          {
            "name": "hue",
            "in": "query",
            "required": false,
            "description": "Hue rotation degrees",
            "schema": {
              "default": 0,
              "type": "number",
              "minimum": -360,
              "maximum": 360
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Adjust brightness / saturation / hue-rotation.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/gamma": {
      "get": {
        "summary": "Gamma correction.",
        "description": "Gamma correction.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_gamma",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "value",
            "in": "query",
            "required": false,
            "description": "Gamma 1.0–3.0",
            "schema": {
              "default": 2.2,
              "type": "number",
              "minimum": 1,
              "maximum": 3
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gamma correction.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/normalize": {
      "get": {
        "summary": "Stretch contrast to the full range.",
        "description": "Stretch contrast to the full range.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_normalize",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp",
                "avif"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stretch contrast to the full range.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/composite": {
      "get": {
        "summary": "Overlay a second image onto the base at a gravity/offset, with optional resize + blend.",
        "description": "Overlay a second image onto the base at a gravity/offset, with optional resize + blend.",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_composite",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "overlay",
            "in": "query",
            "required": false,
            "description": "Overlay image URL (http(s)); required unless overlayData",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "overlayData",
            "in": "query",
            "required": false,
            "description": "Base64 overlay bytes (pipeline use); mutually exclusive with overlay",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "gravity",
            "in": "query",
            "required": false,
            "description": "Overlay anchor",
            "schema": {
              "type": "string",
              "enum": [
                "north",
                "northeast",
                "east",
                "southeast",
                "south",
                "southwest",
                "west",
                "northwest",
                "center"
              ]
            }
          },
          {
            "name": "top",
            "in": "query",
            "required": false,
            "description": "Overlay Y offset px (with left); overrides gravity",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "left",
            "in": "query",
            "required": false,
            "description": "Overlay X offset px (with top)",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "width",
            "in": "query",
            "required": false,
            "description": "Resize overlay to this width px, aspect-preserved",
            "schema": {
              "type": "number",
              "minimum": 1,
              "maximum": 4000
            }
          },
          {
            "name": "blend",
            "in": "query",
            "required": false,
            "description": "Blend mode",
            "schema": {
              "default": "over",
              "type": "string",
              "enum": [
                "over",
                "multiply",
                "screen",
                "overlay",
                "dest-over"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output encoding",
            "schema": {
              "default": "png",
              "type": "string",
              "enum": [
                "png",
                "jpeg",
                "webp"
              ]
            }
          },
          {
            "name": "quality",
            "in": "query",
            "required": false,
            "description": "Encode quality (jpeg/webp)",
            "schema": {
              "default": 80,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Overlay a second image onto the base at a gravity/offset, with optional resize + blend.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/metadata": {
      "get": {
        "summary": "Dimensions, format, channels, density, EXIF orientation, alpha.",
        "description": "Dimensions, format, channels, density, EXIF orientation, alpha.\n\n**Example:**\n\n```\n{ \"width\": 800, \"height\": 450, \"format\": \"jpeg\", \"channels\": 3, \"hasAlpha\": false }\n```",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_metadata",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Dimensions, format, channels, density, EXIF orientation, alpha. Example: { \"width\": 800, \"height\": 450, \"format\": \"jpeg\", \"channels\": 3, \"hasAlpha\": false } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/stats": {
      "get": {
        "summary": "Per-channel min/max/mean/stdev + entropy + dominant color.",
        "description": "Per-channel min/max/mean/stdev + entropy + dominant color.\n\n**Example:**\n\n```\n{ \"entropy\": 7.21, \"sharpness\": 1.4, \"dominant\": \"#8a6f4b\", \"isOpaque\": true }\n```",
        "tags": [
          "CV",
          "CV: Media"
        ],
        "operationId": "get_v1_cv_stats",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Media",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Per-channel min/max/mean/stdev + entropy + dominant color. Example: { \"entropy\": 7.21, \"sharpness\": 1.4, \"dominant\": \"#8a6f4b\", \"isOpaque\": true } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/video-info": {
      "get": {
        "summary": "Dimensions, fps, frame count, duration of a video URL. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "description": "Dimensions, fps, frame count, duration of a video URL. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)\n\n**Example:**\n\n```\n{ \"width\": 1920, \"height\": 1080, \"fps\": 30, \"frames\": 5400, \"duration\": 180 }\n```",
        "tags": [
          "CV",
          "CV: Video"
        ],
        "operationId": "get_v1_cv_video-info",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Video",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Dimensions, fps, frame count, duration of a video URL. Example: { \"width\": 1920, \"height\": 1080, \"fps\": 30, \"frames\": 5400, \"duration\": 180 } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/frame": {
      "get": {
        "summary": "Extract one frame at a timestamp as PNG. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "description": "Extract one frame at a timestamp as PNG. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "tags": [
          "CV",
          "CV: Video"
        ],
        "operationId": "get_v1_cv_frame",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Video",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": false,
            "description": "Timestamp in seconds",
            "schema": {
              "default": 0,
              "type": "number",
              "minimum": 0,
              "maximum": 86400
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Extract one frame at a timestamp as PNG.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/keyframes": {
      "get": {
        "summary": "Contact sheet of evenly-spaced frames (one PNG grid). (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "description": "Contact sheet of evenly-spaced frames (one PNG grid). (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "tags": [
          "CV",
          "CV: Video"
        ],
        "operationId": "get_v1_cv_keyframes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Video",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Frames sampled",
            "schema": {
              "default": 9,
              "type": "number",
              "minimum": 2,
              "maximum": 25
            }
          },
          {
            "name": "columns",
            "in": "query",
            "required": false,
            "description": "Grid columns",
            "schema": {
              "default": 3,
              "type": "number",
              "minimum": 1,
              "maximum": 6
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contact sheet of evenly-spaced frames (one PNG grid).",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/scene-changes": {
      "get": {
        "summary": "Timestamps where the picture cuts (sampled histogram correlation). (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "description": "Timestamps where the picture cuts (sampled histogram correlation). (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)\n\n**Example:**\n\n```\n{ \"sceneChanges\": [{ \"t\": 4.0, \"confidence\": 0.87 }], \"sampled\": true }\n```",
        "tags": [
          "CV",
          "CV: Video"
        ],
        "operationId": "get_v1_cv_scene-changes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Video",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "sensitivity",
            "in": "query",
            "required": false,
            "description": "Cut threshold (higher = fewer cuts)",
            "schema": {
              "default": 0.4,
              "type": "number",
              "minimum": 0.1,
              "maximum": 0.9
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max cuts returned",
            "schema": {
              "default": 100,
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Timestamps where the picture cuts (sampled histogram correlation). Example: { \"sceneChanges\": [{ \"t\": 4.0, \"confidence\": 0.87 }], \"sampled\": true } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/motion-timeline": {
      "get": {
        "summary": "Motion score over time (sampled frame differencing) + the peak moment. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)",
        "description": "Motion score over time (sampled frame differencing) + the peak moment. (video tier — answers 503 until its dedicated container is deployed; stated here so nobody finds out from a bill)\n\n**Example:**\n\n```\n{ \"timeline\": [{ \"t\": 1.5, \"score\": 0.031 }], \"peak\": { \"t\": 4.0, \"score\": 1.0 } }\n```",
        "tags": [
          "CV",
          "CV: Video"
        ],
        "operationId": "get_v1_cv_motion-timeline",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Video",
        "parameters": [
          {
            "name": "src",
            "in": "query",
            "required": true,
            "description": "Source image URL — public http(s) only, 20 MB cap, private addresses refused.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "samples",
            "in": "query",
            "required": false,
            "description": "Points on the timeline",
            "schema": {
              "default": 60,
              "type": "number",
              "minimum": 10,
              "maximum": 300
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "Motion score over time (sampled frame differencing) + the peak moment. Example: { \"timeline\": [{ \"t\": 1.5, \"score\": 0.031 }], \"peak\": { \"t\": 4.0, \"score\": 1.0 } } Field-by-field response shape isn't modeled here — honest breadth over invented precision across 55 ops on 2 engines; refining per-op response schemas is future work.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/pipeline": {
      "post": {
        "summary": "Chain named catalog ops across engines in one request — resize on sharp, then detect on opencv, then composite back on sharp — without your server round-tripping the bytes in between. One op per step, image-kind ops only, up to 8 steps.",
        "description": "Chain named catalog ops across engines in one request — resize on sharp, then detect on opencv, then composite back on sharp — without your server round-tripping the bytes in between. One op per step, image-kind ops only, up to 8 steps.",
        "tags": [
          "CV",
          "CV: Pipeline"
        ],
        "operationId": "post_v1_cv_pipeline",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Pipeline",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "src": {
                    "description": "Starting image URL.",
                    "type": "string",
                    "format": "uri"
                  },
                  "steps": {
                    "description": "Ordered image-kind catalog ops to chain: [{ \"op\": \"<catalog id>\", ...params }]. Up to 8 steps.",
                    "minItems": 1,
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    }
                  },
                  "format": {
                    "description": "Final step's output encoding.",
                    "type": "string",
                    "enum": [
                      "png",
                      "jpeg",
                      "webp",
                      "avif"
                    ]
                  },
                  "quality": {
                    "description": "Final step's encode quality (jpeg/webp/avif).",
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100
                  }
                },
                "required": [
                  "src",
                  "steps"
                ],
                "additionalProperties": false
              },
              "example": {
                "src": "https://cheapass.dev/opengraph-image",
                "steps": [
                  {
                    "op": "grayscale"
                  },
                  {
                    "op": "resize",
                    "w": 200
                  }
                ],
                "format": "png"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Image bytes from the final step (format/quality apply to the last step only); X-Cv-Pipeline header lists the op names run, comma-separated.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/avif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cv/raw": {
      "post": {
        "summary": "Invoke ANY OpenCV function by name — the whole cv2 API (1000+ functions across cv2 and its submodules) behind one endpoint. Body is a step list; values use the {$image}/{$imageData}/{$array}/{$const} codec; steps chain so class-based APIs (SIFT, ORB, BFMatcher) run in one call. GUI/disk/model-file functions are blocked; each call is subprocess-isolated.",
        "description": "Invoke ANY OpenCV function by name — the whole cv2 API (1000+ functions across cv2 and its submodules) behind one endpoint. Body is a step list; values use the {$image}/{$imageData}/{$array}/{$const} codec; steps chain so class-based APIs (SIFT, ORB, BFMatcher) run in one call. GUI/disk/model-file functions are blocked; each call is subprocess-isolated.\n\n**Example:**\n\n```\n{ \"result\": { \"$array\": [[0.1], [0.24], [0.4], [0.24], [0.1]], \"shape\": [5, 1], \"dtype\": \"float64\" } }\n```",
        "tags": [
          "CV",
          "CV: Raw bridge"
        ],
        "operationId": "post_v1_cv_raw",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "cv",
        "x-cheapass-group": "Raw bridge",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "steps": {
                    "description": "Ordered cv2 calls; each can reference an earlier step's saved result.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "fn": {
                          "description": "Any cv2 function name (dotted for submodules, e.g. \"ximgproc.thinning\").",
                          "type": "string"
                        },
                        "args": {
                          "description": "Positional args — values use the {\"$image\"}/{\"$imageData\"}/{\"$array\"}/{\"$const\"}/{\"$ref\"} codec.",
                          "type": "array",
                          "items": {}
                        },
                        "kwargs": {
                          "description": "Keyword args, same codec.",
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "save": {
                          "description": "Name this step's result for a later {\"$ref\": name}.",
                          "type": "string"
                        }
                      },
                      "required": [
                        "fn"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "steps"
                ],
                "additionalProperties": false
              },
              "example": {
                "steps": [
                  {
                    "fn": "cvtColor",
                    "args": [
                      {
                        "$image": "https://cheapass.dev/opengraph-image"
                      },
                      {
                        "$const": "COLOR_BGR2GRAY"
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "The last step's return value through the codec, inside { \"data\": { \"result\": … } }. Shape depends entirely on which cv2 function was called — not modeled field-by-field.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/games/rooms": {
      "get": {
        "summary": "This account's rooms, newest first.",
        "description": "This account's rooms, newest first.",
        "tags": [
          "Games",
          "Games: Rooms"
        ],
        "operationId": "get_v1_games_rooms",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "games",
        "x-cheapass-group": "Rooms",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter to rooms in this status (omit for all statuses).",
            "schema": {
              "type": "string",
              "enum": [
                "lobby",
                "active",
                "finished",
                "abandoned"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Room id.",
                        "type": "string"
                      },
                      "code": {
                        "description": "Human-shareable join code.",
                        "type": "string"
                      },
                      "gameType": {
                        "description": "Consumer-defined game type id (matches a registered GameDefinition).",
                        "type": "string"
                      },
                      "status": {
                        "description": "Room lifecycle status.",
                        "type": "string",
                        "enum": [
                          "lobby",
                          "active",
                          "finished",
                          "abandoned"
                        ]
                      },
                      "maxPlayers": {
                        "description": "Max seats in this room.",
                        "type": "number"
                      },
                      "createdAt": {
                        "description": "Creation time, ms since epoch.",
                        "type": "number"
                      },
                      "finishedAt": {
                        "description": "Finish time, ms since epoch, or null while not finished.",
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "id",
                      "code",
                      "gameType",
                      "status",
                      "maxPlayers",
                      "createdAt",
                      "finishedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/games/leaderboard/{gameType}": {
      "get": {
        "summary": "All-time leaderboard for one of your game types. Tenant-scoped (game types are yours, not a global registry): authenticate with an API key, or read publicly with ?siteKey=gspk_….",
        "description": "All-time leaderboard for one of your game types. Tenant-scoped (game types are yours, not a global registry): authenticate with an API key, or read publicly with ?siteKey=gspk_….\n\n**Example:**\n\n```\n[{ \"name\": \"Ada\", \"bestScore\": 7, \"gamesPlayed\": 12, \"wins\": 9 }]\n```",
        "tags": [
          "Games",
          "Games: Scores"
        ],
        "operationId": "get_v1_games_leaderboard__gameType",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "games",
        "x-cheapass-group": "Scores",
        "parameters": [
          {
            "name": "gameType",
            "in": "path",
            "required": true,
            "description": "Consumer-defined game type id.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max rows to return (server clamps to 1–50; default 10).",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "siteKey",
            "in": "query",
            "required": false,
            "description": "Publishable site key (\"gspk_…\") — alternative to API-key auth for public reads.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "description": "Player display name.",
                        "type": "string"
                      },
                      "bestScore": {
                        "description": "This player's best recorded score for the game type.",
                        "type": "number"
                      },
                      "gamesPlayed": {
                        "description": "Total games this player has completed.",
                        "type": "number"
                      },
                      "wins": {
                        "description": "Total wins for this player.",
                        "type": "number"
                      }
                    },
                    "required": [
                      "name",
                      "bestScore",
                      "gamesPlayed",
                      "wins"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/games/site-keys": {
      "post": {
        "summary": "Mint a publishable site key (gspk_…) for browser game clients.",
        "description": "Mint a publishable site key (gspk_…) for browser game clients.",
        "tags": [
          "Games",
          "Games: Site keys"
        ],
        "operationId": "post_v1_games_site-keys",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "games",
        "x-cheapass-group": "Site keys",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Display name for this site key.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "my-site"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "name": {
                      "description": "Display name.",
                      "type": "string"
                    },
                    "key": {
                      "description": "The newly minted publishable site key (\"gspk_…\" prefixed).",
                      "type": "string"
                    }
                  },
                  "required": [
                    "name",
                    "key"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List this account's site keys (publishable — returned whole).",
        "description": "List this account's site keys (publishable — returned whole).",
        "tags": [
          "Games",
          "Games: Site keys"
        ],
        "operationId": "get_v1_games_site-keys",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "games",
        "x-cheapass-group": "Site keys",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Site key id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name.",
                        "type": "string"
                      },
                      "key": {
                        "description": "The publishable site key, \"gspk_…\" prefixed — safe to embed in browser bundles.",
                        "type": "string"
                      },
                      "createdAt": {
                        "description": "Creation time, ms since epoch.",
                        "type": "number"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "key",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows": {
      "post": {
        "summary": "Create a show (slug, title, description, author, ownerEmail; optional artworkUrl, siteUrl, category, language, explicit).",
        "description": "Create a show (slug, title, description, author, ownerEmail; optional artworkUrl, siteUrl, category, language, explicit).",
        "tags": [
          "Podcasts",
          "Podcasts: Shows"
        ],
        "operationId": "post_v1_podcasts_shows",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Shows",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "slug": {
                    "description": "Globally unique, immutable — becomes the feed URL path.",
                    "type": "string",
                    "pattern": "^[a-z0-9](?:[a-z0-9-]{1,62}[a-z0-9])?$"
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "author": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "ownerEmail": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "artworkUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "siteUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "category": {
                    "description": "Apple Podcasts category.",
                    "type": "string",
                    "maxLength": 80
                  },
                  "language": {
                    "default": "en",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 16
                  },
                  "explicit": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "required": [
                  "slug",
                  "title",
                  "description",
                  "author",
                  "ownerEmail",
                  "language",
                  "explicit"
                ],
                "additionalProperties": false
              },
              "example": {
                "slug": "my-show",
                "title": "My Show",
                "description": "A show about things.",
                "author": "Me",
                "ownerEmail": "me@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Show id.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "Immutable slug — the feed URL path.",
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "author": {
                      "type": "string"
                    },
                    "ownerEmail": {
                      "type": "string"
                    },
                    "artworkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siteUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "type": "string"
                    },
                    "explicit": {
                      "type": "boolean"
                    },
                    "distribution": {
                      "description": "Per-directory distribution state, or null before any check/mark has run.",
                      "anyOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "directory": {
                                "description": "Distribution directory.",
                                "type": "string",
                                "enum": [
                                  "apple",
                                  "spotify",
                                  "youtube"
                                ]
                              },
                              "status": {
                                "description": "Distribution state for this directory.",
                                "type": "string",
                                "enum": [
                                  "not_submitted",
                                  "pending",
                                  "live"
                                ]
                              },
                              "externalId": {
                                "description": "The directory's own id for this show, once detected/recorded.",
                                "type": "string"
                              },
                              "externalUrl": {
                                "description": "A link to the live listing, once detected/recorded.",
                                "type": "string"
                              },
                              "checkedAt": {
                                "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "directory",
                              "status"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "feedUrl": {
                      "description": "The show's public RSS feed URL — added by every show-returning endpoint.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "title",
                    "description",
                    "author",
                    "ownerEmail",
                    "artworkUrl",
                    "siteUrl",
                    "category",
                    "language",
                    "explicit",
                    "distribution",
                    "createdAt",
                    "updatedAt",
                    "feedUrl"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List this account's shows.",
        "description": "List this account's shows.",
        "tags": [
          "Podcasts",
          "Podcasts: Shows"
        ],
        "operationId": "get_v1_podcasts_shows",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Shows",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Show id.",
                        "type": "string"
                      },
                      "slug": {
                        "description": "Immutable slug — the feed URL path.",
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "author": {
                        "type": "string"
                      },
                      "ownerEmail": {
                        "type": "string"
                      },
                      "artworkUrl": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "siteUrl": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "category": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "language": {
                        "type": "string"
                      },
                      "explicit": {
                        "type": "boolean"
                      },
                      "distribution": {
                        "description": "Per-directory distribution state, or null before any check/mark has run.",
                        "anyOf": [
                          {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "directory": {
                                  "description": "Distribution directory.",
                                  "type": "string",
                                  "enum": [
                                    "apple",
                                    "spotify",
                                    "youtube"
                                  ]
                                },
                                "status": {
                                  "description": "Distribution state for this directory.",
                                  "type": "string",
                                  "enum": [
                                    "not_submitted",
                                    "pending",
                                    "live"
                                  ]
                                },
                                "externalId": {
                                  "description": "The directory's own id for this show, once detected/recorded.",
                                  "type": "string"
                                },
                                "externalUrl": {
                                  "description": "A link to the live listing, once detected/recorded.",
                                  "type": "string"
                                },
                                "checkedAt": {
                                  "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                                  "type": "string"
                                }
                              },
                              "required": [
                                "directory",
                                "status"
                              ],
                              "additionalProperties": false
                            }
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "description": "ms epoch.",
                        "type": "number"
                      },
                      "updatedAt": {
                        "description": "ms epoch.",
                        "type": "number"
                      },
                      "feedUrl": {
                        "description": "The show's public RSS feed URL — added by every show-returning endpoint.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "slug",
                      "title",
                      "description",
                      "author",
                      "ownerEmail",
                      "artworkUrl",
                      "siteUrl",
                      "category",
                      "language",
                      "explicit",
                      "distribution",
                      "createdAt",
                      "updatedAt",
                      "feedUrl"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows/{id}": {
      "get": {
        "summary": "One show.",
        "description": "One show.",
        "tags": [
          "Podcasts",
          "Podcasts: Shows"
        ],
        "operationId": "get_v1_podcasts_shows__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Shows",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Show id.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "Immutable slug — the feed URL path.",
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "author": {
                      "type": "string"
                    },
                    "ownerEmail": {
                      "type": "string"
                    },
                    "artworkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siteUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "type": "string"
                    },
                    "explicit": {
                      "type": "boolean"
                    },
                    "distribution": {
                      "description": "Per-directory distribution state, or null before any check/mark has run.",
                      "anyOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "directory": {
                                "description": "Distribution directory.",
                                "type": "string",
                                "enum": [
                                  "apple",
                                  "spotify",
                                  "youtube"
                                ]
                              },
                              "status": {
                                "description": "Distribution state for this directory.",
                                "type": "string",
                                "enum": [
                                  "not_submitted",
                                  "pending",
                                  "live"
                                ]
                              },
                              "externalId": {
                                "description": "The directory's own id for this show, once detected/recorded.",
                                "type": "string"
                              },
                              "externalUrl": {
                                "description": "A link to the live listing, once detected/recorded.",
                                "type": "string"
                              },
                              "checkedAt": {
                                "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "directory",
                              "status"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "feedUrl": {
                      "description": "The show's public RSS feed URL — added by every show-returning endpoint.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "title",
                    "description",
                    "author",
                    "ownerEmail",
                    "artworkUrl",
                    "siteUrl",
                    "category",
                    "language",
                    "explicit",
                    "distribution",
                    "createdAt",
                    "updatedAt",
                    "feedUrl"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update show metadata (slug is immutable — it is the feed URL).",
        "description": "Update show metadata (slug is immutable — it is the feed URL).",
        "tags": [
          "Podcasts",
          "Podcasts: Shows"
        ],
        "operationId": "patch_v1_podcasts_shows__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Shows",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "author": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "ownerEmail": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "artworkUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "siteUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "category": {
                    "description": "Apple Podcasts category.",
                    "type": "string",
                    "maxLength": 80
                  },
                  "language": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 16
                  },
                  "explicit": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Renamed Show"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Show id.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "Immutable slug — the feed URL path.",
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "author": {
                      "type": "string"
                    },
                    "ownerEmail": {
                      "type": "string"
                    },
                    "artworkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siteUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "category": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "language": {
                      "type": "string"
                    },
                    "explicit": {
                      "type": "boolean"
                    },
                    "distribution": {
                      "description": "Per-directory distribution state, or null before any check/mark has run.",
                      "anyOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "directory": {
                                "description": "Distribution directory.",
                                "type": "string",
                                "enum": [
                                  "apple",
                                  "spotify",
                                  "youtube"
                                ]
                              },
                              "status": {
                                "description": "Distribution state for this directory.",
                                "type": "string",
                                "enum": [
                                  "not_submitted",
                                  "pending",
                                  "live"
                                ]
                              },
                              "externalId": {
                                "description": "The directory's own id for this show, once detected/recorded.",
                                "type": "string"
                              },
                              "externalUrl": {
                                "description": "A link to the live listing, once detected/recorded.",
                                "type": "string"
                              },
                              "checkedAt": {
                                "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                                "type": "string"
                              }
                            },
                            "required": [
                              "directory",
                              "status"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "feedUrl": {
                      "description": "The show's public RSS feed URL — added by every show-returning endpoint.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "title",
                    "description",
                    "author",
                    "ownerEmail",
                    "artworkUrl",
                    "siteUrl",
                    "category",
                    "language",
                    "explicit",
                    "distribution",
                    "createdAt",
                    "updatedAt",
                    "feedUrl"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows/{id}/episodes": {
      "post": {
        "summary": "Create an episode from ordered segment URLs (intro/story/segue/outro/body). Returns 202 with status processing; assembly stitches + hosts the audio asynchronously. Per segment: title → a Podcasting 2.0 chapter, transcript → a timed transcript entry, padBefore/padAfterSeconds → inserted silence (no re-encode). episodeNumber auto-assigns (next per show) when omitted; linkUrl becomes the feed item's <link>.",
        "description": "Create an episode from ordered segment URLs (intro/story/segue/outro/body). Returns 202 with status processing; assembly stitches + hosts the audio asynchronously. Per segment: title → a Podcasting 2.0 chapter, transcript → a timed transcript entry, padBefore/padAfterSeconds → inserted silence (no re-encode). episodeNumber auto-assigns (next per show) when omitted; linkUrl becomes the feed item's <link>.",
        "tags": [
          "Podcasts",
          "Podcasts: Episodes"
        ],
        "operationId": "post_v1_podcasts_shows__id_episodes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Episodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "linkUrl": {
                    "description": "Episode webpage — becomes the feed item's <link>.",
                    "type": "string",
                    "format": "uri"
                  },
                  "episodeNumber": {
                    "description": "Auto-assigned (next per show) when omitted.",
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "seasonNumber": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "publishAt": {
                    "description": "ISO datetime; future = scheduled. Defaults to now.",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$"
                  },
                  "draft": {
                    "default": false,
                    "type": "boolean"
                  },
                  "segments": {
                    "minItems": 1,
                    "maxItems": 64,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "description": "Segment position in the episode's timeline.",
                          "type": "string",
                          "enum": [
                            "intro",
                            "story",
                            "segue",
                            "outro",
                            "body"
                          ]
                        },
                        "sourceUrl": {
                          "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                          "type": "string",
                          "format": "uri"
                        },
                        "title": {
                          "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 300
                        },
                        "transcript": {
                          "description": "Spoken text — segments with transcripts feed the episode transcript.",
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 50000
                        },
                        "padBeforeSeconds": {
                          "description": "Inserted silence (seconds) before this segment (max 30s).",
                          "type": "number",
                          "minimum": 0,
                          "maximum": 30
                        },
                        "padAfterSeconds": {
                          "description": "Inserted silence (seconds) after this segment (max 30s).",
                          "type": "number",
                          "minimum": 0,
                          "maximum": 30
                        }
                      },
                      "required": [
                        "kind",
                        "sourceUrl"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "title",
                  "description",
                  "draft",
                  "segments"
                ],
                "additionalProperties": false
              },
              "example": {
                "title": "Episode 1",
                "description": "The first episode.",
                "segments": [
                  {
                    "kind": "intro",
                    "sourceUrl": "https://example.com/intro.mp3"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Episode id.",
                      "type": "string"
                    },
                    "showId": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "guid": {
                      "description": "Stable feed identity, minted at create.",
                      "type": "string"
                    },
                    "linkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "episodeNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "seasonNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "publishAt": {
                      "description": "ms epoch; future = scheduled.",
                      "type": "number"
                    },
                    "status": {
                      "description": "Assembly lifecycle state — distinct from the `draft` editorial flag.",
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready",
                        "failed"
                      ]
                    },
                    "draft": {
                      "type": "boolean"
                    },
                    "error": {
                      "description": "Assembly failure reason, when status is failed (e.g. mixed_audio_formats).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "description": "Segment position in the episode's timeline.",
                            "type": "string",
                            "enum": [
                              "intro",
                              "story",
                              "segue",
                              "outro",
                              "body"
                            ]
                          },
                          "sourceUrl": {
                            "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                            "type": "string",
                            "format": "uri"
                          },
                          "title": {
                            "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "transcript": {
                            "description": "Spoken text — segments with transcripts feed the episode transcript.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 50000
                          },
                          "padBeforeSeconds": {
                            "description": "Inserted silence (seconds) before this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "padAfterSeconds": {
                            "description": "Inserted silence (seconds) after this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "startSeconds": {
                            "description": "Where this segment lands on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          },
                          "durationSeconds": {
                            "description": "This segment's duration on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          }
                        },
                        "required": [
                          "kind",
                          "sourceUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "audioUrl": {
                      "description": "Public CDN URL of the assembled artifact, once ready.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "audioBytes": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "durationSeconds": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "id",
                    "showId",
                    "title",
                    "description",
                    "guid",
                    "linkUrl",
                    "episodeNumber",
                    "seasonNumber",
                    "publishAt",
                    "status",
                    "draft",
                    "error",
                    "segments",
                    "audioUrl",
                    "audioBytes",
                    "durationSeconds",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List a show's episodes, newest first (all states).",
        "description": "List a show's episodes, newest first (all states).",
        "tags": [
          "Podcasts",
          "Podcasts: Episodes"
        ],
        "operationId": "get_v1_podcasts_shows__id_episodes",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Episodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Episode id.",
                        "type": "string"
                      },
                      "showId": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "guid": {
                        "description": "Stable feed identity, minted at create.",
                        "type": "string"
                      },
                      "linkUrl": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "episodeNumber": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "seasonNumber": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "publishAt": {
                        "description": "ms epoch; future = scheduled.",
                        "type": "number"
                      },
                      "status": {
                        "description": "Assembly lifecycle state — distinct from the `draft` editorial flag.",
                        "type": "string",
                        "enum": [
                          "processing",
                          "ready",
                          "failed"
                        ]
                      },
                      "draft": {
                        "type": "boolean"
                      },
                      "error": {
                        "description": "Assembly failure reason, when status is failed (e.g. mixed_audio_formats).",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "segments": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "description": "Segment position in the episode's timeline.",
                              "type": "string",
                              "enum": [
                                "intro",
                                "story",
                                "segue",
                                "outro",
                                "body"
                              ]
                            },
                            "sourceUrl": {
                              "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                              "type": "string",
                              "format": "uri"
                            },
                            "title": {
                              "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 300
                            },
                            "transcript": {
                              "description": "Spoken text — segments with transcripts feed the episode transcript.",
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 50000
                            },
                            "padBeforeSeconds": {
                              "description": "Inserted silence (seconds) before this segment (max 30s).",
                              "type": "number",
                              "minimum": 0,
                              "maximum": 30
                            },
                            "padAfterSeconds": {
                              "description": "Inserted silence (seconds) after this segment (max 30s).",
                              "type": "number",
                              "minimum": 0,
                              "maximum": 30
                            },
                            "startSeconds": {
                              "description": "Where this segment lands on the assembled timeline. Absent until the episode is ready.",
                              "type": "number"
                            },
                            "durationSeconds": {
                              "description": "This segment's duration on the assembled timeline. Absent until the episode is ready.",
                              "type": "number"
                            }
                          },
                          "required": [
                            "kind",
                            "sourceUrl"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "audioUrl": {
                        "description": "Public CDN URL of the assembled artifact, once ready.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "audioBytes": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "durationSeconds": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "description": "ms epoch.",
                        "type": "number"
                      },
                      "updatedAt": {
                        "description": "ms epoch.",
                        "type": "number"
                      }
                    },
                    "required": [
                      "id",
                      "showId",
                      "title",
                      "description",
                      "guid",
                      "linkUrl",
                      "episodeNumber",
                      "seasonNumber",
                      "publishAt",
                      "status",
                      "draft",
                      "error",
                      "segments",
                      "audioUrl",
                      "audioBytes",
                      "durationSeconds",
                      "createdAt",
                      "updatedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/episodes/{id}": {
      "get": {
        "summary": "One episode, including assembly status and audio metadata.",
        "description": "One episode, including assembly status and audio metadata.",
        "tags": [
          "Podcasts",
          "Podcasts: Episodes"
        ],
        "operationId": "get_v1_podcasts_episodes__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Episodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Episode id.",
                      "type": "string"
                    },
                    "showId": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "guid": {
                      "description": "Stable feed identity, minted at create.",
                      "type": "string"
                    },
                    "linkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "episodeNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "seasonNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "publishAt": {
                      "description": "ms epoch; future = scheduled.",
                      "type": "number"
                    },
                    "status": {
                      "description": "Assembly lifecycle state — distinct from the `draft` editorial flag.",
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready",
                        "failed"
                      ]
                    },
                    "draft": {
                      "type": "boolean"
                    },
                    "error": {
                      "description": "Assembly failure reason, when status is failed (e.g. mixed_audio_formats).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "description": "Segment position in the episode's timeline.",
                            "type": "string",
                            "enum": [
                              "intro",
                              "story",
                              "segue",
                              "outro",
                              "body"
                            ]
                          },
                          "sourceUrl": {
                            "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                            "type": "string",
                            "format": "uri"
                          },
                          "title": {
                            "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "transcript": {
                            "description": "Spoken text — segments with transcripts feed the episode transcript.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 50000
                          },
                          "padBeforeSeconds": {
                            "description": "Inserted silence (seconds) before this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "padAfterSeconds": {
                            "description": "Inserted silence (seconds) after this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "startSeconds": {
                            "description": "Where this segment lands on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          },
                          "durationSeconds": {
                            "description": "This segment's duration on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          }
                        },
                        "required": [
                          "kind",
                          "sourceUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "audioUrl": {
                      "description": "Public CDN URL of the assembled artifact, once ready.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "audioBytes": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "durationSeconds": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "id",
                    "showId",
                    "title",
                    "description",
                    "guid",
                    "linkUrl",
                    "episodeNumber",
                    "seasonNumber",
                    "publishAt",
                    "status",
                    "draft",
                    "error",
                    "segments",
                    "audioUrl",
                    "audioBytes",
                    "durationSeconds",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update episode metadata; sending new segments re-runs assembly IN PLACE (same guid + episode number — the feed shows one item, re-stitched). This is how a publisher re-runs a day's episode without creating a duplicate.",
        "description": "Update episode metadata; sending new segments re-runs assembly IN PLACE (same guid + episode number — the feed shows one item, re-stitched). This is how a publisher re-runs a day's episode without creating a duplicate.",
        "tags": [
          "Podcasts",
          "Podcasts: Episodes"
        ],
        "operationId": "patch_v1_podcasts_episodes__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Episodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "linkUrl": {
                    "description": "Episode webpage — becomes the feed item's <link>.",
                    "type": "string",
                    "format": "uri"
                  },
                  "episodeNumber": {
                    "description": "Auto-assigned (next per show) when omitted.",
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "seasonNumber": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "publishAt": {
                    "description": "ISO datetime; future = scheduled. Defaults to now.",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$"
                  },
                  "draft": {
                    "type": "boolean"
                  },
                  "segments": {
                    "minItems": 1,
                    "maxItems": 64,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "description": "Segment position in the episode's timeline.",
                          "type": "string",
                          "enum": [
                            "intro",
                            "story",
                            "segue",
                            "outro",
                            "body"
                          ]
                        },
                        "sourceUrl": {
                          "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                          "type": "string",
                          "format": "uri"
                        },
                        "title": {
                          "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 300
                        },
                        "transcript": {
                          "description": "Spoken text — segments with transcripts feed the episode transcript.",
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 50000
                        },
                        "padBeforeSeconds": {
                          "description": "Inserted silence (seconds) before this segment (max 30s).",
                          "type": "number",
                          "minimum": 0,
                          "maximum": 30
                        },
                        "padAfterSeconds": {
                          "description": "Inserted silence (seconds) after this segment (max 30s).",
                          "type": "number",
                          "minimum": 0,
                          "maximum": 30
                        }
                      },
                      "required": [
                        "kind",
                        "sourceUrl"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Renamed Episode"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Episode id.",
                      "type": "string"
                    },
                    "showId": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "guid": {
                      "description": "Stable feed identity, minted at create.",
                      "type": "string"
                    },
                    "linkUrl": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "episodeNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "seasonNumber": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "publishAt": {
                      "description": "ms epoch; future = scheduled.",
                      "type": "number"
                    },
                    "status": {
                      "description": "Assembly lifecycle state — distinct from the `draft` editorial flag.",
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready",
                        "failed"
                      ]
                    },
                    "draft": {
                      "type": "boolean"
                    },
                    "error": {
                      "description": "Assembly failure reason, when status is failed (e.g. mixed_audio_formats).",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "description": "Segment position in the episode's timeline.",
                            "type": "string",
                            "enum": [
                              "intro",
                              "story",
                              "segue",
                              "outro",
                              "body"
                            ]
                          },
                          "sourceUrl": {
                            "description": "Publicly fetchable, same-format MP3 (CBR, one sample rate).",
                            "type": "string",
                            "format": "uri"
                          },
                          "title": {
                            "description": "Chapter title — titled segments become Podcasting 2.0 chapters once assembly stamps their timeline offsets.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 300
                          },
                          "transcript": {
                            "description": "Spoken text — segments with transcripts feed the episode transcript.",
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 50000
                          },
                          "padBeforeSeconds": {
                            "description": "Inserted silence (seconds) before this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "padAfterSeconds": {
                            "description": "Inserted silence (seconds) after this segment (max 30s).",
                            "type": "number",
                            "minimum": 0,
                            "maximum": 30
                          },
                          "startSeconds": {
                            "description": "Where this segment lands on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          },
                          "durationSeconds": {
                            "description": "This segment's duration on the assembled timeline. Absent until the episode is ready.",
                            "type": "number"
                          }
                        },
                        "required": [
                          "kind",
                          "sourceUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "audioUrl": {
                      "description": "Public CDN URL of the assembled artifact, once ready.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "audioBytes": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "durationSeconds": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    },
                    "updatedAt": {
                      "description": "ms epoch.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "id",
                    "showId",
                    "title",
                    "description",
                    "guid",
                    "linkUrl",
                    "episodeNumber",
                    "seasonNumber",
                    "publishAt",
                    "status",
                    "draft",
                    "error",
                    "segments",
                    "audioUrl",
                    "audioBytes",
                    "durationSeconds",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows/{id}/distribution": {
      "get": {
        "summary": "Per-directory distribution state (Apple / Spotify / YouTube) with prefilled submit links and the feed URL to paste. Submission itself is manual — no directory exposes a public submission API.",
        "description": "Per-directory distribution state (Apple / Spotify / YouTube) with prefilled submit links and the feed URL to paste. Submission itself is manual — no directory exposes a public submission API.",
        "tags": [
          "Podcasts",
          "Podcasts: Distribution"
        ],
        "operationId": "get_v1_podcasts_shows__id_distribution",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Distribution",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "feedUrl": {
                      "description": "The feed URL to paste into each directory.",
                      "type": "string"
                    },
                    "directories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "directory": {
                            "description": "Distribution directory.",
                            "type": "string",
                            "enum": [
                              "apple",
                              "spotify",
                              "youtube"
                            ]
                          },
                          "status": {
                            "description": "Distribution state for this directory.",
                            "type": "string",
                            "enum": [
                              "not_submitted",
                              "pending",
                              "live"
                            ]
                          },
                          "externalId": {
                            "description": "The directory's own id for this show, once detected/recorded.",
                            "type": "string"
                          },
                          "externalUrl": {
                            "description": "A link to the live listing, once detected/recorded.",
                            "type": "string"
                          },
                          "checkedAt": {
                            "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                            "type": "string"
                          },
                          "submitUrl": {
                            "description": "Where a human pastes the feed URL for this directory.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "directory",
                          "status",
                          "submitUrl"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "feedUrl",
                    "directories"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows/{id}/distribution/check": {
      "post": {
        "summary": "Detect live listings and persist them: Apple via the public iTunes Search API (exact feedUrl match), Spotify via the Web API using your `connect` Spotify connection (title + publisher match). Returns the refreshed rows plus per-directory notes when detection was skipped.",
        "description": "Detect live listings and persist them: Apple via the public iTunes Search API (exact feedUrl match), Spotify via the Web API using your `connect` Spotify connection (title + publisher match). Returns the refreshed rows plus per-directory notes when detection was skipped.",
        "tags": [
          "Podcasts",
          "Podcasts: Distribution"
        ],
        "operationId": "post_v1_podcasts_shows__id_distribution_check",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Distribution",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "feedUrl": {
                      "type": "string"
                    },
                    "directories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "directory": {
                            "description": "Distribution directory.",
                            "type": "string",
                            "enum": [
                              "apple",
                              "spotify",
                              "youtube"
                            ]
                          },
                          "status": {
                            "description": "Distribution state for this directory.",
                            "type": "string",
                            "enum": [
                              "not_submitted",
                              "pending",
                              "live"
                            ]
                          },
                          "externalId": {
                            "description": "The directory's own id for this show, once detected/recorded.",
                            "type": "string"
                          },
                          "externalUrl": {
                            "description": "A link to the live listing, once detected/recorded.",
                            "type": "string"
                          },
                          "checkedAt": {
                            "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                            "type": "string"
                          },
                          "submitUrl": {
                            "description": "Where a human pastes the feed URL for this directory.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "directory",
                          "status",
                          "submitUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "notes": {
                      "description": "Per-directory notes when detection was skipped (e.g. no connect Spotify connection).",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "feedUrl",
                    "directories",
                    "notes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/shows/{id}/distribution/{directory}": {
      "patch": {
        "summary": "Manually mark a directory (e.g. YouTube after Studio RSS setup, or record a submission as pending).",
        "description": "Manually mark a directory (e.g. YouTube after Studio RSS setup, or record a submission as pending).",
        "tags": [
          "Podcasts",
          "Podcasts: Distribution"
        ],
        "operationId": "patch_v1_podcasts_shows__id_distribution__directory",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Distribution",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "directory",
            "in": "path",
            "required": true,
            "description": "Distribution directory.",
            "schema": {
              "type": "string",
              "enum": [
                "apple",
                "spotify",
                "youtube"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "status": {
                    "description": "Distribution state for this directory.",
                    "type": "string",
                    "enum": [
                      "not_submitted",
                      "pending",
                      "live"
                    ]
                  },
                  "externalUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "externalId": {
                    "type": "string"
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              },
              "example": {
                "status": "pending"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "feedUrl": {
                      "type": "string"
                    },
                    "directories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "directory": {
                            "description": "Distribution directory.",
                            "type": "string",
                            "enum": [
                              "apple",
                              "spotify",
                              "youtube"
                            ]
                          },
                          "status": {
                            "description": "Distribution state for this directory.",
                            "type": "string",
                            "enum": [
                              "not_submitted",
                              "pending",
                              "live"
                            ]
                          },
                          "externalId": {
                            "description": "The directory's own id for this show, once detected/recorded.",
                            "type": "string"
                          },
                          "externalUrl": {
                            "description": "A link to the live listing, once detected/recorded.",
                            "type": "string"
                          },
                          "checkedAt": {
                            "description": "ISO timestamp of the last detection/manual-mark for this directory.",
                            "type": "string"
                          },
                          "submitUrl": {
                            "description": "Where a human pastes the feed URL for this directory.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "directory",
                          "status",
                          "submitUrl"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "feedUrl",
                    "directories"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/episodes/{id}/analytics": {
      "get": {
        "summary": "Download counts: total plus per-UTC-day breakdown.",
        "description": "Download counts: total plus per-UTC-day breakdown.",
        "tags": [
          "Podcasts",
          "Podcasts: Analytics"
        ],
        "operationId": "get_v1_podcasts_episodes__id_analytics",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Analytics",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "episodeId": {
                      "type": "string"
                    },
                    "total": {
                      "description": "Total downloads across all days.",
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "daily": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "day": {
                            "description": "UTC date, YYYY-MM-DD.",
                            "type": "string"
                          },
                          "count": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "day",
                          "count"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "episodeId",
                    "total",
                    "daily"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/episodes/{id}/chapters.json": {
      "get": {
        "summary": "Podcasting 2.0 chapters (json+chapters) built from the episode's titled segments and their assembly-stamped timeline — linked automatically from the feed via <podcast:chapters>.",
        "description": "Podcasting 2.0 chapters (json+chapters) built from the episode's titled segments and their assembly-stamped timeline — linked automatically from the feed via <podcast:chapters>.\n\n**Example:**\n\n```\n{ \"version\": \"1.2.0\", \"chapters\": [{ \"startTime\": 9.038, \"title\": \"Introduction\" }, { \"startTime\": 47.229, \"title\": \"First story headline\" }] }\n```",
        "tags": [
          "Podcasts",
          "Podcasts: Public"
        ],
        "operationId": "get_v1_podcasts_episodes__id_chapters.json",
        "security": [],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Public",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Podcasting 2.0 chapters document (raw, not the { data } envelope): { \"version\": \"1.2.0\", \"chapters\": [{ \"startTime\": number, \"title\": string }] }. Built from the episode's titled, timeline-stamped segments.",
            "content": {
              "application/json+chapters": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/episodes/{id}/transcript.json": {
      "get": {
        "summary": "Podcasting 2.0 JSON transcript built from the segments' spoken text, timed by the assembly's frame-counted offsets — linked from the feed via <podcast:transcript>.",
        "description": "Podcasting 2.0 JSON transcript built from the segments' spoken text, timed by the assembly's frame-counted offsets — linked from the feed via <podcast:transcript>.\n\n**Example:**\n\n```\n{ \"version\": \"1.0.0\", \"segments\": [{ \"startTime\": 9.0, \"endTime\": 45.8, \"body\": \"Welcome to the show…\" }] }\n```",
        "tags": [
          "Podcasts",
          "Podcasts: Public"
        ],
        "operationId": "get_v1_podcasts_episodes__id_transcript.json",
        "security": [],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Public",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Show or episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Podcasting 2.0 JSON transcript (raw, not the { data } envelope): { \"version\": \"1.0.0\", \"segments\": [{ \"startTime\": number, \"endTime\": number, \"body\": string }] }. Built from the episode's transcribed, timeline-stamped segments.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/feeds/{slug}.xml": {
      "get": {
        "summary": "The show's RSS feed — RSS 2.0 + iTunes tags (episodic type, copyright, per-item episodeType/link/episode numbers) + Podcasting 2.0 chapter/transcript links. This is the URL you submit to directories.",
        "description": "The show's RSS feed — RSS 2.0 + iTunes tags (episodic type, copyright, per-item episodeType/link/episode numbers) + Podcasting 2.0 chapter/transcript links. This is the URL you submit to directories.",
        "tags": [
          "Podcasts",
          "Podcasts: Public"
        ],
        "operationId": "get_v1_podcasts_feeds__slug.xml",
        "security": [],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Public",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Show slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "RSS 2.0 + iTunes tags + Podcasting 2.0 chapter/transcript links. Only assembled, non-draft episodes past their publishAt appear.",
            "content": {
              "application/rss+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/v1/podcasts/audio/{episodeId}.mp3": {
      "get": {
        "summary": "Counting audio redirect — increments the day's download count and 302s to the CDN file. Used as the feed's enclosure URL.",
        "description": "Counting audio redirect — increments the day's download count and 302s to the CDN file. Used as the feed's enclosure URL.",
        "tags": [
          "Podcasts",
          "Podcasts: Public"
        ],
        "operationId": "get_v1_podcasts_audio__episodeId.mp3",
        "security": [],
        "x-cheapass-product": "podcasts",
        "x-cheapass-group": "Public",
        "parameters": [
          {
            "name": "episodeId",
            "in": "path",
            "required": true,
            "description": "Episode id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Counts the day's download, then 302s to the CDN file (Location header; empty body). Used as every feed item's enclosure URL."
          }
        }
      }
    },
    "/v1/users/me": {
      "get": {
        "summary": "The authenticated account: id, email, plan, enabled products. The standard 'is my key valid' call.",
        "description": "The authenticated account: id, email, plan, enabled products. The standard 'is my key valid' call.",
        "tags": [
          "Platform",
          "Platform: Identity"
        ],
        "operationId": "get_v1_users_me",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Identity",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "User id.",
                      "type": "string"
                    },
                    "email": {
                      "description": "Account email.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Account display name.",
                      "type": "string"
                    },
                    "isOwner": {
                      "description": "True for the platform owner's own account.",
                      "type": "boolean"
                    },
                    "billing": {
                      "type": "object",
                      "properties": {
                        "plan": {
                          "description": "Canonical plan id, or \"owner\" for the owner account.",
                          "type": "string",
                          "enum": [
                            "owner",
                            "vibe",
                            "junior",
                            "senior"
                          ]
                        },
                        "unlimited": {
                          "description": "True only for the owner.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "plan",
                        "unlimited"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "email",
                    "name",
                    "isOwner",
                    "billing"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "summary": "List this account's API keys (prefixes only — secrets are shown once at mint).",
        "description": "List this account's API keys (prefixes only — secrets are shown once at mint).",
        "tags": [
          "Platform",
          "Platform: Keys"
        ],
        "operationId": "get_v1_api-keys",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Keys",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Key id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name.",
                        "type": "string"
                      },
                      "keyPrefix": {
                        "description": "The key's non-secret prefix, for identifying it in a list.",
                        "type": "string"
                      },
                      "productIds": {
                        "description": "Products this key is scoped to. Empty = no restriction.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "projectId": {
                        "description": "Project this key belongs to, or null for Global.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "lastUsedAt": {
                        "description": "ISO timestamp of the key's last authenticated request, when it has one.",
                        "type": "string"
                      },
                      "expiresAt": {
                        "description": "ISO expiry timestamp, when set.",
                        "type": "string"
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "keyPrefix",
                      "productIds",
                      "projectId",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Mint a key, optionally scoped to specific products and/or assigned to a project.",
        "description": "Mint a key, optionally scoped to specific products and/or assigned to a project.",
        "tags": [
          "Platform",
          "Platform: Keys"
        ],
        "operationId": "post_v1_api-keys",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Keys",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Display name for the key.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "expiresAt": {
                    "description": "ISO expiry timestamp. Absent = never expires.",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
                  },
                  "productIds": {
                    "description": "Restrict the key to these product ids (validated against the live catalog). Empty/absent = the key may call any enabled product.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "projectId": {
                    "description": "Assign the key to this project at mint time. Absent = Global (or the calling key's own project, if any).",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "cheapass contract test key"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "The new key's id.",
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "key": {
                      "description": "The RAW secret key. Shown exactly once, here — it is never retrievable again; only `keyPrefix` is stored for display.",
                      "type": "string"
                    },
                    "keyPrefix": {
                      "type": "string"
                    },
                    "productIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "projectId": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expiresAt": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "warning": {
                      "description": "Always \"Store this key securely. It will not be shown again.\"",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "key",
                    "keyPrefix",
                    "productIds",
                    "projectId",
                    "expiresAt",
                    "warning"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "patch": {
        "summary": "Assign or move a key between projects. Body requires projectId: a project id to move the key there, or null to move it back to Global — the field itself is required (there is no 'omit it, nothing changes' form).",
        "description": "Assign or move a key between projects. Body requires projectId: a project id to move the key there, or null to move it back to Global — the field itself is required (there is no 'omit it, nothing changes' form).",
        "tags": [
          "Platform",
          "Platform: Keys"
        ],
        "operationId": "patch_v1_api-keys__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Keys",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "projectId": {
                    "description": "Project id to move the key to, or null to move it back to Global. Required — this field cannot be omitted.",
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "projectId"
                ],
                "additionalProperties": false
              },
              "example": {
                "projectId": null
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Key id.",
                      "type": "string"
                    },
                    "projectId": {
                      "description": "The key's new project scope.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "projectId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Revoke a key.",
        "description": "Revoke a key.",
        "tags": [
          "Platform",
          "Platform: Keys"
        ],
        "operationId": "delete_v1_api-keys__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Keys",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Key id.",
                      "type": "string"
                    },
                    "revokedAt": {
                      "description": "ISO timestamp of revocation.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "revokedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/credentials": {
      "post": {
        "summary": "Store a third-party secret (API key/token) for a connector provider, encrypted at rest. Returns the credential's id/provider/label/createdAt — never the secret again.",
        "description": "Store a third-party secret (API key/token) for a connector provider, encrypted at rest. Returns the credential's id/provider/label/createdAt — never the secret again.",
        "tags": [
          "Platform",
          "Platform: Credentials"
        ],
        "operationId": "post_v1_credentials",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Credentials",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "provider": {
                    "description": "Connector provider id this credential is for (e.g. \"acme\") — matches a future connector's connectorMeta.provider.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "secret": {
                    "description": "The raw secret (API key/token/etc.) to store. Encrypted at rest; no read endpoint ever returns it.",
                    "type": "string",
                    "minLength": 1
                  },
                  "label": {
                    "description": "Optional display label, for telling multiple credentials for the same provider apart.",
                    "type": "string",
                    "maxLength": 120
                  }
                },
                "required": [
                  "provider",
                  "secret"
                ],
                "additionalProperties": false
              },
              "example": {
                "provider": "example",
                "secret": "test-secret-not-real",
                "label": "contract test credential"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Credential id.",
                      "type": "string"
                    },
                    "provider": {
                      "description": "Provider id this credential is stored for.",
                      "type": "string"
                    },
                    "label": {
                      "description": "Display label, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "provider",
                    "label",
                    "createdAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List this account's stored credentials (provider/label/createdAt only — secrets are never returned).",
        "description": "List this account's stored credentials (provider/label/createdAt only — secrets are never returned).",
        "tags": [
          "Platform",
          "Platform: Credentials"
        ],
        "operationId": "get_v1_credentials",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Credentials",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Credential id.",
                        "type": "string"
                      },
                      "provider": {
                        "description": "Provider id this credential is stored for.",
                        "type": "string"
                      },
                      "label": {
                        "description": "Display label, or null.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "provider",
                      "label",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/credentials/{id}": {
      "delete": {
        "summary": "Remove a stored credential.",
        "description": "Remove a stored credential.",
        "tags": [
          "Platform",
          "Platform: Credentials"
        ],
        "operationId": "delete_v1_credentials__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Credentials",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Credential id.",
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "summary": "List this account's projects.",
        "description": "List this account's projects.",
        "tags": [
          "Platform",
          "Platform: Projects"
        ],
        "operationId": "get_v1_projects",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Projects",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Project id.",
                        "type": "string"
                      },
                      "name": {
                        "description": "Project name.",
                        "type": "string"
                      },
                      "description": {
                        "description": "Description, or null.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "icon": {
                        "description": "Icon id, or null.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "allowGlobalFallback": {
                        "description": "Whether this project's keys fall back to Global connections when it has none of its own.",
                        "type": "boolean"
                      },
                      "createdAt": {
                        "description": "ISO timestamp.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "description",
                      "icon",
                      "allowGlobalFallback",
                      "createdAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project - an optional scope for keys, connections, and product kill switches. By default a project only overrides what it sets (everything else falls back to Global); pass allowGlobalFallback: false for strict isolation - its keys then see only the project's own connections.",
        "description": "Create a project - an optional scope for keys, connections, and product kill switches. By default a project only overrides what it sets (everything else falls back to Global); pass allowGlobalFallback: false for strict isolation - its keys then see only the project's own connections.",
        "tags": [
          "Platform",
          "Platform: Projects"
        ],
        "operationId": "post_v1_projects",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Projects",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Project name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "description": {
                    "description": "Optional description.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "icon": {
                    "description": "One of: cube, rocket, globe, key, bolt, chart, terminal, database, cloud, book, flask, gamepad, music, camera, heart, star, mail, wrench (or \"\" to leave unset).",
                    "type": "string"
                  },
                  "allowGlobalFallback": {
                    "description": "false = strict isolation: the project's keys see only its own connections, no Global fallback. Defaults to true.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "cheapass contract test project"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Project id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Project name.",
                      "type": "string"
                    },
                    "description": {
                      "description": "Description, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "icon": {
                      "description": "Icon id, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "allowGlobalFallback": {
                      "description": "Whether this project's keys fall back to Global connections when it has none of its own.",
                      "type": "boolean"
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "description",
                    "icon",
                    "allowGlobalFallback",
                    "createdAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}": {
      "patch": {
        "summary": "Rename a project, change its description/icon, or flip its Global-fallback setting.",
        "description": "Rename a project, change its description/icon, or flip its Global-fallback setting.",
        "tags": [
          "Platform",
          "Platform: Projects"
        ],
        "operationId": "patch_v1_projects__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Projects",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Rename the project.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "description": {
                    "description": "Replace the description.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "icon": {
                    "description": "One of: cube, rocket, globe, key, bolt, chart, terminal, database, cloud, book, flask, gamepad, music, camera, heart, star, mail, wrench (or \"\" to leave unset).",
                    "type": "string"
                  },
                  "allowGlobalFallback": {
                    "description": "Flip the Global-fallback setting.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Renamed"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Project id.",
                      "type": "string"
                    },
                    "name": {
                      "description": "Project name.",
                      "type": "string"
                    },
                    "description": {
                      "description": "Description, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "icon": {
                      "description": "Icon id, or null.",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "allowGlobalFallback": {
                      "description": "Whether this project's keys fall back to Global connections when it has none of its own.",
                      "type": "boolean"
                    },
                    "createdAt": {
                      "description": "ISO timestamp.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "description",
                    "icon",
                    "allowGlobalFallback",
                    "createdAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a project. Its keys and connections fall back to Global; its kill switches are removed. Nothing is destroyed except the grouping.",
        "description": "Delete a project. Its keys and connections fall back to Global; its kill switches are removed. Nothing is destroyed except the grouping.",
        "tags": [
          "Platform",
          "Platform: Projects"
        ],
        "operationId": "delete_v1_projects__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Projects",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "summary": "The full product catalog with per-endpoint documentation — the same data the docs render, machine-readable.",
        "description": "The full product catalog with per-endpoint documentation — the same data the docs render, machine-readable.",
        "tags": [
          "Platform",
          "Platform: Catalog"
        ],
        "operationId": "get_v1_products",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Catalog",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "tagline": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "pitch": {
                        "type": "string"
                      },
                      "basePath": {
                        "type": "string"
                      },
                      "category": {
                        "type": "string",
                        "enum": [
                          "publish",
                          "ingest",
                          "build"
                        ]
                      },
                      "highlights": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string"
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          },
                          "required": [
                            "label",
                            "items"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "available",
                          "coming_soon"
                        ]
                      },
                      "alwaysOn": {
                        "type": "boolean"
                      },
                      "minPlan": {
                        "description": "Minimum plan tier required to enable this product. Absent = the default tier.",
                        "type": "string"
                      },
                      "addOnId": {
                        "description": "Separately-priced add-on id that gates this product instead of minPlan, when set.",
                        "type": "string"
                      },
                      "howItWorks": {
                        "type": "string"
                      },
                      "getStarted": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "useCases": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "cliCommands": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "enabled": {
                        "description": "Whether the calling account has this product enabled. Best-effort: only populated when an API key is supplied; false otherwise.",
                        "type": "boolean"
                      },
                      "endpoints": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "method": {
                              "type": "string",
                              "enum": [
                                "GET",
                                "POST",
                                "PATCH",
                                "PUT",
                                "DELETE"
                              ]
                            },
                            "path": {
                              "description": "Path, with `:param` segments.",
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            },
                            "group": {
                              "description": "Sub-group within the product, for docs organization.",
                              "type": "string"
                            },
                            "auth": {
                              "type": "string",
                              "enum": [
                                "api_key",
                                "none",
                                "admin"
                              ]
                            },
                            "request": {
                              "description": "Legacy request-shape prose — present only for endpoints not yet migrated to the schema registry.",
                              "type": "string"
                            },
                            "response": {
                              "description": "Legacy response-shape prose — same caveat as `request`.",
                              "type": "string"
                            },
                            "example": {
                              "description": "A real example response body (JSON string), when curated.",
                              "type": "string"
                            },
                            "billing": {
                              "type": "string",
                              "enum": [
                                "billable",
                                "free_tier_only"
                              ]
                            },
                            "comingSoon": {
                              "description": "True if this specific endpoint still 501s even though its product is available.",
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "method",
                            "path",
                            "description"
                          ],
                          "additionalProperties": false
                        }
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "tagline",
                      "description",
                      "pitch",
                      "basePath",
                      "category",
                      "status",
                      "alwaysOn",
                      "howItWorks",
                      "getStarted",
                      "useCases",
                      "cliCommands",
                      "enabled",
                      "endpoints"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}": {
      "get": {
        "summary": "One product's catalog entry.",
        "description": "One product's catalog entry.",
        "tags": [
          "Platform",
          "Platform: Catalog"
        ],
        "operationId": "get_v1_products__id",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "tagline": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "pitch": {
                      "type": "string"
                    },
                    "basePath": {
                      "type": "string"
                    },
                    "category": {
                      "type": "string",
                      "enum": [
                        "publish",
                        "ingest",
                        "build"
                      ]
                    },
                    "highlights": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "label": {
                            "type": "string"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "label",
                          "items"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "available",
                        "coming_soon"
                      ]
                    },
                    "alwaysOn": {
                      "type": "boolean"
                    },
                    "minPlan": {
                      "description": "Minimum plan tier required to enable this product. Absent = the default tier.",
                      "type": "string"
                    },
                    "addOnId": {
                      "description": "Separately-priced add-on id that gates this product instead of minPlan, when set.",
                      "type": "string"
                    },
                    "howItWorks": {
                      "type": "string"
                    },
                    "getStarted": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "useCases": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "cliCommands": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "enabled": {
                      "description": "Whether the calling account has this product enabled. Best-effort: only populated when an API key is supplied; false otherwise.",
                      "type": "boolean"
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "method": {
                            "type": "string",
                            "enum": [
                              "GET",
                              "POST",
                              "PATCH",
                              "PUT",
                              "DELETE"
                            ]
                          },
                          "path": {
                            "description": "Path, with `:param` segments.",
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "group": {
                            "description": "Sub-group within the product, for docs organization.",
                            "type": "string"
                          },
                          "auth": {
                            "description": "Overwritten by the descriptor's own `auth` when one exists (identical values today).",
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "api_key",
                                  "none",
                                  "admin"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "credential": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "credential"
                                ],
                                "additionalProperties": false
                              }
                            ]
                          },
                          "request": {
                            "description": "Legacy request-shape prose — present only for endpoints not yet migrated to the schema registry.",
                            "type": "string"
                          },
                          "response": {
                            "description": "Legacy response-shape prose — same caveat as `request`.",
                            "type": "string"
                          },
                          "example": {
                            "description": "A real example response body (JSON string), when curated.",
                            "type": "string"
                          },
                          "billing": {
                            "type": "string",
                            "enum": [
                              "billable",
                              "free_tier_only"
                            ]
                          },
                          "comingSoon": {
                            "description": "True if this specific endpoint still 501s even though its product is available.",
                            "type": "boolean"
                          },
                          "params": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          "query": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          "requestSchema": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          "responseSchema": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          "responseBinary": {
                            "type": "object",
                            "properties": {
                              "contentTypes": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "description": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "contentTypes",
                              "description"
                            ],
                            "additionalProperties": false
                          },
                          "responseRedirect": {
                            "type": "object",
                            "properties": {
                              "description": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "description"
                            ],
                            "additionalProperties": false
                          },
                          "responseStream": {
                            "type": "object",
                            "properties": {
                              "contentType": {
                                "type": "string"
                              },
                              "description": {
                                "type": "string"
                              },
                              "events": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "contentType",
                              "description"
                            ],
                            "additionalProperties": false
                          },
                          "requestExample": {
                            "description": "A runnable example request for this endpoint.",
                            "type": "object",
                            "properties": {
                              "params": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {
                                  "type": "string"
                                }
                              },
                              "query": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {
                                  "type": "string"
                                }
                              },
                              "body": {},
                              "note": {
                                "type": "string"
                              }
                            },
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "method",
                          "path",
                          "description"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "tagline",
                    "description",
                    "pitch",
                    "basePath",
                    "category",
                    "status",
                    "alwaysOn",
                    "howItWorks",
                    "getStarted",
                    "useCases",
                    "cliCommands",
                    "enabled",
                    "endpoints"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Disable a product — an explicit kill switch. Calls to it 403 until re-enabled; auto-enable-on-use won't override it. ?project=<id> switches off only that project (default: the calling key's scope; a Global disable applies account-wide). Always-on products (social, assistant) can't be disabled.",
        "description": "Disable a product — an explicit kill switch. Calls to it 403 until re-enabled; auto-enable-on-use won't override it. ?project=<id> switches off only that project (default: the calling key's scope; a Global disable applies account-wide). Always-on products (social, assistant) can't be disabled.",
        "tags": [
          "Platform",
          "Platform: Catalog"
        ],
        "operationId": "delete_v1_products__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "query",
            "required": false,
            "description": "Target one project's switch instead of the calling key's own scope (Global if the key has none).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean",
                      "const": false
                    }
                  },
                  "required": [
                    "id",
                    "enabled"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/endpoints/{slug}": {
      "get": {
        "summary": "One endpoint from a product's catalog entry, addressed by its stable slug (the same slug /docs/<product>/endpoints/<slug> uses) — enriched with its generated request/response JSON Schema and a runnable example.",
        "description": "One endpoint from a product's catalog entry, addressed by its stable slug (the same slug /docs/<product>/endpoints/<slug> uses) — enriched with its generated request/response JSON Schema and a runnable example.",
        "tags": [
          "Platform",
          "Platform: Catalog"
        ],
        "operationId": "get_v1_products__id_endpoints__slug",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Product id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Endpoint slug — see GET /v1/products/:id's enriched endpoint list, or /docs/<product> (the slug in each endpoint's own docs URL).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "product": {
                      "description": "Product id.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "Endpoint slug (echoed).",
                      "type": "string"
                    },
                    "endpoint": {
                      "type": "object",
                      "properties": {
                        "method": {
                          "type": "string",
                          "enum": [
                            "GET",
                            "POST",
                            "PATCH",
                            "PUT",
                            "DELETE"
                          ]
                        },
                        "path": {
                          "description": "Path, with `:param` segments.",
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "group": {
                          "description": "Sub-group within the product, for docs organization.",
                          "type": "string"
                        },
                        "auth": {
                          "description": "Overwritten by the descriptor's own `auth` when one exists (identical values today).",
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "api_key",
                                "none",
                                "admin"
                              ]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "credential": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "credential"
                              ],
                              "additionalProperties": false
                            }
                          ]
                        },
                        "request": {
                          "description": "Legacy request-shape prose — present only for endpoints not yet migrated to the schema registry.",
                          "type": "string"
                        },
                        "response": {
                          "description": "Legacy response-shape prose — same caveat as `request`.",
                          "type": "string"
                        },
                        "example": {
                          "description": "A real example response body (JSON string), when curated.",
                          "type": "string"
                        },
                        "billing": {
                          "type": "string",
                          "enum": [
                            "billable",
                            "free_tier_only"
                          ]
                        },
                        "comingSoon": {
                          "description": "True if this specific endpoint still 501s even though its product is available.",
                          "type": "boolean"
                        },
                        "params": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "query": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "requestSchema": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "responseSchema": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        "responseBinary": {
                          "type": "object",
                          "properties": {
                            "contentTypes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "description": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "contentTypes",
                            "description"
                          ],
                          "additionalProperties": false
                        },
                        "responseRedirect": {
                          "type": "object",
                          "properties": {
                            "description": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "description"
                          ],
                          "additionalProperties": false
                        },
                        "responseStream": {
                          "type": "object",
                          "properties": {
                            "contentType": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            },
                            "events": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "contentType",
                            "description"
                          ],
                          "additionalProperties": false
                        },
                        "requestExample": {
                          "description": "A runnable example request for this endpoint.",
                          "type": "object",
                          "properties": {
                            "params": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "type": "string"
                              }
                            },
                            "query": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "type": "string"
                              }
                            },
                            "body": {},
                            "note": {
                              "type": "string"
                            }
                          },
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "method",
                        "path",
                        "description"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "product",
                    "slug",
                    "endpoint"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/enable": {
      "post": {
        "summary": "Enable a product explicitly. Optional — products auto-enable on your first call to them (plan gates still apply); this endpoint remains for pre-flighting and for re-enabling after a disable. ?project=<id> targets one project's switch (default: the calling key's scope).",
        "description": "Enable a product explicitly. Optional — products auto-enable on your first call to them (plan gates still apply); this endpoint remains for pre-flighting and for re-enabling after a disable. ?project=<id> targets one project's switch (default: the calling key's scope).",
        "tags": [
          "Platform",
          "Platform: Catalog"
        ],
        "operationId": "post_v1_products__id_enable",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Catalog",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "query",
            "required": false,
            "description": "Target one project's switch instead of the calling key's own scope (Global if the key has none).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "alreadyEnabled": {
                      "description": "Present (and false) only on a fresh enable; absent for always-on products.",
                      "type": "boolean"
                    },
                    "alwaysOn": {
                      "description": "Present only for always-on products, which are already enabled and can't be toggled.",
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "enabled"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "summary": "Platform health as JSON — the public status page's data.",
        "description": "Platform health as JSON — the public status page's data.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_v1_status",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "status": {
                      "description": "Overall platform status.",
                      "type": "string",
                      "enum": [
                        "operational",
                        "degraded",
                        "down"
                      ]
                    },
                    "generatedAt": {
                      "type": "string"
                    },
                    "products": {
                      "description": "Every `available` product (coming_soon products are excluded, not counted as down).",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "tagline": {
                            "type": "string"
                          },
                          "basePath": {
                            "type": "string"
                          },
                          "category": {
                            "type": "string",
                            "enum": [
                              "publish",
                              "ingest",
                              "build"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "available",
                              "coming_soon"
                            ]
                          },
                          "alwaysOn": {
                            "type": "boolean"
                          },
                          "operational": {
                            "type": "string",
                            "enum": [
                              "operational",
                              "degraded",
                              "down"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "tagline",
                          "basePath",
                          "category",
                          "status",
                          "alwaysOn",
                          "operational"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "feeds": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "counts": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "errored": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "dead": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "active",
                            "errored",
                            "dead"
                          ],
                          "additionalProperties": false
                        },
                        "healthyPct": {
                          "description": "Percentage of feeds currently active.",
                          "type": "number"
                        },
                        "lastFetchedAt": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "oldestNextFetch": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "generatedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "total",
                        "counts",
                        "healthyPct",
                        "lastFetchedAt",
                        "oldestNextFetch",
                        "generatedAt"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "status",
                    "generatedAt",
                    "products",
                    "feeds"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/status/feeds": {
      "get": {
        "summary": "Per-source health for every feed in the shared catalog: status, last fetch, consecutive failures, reliability.",
        "description": "Per-source health for every feed in the shared catalog: status, last fetch, consecutive failures, reliability.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_v1_status_feeds",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "counts": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "errored": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "dead": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "active",
                            "errored",
                            "dead"
                          ],
                          "additionalProperties": false
                        },
                        "healthyPct": {
                          "description": "Percentage of feeds currently active.",
                          "type": "number"
                        },
                        "lastFetchedAt": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "oldestNextFetch": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "generatedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "total",
                        "counts",
                        "healthyPct",
                        "lastFetchedAt",
                        "oldestNextFetch",
                        "generatedAt"
                      ],
                      "additionalProperties": false
                    },
                    "feeds": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "errored",
                              "dead"
                            ]
                          },
                          "reliability": {
                            "type": "string",
                            "enum": [
                              "mainstream",
                              "watchdog",
                              "unverified"
                            ]
                          },
                          "language": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "categorySlug": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "categorySlugs": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "lastFetchedAt": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "nextFetchAt": {
                            "type": "string"
                          },
                          "consecutiveFailures": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "url",
                          "status",
                          "reliability",
                          "language",
                          "categorySlug",
                          "categorySlugs",
                          "lastFetchedAt",
                          "nextFetchAt",
                          "consecutiveFailures"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "parentSlug": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "parentName": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "count": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "slug",
                          "name",
                          "parentSlug",
                          "parentName",
                          "count"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "summary",
                    "feeds",
                    "categories"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/status/data": {
      "get": {
        "summary": "Per-source health for the data product's upstream datasets — which are live, which still 501.",
        "description": "Per-source health for the data product's upstream datasets — which are live, which still 501.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_v1_status_data",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "product": {
                      "type": "string",
                      "const": "data"
                    },
                    "total": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "live": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "planned": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "generatedAt": {
                      "type": "string"
                    },
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "endpoint": {
                            "description": "Path suffix after /v1/data/.",
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "group": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "description": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "operational",
                              "coming_soon"
                            ]
                          }
                        },
                        "required": [
                          "endpoint",
                          "path",
                          "group",
                          "description",
                          "status"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "product",
                    "total",
                    "live",
                    "planned",
                    "generatedAt",
                    "sources"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/status/sports": {
      "get": {
        "summary": "Per-league health for the shared sports-scores catalog: status, live-game count, consecutive failures, last poll — the same per-source pattern as /v1/status/feeds.",
        "description": "Per-league health for the shared sports-scores catalog: status, live-game count, consecutive failures, last poll — the same per-source pattern as /v1/status/feeds.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_v1_status_sports",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "description": "Enabled leagues only.",
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "counts": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "errored": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "dead": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            }
                          },
                          "required": [
                            "active",
                            "errored",
                            "dead"
                          ],
                          "additionalProperties": false
                        },
                        "healthyPct": {
                          "type": "number"
                        },
                        "liveGames": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        "lastPolledAt": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "generatedAt": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "total",
                        "counts",
                        "healthyPct",
                        "liveGames",
                        "lastPolledAt",
                        "generatedAt"
                      ],
                      "additionalProperties": false
                    },
                    "leagues": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "sport": {
                            "type": "string"
                          },
                          "source": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "errored",
                              "dead"
                            ]
                          },
                          "liveGames": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          },
                          "consecutiveFailures": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 9007199254740991
                          },
                          "lastError": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lastPolledAt": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "nextPollAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "slug",
                          "name",
                          "sport",
                          "source",
                          "status",
                          "liveGames",
                          "consecutiveFailures",
                          "lastError",
                          "lastPolledAt",
                          "nextPollAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "summary",
                    "leagues"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "summary": "The entire platform as an OpenAPI 3 document — import into Postman or generate a client.",
        "description": "The entire platform as an OpenAPI 3 document — import into Postman or generate a client.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_v1_openapi.json",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "The full OpenAPI 3.1 document, generated from PRODUCTS + this schema registry (see lib/openapi.ts), returned directly (not wrapped in the `{data}` envelope — the OpenAPI convention). Not modeled field-by-field — it's self-referential with respect to this very registry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "summary": "The docs as an llmstxt.org index — point an LLM at this instead of scraping the website.",
        "description": "The docs as an llmstxt.org index — point an LLM at this instead of scraping the website.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_llms.txt",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "The llmstxt.org-convention index: live/coming-soon product lists plus links to the full reference, OpenAPI spec, and catalog JSON.",
            "content": {
              "text/plain; charset=utf-8": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "summary": "The entire platform reference as one LLM-readable markdown file — every product, every endpoint, schemas and runnable examples included.",
        "description": "The entire platform reference as one LLM-readable markdown file — every product, every endpoint, schemas and runnable examples included.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "get_llms-full.txt",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "responses": {
          "200": {
            "description": "The entire platform reference as one markdown document — every product, every endpoint, schemas and runnable examples included (see lib/llmsFull.ts).",
            "content": {
              "text/plain; charset=utf-8": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "A Streamable-HTTP MCP server: search_docs, get_product, and get_endpoint read the same catalog as the docs site and are keyless; try_endpoint calls a real endpoint on your behalf, forwarding this request's own Authorization header — no separate credential needed.",
        "description": "A Streamable-HTTP MCP server: search_docs, get_product, and get_endpoint read the same catalog as the docs site and are keyless; try_endpoint calls a real endpoint on your behalf, forwarding this request's own Authorization header — no separate credential needed.",
        "tags": [
          "Platform",
          "Platform: Health"
        ],
        "operationId": "post_mcp",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Health",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "description": "A JSON-RPC 2.0 message (initialize | tools/list | tools/call).",
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {}
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "description": "A JSON-RPC 2.0 response (or an array of them for a batch request) — shape depends on the message's own method.",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/device": {
      "post": {
        "summary": "Start the CLI device-code flow: returns a user code + verification URL.",
        "description": "Start the CLI device-code flow: returns a user code + verification URL.",
        "tags": [
          "Platform",
          "Platform: Device auth"
        ],
        "operationId": "post_v1_auth_device",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Device auth",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "device_code": {
                      "description": "Opaque code the CLI polls with. Never shown to the user.",
                      "type": "string"
                    },
                    "user_code": {
                      "description": "Human-typeable code, format \"XXXX-XXXX\", shown to the user.",
                      "type": "string"
                    },
                    "verification_uri": {
                      "description": "Where the user enters `user_code` to approve the request.",
                      "type": "string"
                    },
                    "expires_in": {
                      "description": "Seconds until the code expires (900 = 15 minutes).",
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "interval": {
                      "description": "Recommended poll interval, in seconds.",
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "device_code",
                    "user_code",
                    "verification_uri",
                    "expires_in",
                    "interval"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/device/poll": {
      "post": {
        "summary": "Poll the device flow; once the code is approved at /device, returns a fresh API key.",
        "description": "Poll the device flow; once the code is approved at /device, returns a fresh API key.",
        "tags": [
          "Platform",
          "Platform: Device auth"
        ],
        "operationId": "post_v1_auth_device_poll",
        "security": [],
        "x-cheapass-product": "platform",
        "x-cheapass-group": "Device auth",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "description": "Either field name is accepted (device_code takes precedence); the handler parses this by hand rather than through the shared validator — see file header.",
                "type": "object",
                "properties": {
                  "device_code": {
                    "description": "The device_code from POST /v1/auth/device. Checked first if both fields are present.",
                    "type": "string"
                  },
                  "deviceCode": {
                    "description": "Accepted camelCase alias for device_code.",
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "device_code": "<deviceCode>"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "claimed",
                        "denied",
                        "expired",
                        "invalid"
                      ]
                    },
                    "apiKey": {
                      "description": "The freshly minted raw API key. Present only when status is \"claimed\" — one-shot, never retrievable again.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/gate": {
      "get": {
        "summary": "List your gates (never returns password hashes or secrets).",
        "description": "List your gates (never returns password hashes or secrets).",
        "tags": [
          "Gate",
          "Gate: Gates"
        ],
        "operationId": "get_v1_gate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Gates",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Gate id — the public identifier used in /v1/gate/check.",
                        "type": "string"
                      },
                      "slug": {
                        "description": "URL-safe identifier.",
                        "type": "string"
                      },
                      "label": {
                        "description": "Human-friendly name.",
                        "type": "string"
                      },
                      "ttlSeconds": {
                        "description": "Unlock lifetime in seconds.",
                        "type": "number"
                      },
                      "createdAt": {
                        "description": "Creation time, ISO-8601.",
                        "type": "string"
                      },
                      "updatedAt": {
                        "description": "Last update time, ISO-8601.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "slug",
                      "label",
                      "ttlSeconds",
                      "createdAt",
                      "updatedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a gate. Returns the signing secret ONCE — store it to verify tokens offline.",
        "description": "Create a gate. Returns the signing secret ONCE — store it to verify tokens offline.\n\n**Example:**\n\n```\n{ \"id\": \"…\", \"slug\": \"escher-preview\", \"signingSecret\": \"gsk_…\", \"ttlSeconds\": 604800 }\n```",
        "tags": [
          "Gate",
          "Gate: Gates"
        ],
        "operationId": "post_v1_gate",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Gates",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "slug": {
                    "description": "URL-safe identifier for the gate, unique within your account (e.g. \"escher-preview\").",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "pattern": "^[a-z0-9][a-z0-9-]*$"
                  },
                  "password": {
                    "description": "The shared password visitors will enter.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "label": {
                    "description": "Human-friendly name shown in the dashboard.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "ttlSeconds": {
                    "description": "How long an unlocked visitor stays unlocked (default 7 days).",
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 7776000
                  }
                },
                "required": [
                  "slug",
                  "password"
                ],
                "additionalProperties": false
              },
              "example": {
                "slug": "escher-preview",
                "password": "hunter2",
                "label": "Escher preview builds"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Gate id — the public identifier used in /v1/gate/check.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "URL-safe identifier.",
                      "type": "string"
                    },
                    "label": {
                      "description": "Human-friendly name.",
                      "type": "string"
                    },
                    "ttlSeconds": {
                      "description": "Unlock lifetime in seconds.",
                      "type": "number"
                    },
                    "createdAt": {
                      "description": "Creation time, ISO-8601.",
                      "type": "string"
                    },
                    "updatedAt": {
                      "description": "Last update time, ISO-8601.",
                      "type": "string"
                    },
                    "signingSecret": {
                      "description": "HMAC signing secret (\"gsk_…\") — shown ONCE. Store it to verify tokens offline; rotate to reissue.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "label",
                    "ttlSeconds",
                    "createdAt",
                    "updatedAt",
                    "signingSecret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/gate/{id}": {
      "patch": {
        "summary": "Change the password, label, token lifetime, or rotate the signing secret.",
        "description": "Change the password, label, token lifetime, or rotate the signing secret.",
        "tags": [
          "Gate",
          "Gate: Gates"
        ],
        "operationId": "patch_v1_gate__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Gates",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Gate id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "password": {
                    "description": "Set a new shared password.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "label": {
                    "description": "Rename the gate.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "ttlSeconds": {
                    "description": "Change the unlock lifetime.",
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 7776000
                  },
                  "rotateSecret": {
                    "description": "Issue a new signing secret (invalidates all outstanding tokens).",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "ttlSeconds": 3600
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "description": "Gate id — the public identifier used in /v1/gate/check.",
                      "type": "string"
                    },
                    "slug": {
                      "description": "URL-safe identifier.",
                      "type": "string"
                    },
                    "label": {
                      "description": "Human-friendly name.",
                      "type": "string"
                    },
                    "ttlSeconds": {
                      "description": "Unlock lifetime in seconds.",
                      "type": "number"
                    },
                    "createdAt": {
                      "description": "Creation time, ISO-8601.",
                      "type": "string"
                    },
                    "updatedAt": {
                      "description": "Last update time, ISO-8601.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "slug",
                    "label",
                    "ttlSeconds",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a gate. Any tokens it minted stop verifying.",
        "description": "Delete a gate. Any tokens it minted stop verifying.",
        "tags": [
          "Gate",
          "Gate: Gates"
        ],
        "operationId": "delete_v1_gate__id",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Gates",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Gate id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/gate/check": {
      "post": {
        "summary": "PUBLIC (no API key): exchange the shared password for a signed access token.",
        "description": "PUBLIC (no API key): exchange the shared password for a signed access token.\n\n**Example:**\n\n```\n{ \"token\": \"eyJ….sig\", \"expiresAt\": 1765000000000 }\n```",
        "tags": [
          "Gate",
          "Gate: Unlock"
        ],
        "operationId": "post_v1_gate_check",
        "security": [],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Unlock",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "gate": {
                    "description": "The gate id to unlock.",
                    "type": "string",
                    "minLength": 1
                  },
                  "password": {
                    "description": "The shared password.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  }
                },
                "required": [
                  "gate",
                  "password"
                ],
                "additionalProperties": false
              },
              "example": {
                "gate": "gate_id_here",
                "password": "hunter2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "token": {
                      "description": "Signed access token — present it to the protected site.",
                      "type": "string"
                    },
                    "expiresAt": {
                      "description": "Token expiry, ms since epoch.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "token",
                    "expiresAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/v1/gate/verify": {
      "post": {
        "summary": "PUBLIC (no API key): server-side token verification for sites that don't hold the secret.",
        "description": "PUBLIC (no API key): server-side token verification for sites that don't hold the secret.\n\n**Example:**\n\n```\n{ \"valid\": true, \"expiresAt\": 1765000000000 }\n```",
        "tags": [
          "Gate",
          "Gate: Unlock"
        ],
        "operationId": "post_v1_gate_verify",
        "security": [],
        "x-cheapass-product": "gate",
        "x-cheapass-group": "Unlock",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "gate": {
                    "description": "The gate id the token was minted for.",
                    "type": "string",
                    "minLength": 1
                  },
                  "token": {
                    "description": "A token previously returned by /v1/gate/check.",
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "gate",
                  "token"
                ],
                "additionalProperties": false
              },
              "example": {
                "gate": "gate_id_here",
                "token": "eyJ….sig"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "valid": {
                      "description": "Whether the token is authentic and unexpired.",
                      "type": "boolean"
                    },
                    "expiresAt": {
                      "description": "Token expiry, ms since epoch, when valid.",
                      "type": "number"
                    }
                  },
                  "required": [
                    "valid"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer <api key>"
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  }
}