{
  "openapi": "3.1.0",
  "info": {
    "title": "StreamRank API",
    "version": "1.0.0",
    "summary": "Daily breakout picks: titles heating up on zero streaming Top 10s, plus the Top 10s we score them against. Plain JSON over HTTPS. Optional Bearer API key.",
    "description": "StreamRank publishes a daily list of titles that are heating up and are not on a Top 10 yet, with a measured hit rate against the next two weeks of charts. The same API serves those Top 10s for Netflix, Prime Video, Disney+, HBO Max, Hulu, Apple TV, Paramount+, Peacock, and Starz.\n\nRequests without a key run in the sample scope: country=US; provider=netflix; current charts only. Send `Authorization: Bearer sk_live_…` for your plan. A free account's live key reads every country and provider with 7 days of history; show a visible link to StreamRank wherever you display its data. Test keys (`sk_test_…`) stay in the sample scope and never count toward quota.\n\nThis is a daily pick list plus Top 10 charts, not a catalog of everything on a service. Picks and charts update once a day. Cache them.\n\nIdentifiers: provider ids are lowercase (`netflix`, not `Netflix`). Countries are ISO 3166-1 alpha-2 (`US`, not `USA`). Look up a title with `GET /v1/titles?q=` or `imdb_id` / `tmdb_id`. Title ids look like `ttl_…`.\n\nHuman docs: https://streamrank.io/docs\nMarkdown: https://streamrank.io/docs.md\nThis document: https://streamrank.io/v1/openapi.json"
  },
  "servers": [
    {
      "url": "https://streamrank.io",
      "description": "StreamRank"
    }
  ],
  "security": [
    {},
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Charts"
    },
    {
      "name": "Titles"
    },
    {
      "name": "Trending"
    },
    {
      "name": "Catalog"
    }
  ],
  "paths": {
    "/v1/charts": {
      "get": {
        "operationId": "getCharts",
        "summary": "Current or historical Top 10",
        "description": "The Top 10 for one provider in one country. Omit `type` to receive both the movie and TV charts in one response.",
        "tags": [
          "Charts"
        ],
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": true,
            "description": "Required. netflix, prime, disney, max, hulu, apple, paramount, peacock, starz.",
            "schema": {
              "type": "string",
              "enum": [
                "netflix",
                "prime",
                "disney",
                "max",
                "hulu",
                "apple",
                "paramount",
                "peacock",
                "starz"
              ]
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "Required. ISO 3166-1 alpha-2, e.g. US, GB, JP.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional. Return one chart instead of both.",
            "schema": {
              "type": "string",
              "enum": [
                "movie",
                "tv"
              ]
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Optional. A past chart. Resolves to the newest chart on or before the date. Requires history on your plan.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Return only the top N.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/titles": {
      "get": {
        "operationId": "searchTitles",
        "summary": "Look up titles by name, IMDb id, or TMDB id",
        "description": "Returns a ranked list. Ambiguous names are not a 404. Then call GET /v1/titles/{id} for current positions. At least one of q, imdb_id, or tmdb_id is required.",
        "tags": [
          "Titles"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Name, slug, ttl_ id, IMDb id, or TMDB id. Required unless imdb_id or tmdb_id is set.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "imdb_id",
            "in": "query",
            "required": false,
            "description": "Exact IMDb id, e.g. tt4574334.",
            "schema": {
              "type": "string",
              "pattern": "^tt\\d{7,}$"
            }
          },
          {
            "name": "tmdb_id",
            "in": "query",
            "required": false,
            "description": "Exact TMDB id. Pass type when a movie and a show share the number.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional. Restrict results to one kind.",
            "schema": {
              "type": "string",
              "enum": [
                "movie",
                "tv"
              ]
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Optional. Prefer titles released this year when matching by name.",
            "schema": {
              "type": "integer",
              "minimum": 1870,
              "maximum": 2100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Default 10.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/titles/{id}": {
      "get": {
        "operationId": "getTitle",
        "summary": "Canonical title, current positions, lifetime stats",
        "description": "Accepts a title id (`ttl_…`), slug, IMDb id, or TMDB id. TMDB ids that match both a movie and a show should use GET /v1/titles?tmdb_id=&type= instead. Returns where it sits on every current chart plus lifetime stats.",
        "tags": [
          "Titles"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Title id (`ttl_…`), slug, IMDb id, or numeric TMDB id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/titles/{id}/rankings": {
      "get": {
        "operationId": "getTitleRankings",
        "summary": "Day-by-day ranking history",
        "description": "Newest first, clamped to your plan's history window.",
        "tags": [
          "Titles"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Title id (`ttl_…`) or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "description": "Optional filter.",
            "schema": {
              "type": "string",
              "enum": [
                "netflix",
                "prime",
                "disney",
                "max",
                "hulu",
                "apple",
                "paramount",
                "peacock",
                "starz"
              ]
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional filter.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Optional start date.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Optional end date.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Default 1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/trending": {
      "get": {
        "operationId": "getTrending",
        "summary": "Risers, new entries, longest streaks",
        "description": "Movement inside one provider's charts in one country: `biggest_risers`, `new_entries`, and `longest_streaks`. It compares a chart with itself, so a #1 on Apple TV and a #5 on Netflix are not comparable. For one list that ranks titles across every service, use GET /v1/trending/titles.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": true,
            "description": "Required.",
            "schema": {
              "type": "string",
              "enum": [
                "netflix",
                "prime",
                "disney",
                "max",
                "hulu",
                "apple",
                "paramount",
                "peacock",
                "starz"
              ]
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "Required. ISO 3166-1 alpha-2.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Items per bucket, default 5.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 5
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/trending/titles": {
      "get": {
        "operationId": "getTrendingTitles",
        "summary": "One cross-service trending list",
        "description": "Titles ranked across every service by a single trend score, 0–100. Three categories feed the score: `chart_momentum` (position, breadth, and movement across Top 10 charts inside the scope), `demand` (consumption and discovery intent: first-party activity is worldwide, discovery rankings follow the country scope and are summed on the global list), and `attention` (broad web attention: one worldwide feed, and reading per language that follows the country). Omit `country` for the global list; a country scope weights that country's Top 10 charts, discovery rankings, and reading in its language, while first-party demand stays worldwide. The score is daily. First-party demand counts cover the last complete day, attention is discounted when it is flat, and titles seen only by attention rank after titles with chart or demand presence.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional. ISO 3166-1 alpha-2. Omit it for the global list. A country scope weights that country's Top 10 charts, that country's discovery rankings, and reading in its language; first-party demand stays worldwide.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional. Restrict the list to movies or to shows.",
            "schema": {
              "type": "string",
              "enum": [
                "movie",
                "tv"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Optional. Keep only titles with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "rising",
                "steady",
                "peaking",
                "fading"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Default 10. Capped by your plan: 10 on Free, without a key, or with a test key; 100 on paid plans.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Optional. A past list. Resolves to the newest list on or before the date. Requires history on your plan.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/titles/{id}/trend": {
      "get": {
        "operationId": "getTitleTrend",
        "summary": "Day-by-day trend score for one title",
        "description": "The title's row on today's list plus its score history, newest first, clamped to your plan's history window. `current` is null when the title is not trending in that scope today.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Title id (`ttl_…`), slug, IMDb id, or numeric TMDB id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional. ISO 3166-1 alpha-2. Omit it for the global scope.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Optional start date. Clamped to your plan's history window.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Optional end date.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Days of history, default 90.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365,
              "default": 90
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/titles/{id}/signals": {
      "get": {
        "operationId": "getTitleSignals",
        "summary": "Day-by-day category detail for one title",
        "description": "What moved the score, one day per row, newest first. Each category carries its 0–100 level, how many independent feeds saw the title that day, and its growth against its own 7-day baseline (clipped log growth, −1 to 1). `chart_momentum` carries `charts`, the Top 10 charts the title sat on inside the scope that day. `threshold` is the demand level a title must reach to be a pick, so you can see the day it crossed. Feeds are counted, never named. `from` is clamped to your plan's history window.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Title id (`ttl_…`), slug, IMDb id, or numeric TMDB id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional. ISO 3166-1 alpha-2. Omit it for the global scope.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Optional start date. Clamped to your plan's history window.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Optional end date.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Days of history, default 90.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365,
              "default": 90
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/trending/breakouts": {
      "get": {
        "operationId": "getBreakouts",
        "summary": "Titles heating up on zero Top 10 charts",
        "description": "The daily breakout picks for a scope: titles on zero Top 10 charts inside the scope, on the list for more than a day, and off every chart for the previous 30 days (under any title of the same name), that reached demand 40 out of 100, or attention 50 with demand 20, or have a premiere, season start, or digital release inside the scope within 3 days with demand 20 or attention 40, or at any level when a tracked service in the scope is the title's home. An episode that airs within 21 days of the one before it continues a run and is not a release. Ten shows a day. A title with a known release more than 3 days out waits until the release is inside 3 days. Shows rank launches first (a release inside 3 days or in the 14 days before the pick), then originals on their own service, then titles landing within 3 days, then demand level. Inside each of those groups, fading titles go last, so a fading launch still ranks above a steady library show. Each item carries `strength`: `strong` for a launch, `watch` for the rest. A show picked five days running with no chart rests until something changes. Five movie picks a day are logged the same way, but only movie launches publish: a digital release or premiere inside 3 days on a tracked service the movie is made for. They rank first among movies and are returned with `type=movie`. Other movie picks charted at the rate of a random draw from the pool and stay in the ledger. On the worldwide scope, charts in Japan and South Korea do not count: they neither block a pick nor count as its outcome. Each item carries `why`, plain-language reasons built from the categories and release data, and `outcome` once the title charts. `track_record` counts calls, not pick days: a title picked on consecutive days (gaps up to 7 days) is one call dated from its first day. Top-level numbers cover the published types (`types`); `by_type` holds every type with its own `control`, and `by_strength` splits the published calls into strong and watch.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional. ISO 3166-1 alpha-2. Omit it for the global list. A country scope means zero Top 10 charts in that country.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional. Default `tv`, the published list. `movie` returns the movie picks, which are logged every day but not published while they chart at the control rate.",
            "schema": {
              "type": "string",
              "enum": [
                "movie",
                "tv"
              ],
              "default": "tv"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. 1–50, default 10, capped by your plan's trending limit. On a list younger than 14 days, Free, test keys, and calls without a key get the top pick and the rest is reported in `meta.locked`; paid plans get all of them. Lists 14 days old or older return in full for everyone.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Optional. The newest pick list on or before this date, inside your plan's history window.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/trending/breakouts/history": {
      "get": {
        "operationId": "getBreakoutHistory",
        "summary": "Every past pick and what happened to it",
        "description": "Past picks for a scope, newest day first and in list order inside a day. Shows by default; `type=movie` returns the published movie launches. Each item is a pick row with the day it was made, the reasons we gave, and the outcome we recorded: `outcome` once the title entered a Top 10 inside the scope within 30 days, `missed` once 14 days passed without one. `from` is clamped to your plan's history window instead of failing. Page with `limit` and `offset`; `meta.total` is the full count. On a list younger than 14 days, Free, test keys, and calls without a key get the top pick only.",
        "tags": [
          "Trending"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Optional. ISO 3166-1 alpha-2. Omit it for the global list.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional. Default `tv`, the published list. `movie` returns the movie picks, which are logged every day but not published while they chart at the control rate.",
            "schema": {
              "type": "string",
              "enum": [
                "movie",
                "tv"
              ],
              "default": "tv"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Optional start date. Clamped to your plan's history window.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Optional end date.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Optional. Picks per page, default 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Optional. Picks to skip, default 0. Page with `meta.total`.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/countries": {
      "get": {
        "operationId": "listCountries",
        "summary": "Countries with chart data",
        "description": "Every country with chart data and the providers available in each, plus whether your plan includes it.",
        "tags": [
          "Catalog"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    },
    "/v1/providers": {
      "get": {
        "operationId": "listProviders",
        "summary": "Providers and their countries",
        "description": "Every provider we cover, the countries that have data, and whether your plan includes it.",
        "tags": [
          "Catalog"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Body is `{ data }` and sometimes `{ meta }`."
          },
          "400": {
            "description": "invalid_request"
          },
          "401": {
            "description": "unauthorized"
          },
          "403": {
            "description": "plan_required"
          },
          "404": {
            "description": "not_found"
          },
          "429": {
            "description": "rate_limited or quota_exceeded"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "sk_live_… or sk_test_…. Omit the header to use the sample scope."
      }
    },
    "schemas": {
      "TitleSummary": {
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "type",
          "year",
          "tmdb_id",
          "imdb_id",
          "poster_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "ttl_5k2m9x1qzc7v"
            ]
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "movie",
              "tv"
            ]
          },
          "year": {
            "type": [
              "integer",
              "null"
            ]
          },
          "tmdb_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "imdb_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "poster_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Chart": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "movie",
              "tv"
            ]
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "rankings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RankingItem"
            }
          }
        }
      },
      "RankingItem": {
        "type": "object",
        "properties": {
          "rank": {
            "type": "integer"
          },
          "previous_rank": {
            "type": [
              "integer",
              "null"
            ]
          },
          "rank_change": {
            "type": [
              "integer",
              "null"
            ]
          },
          "is_new": {
            "type": "boolean"
          },
          "days_in_top_10": {
            "type": "integer"
          },
          "peak_rank": {
            "type": [
              "integer",
              "null"
            ]
          },
          "first_charted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "title": {
            "$ref": "#/components/schemas/TitleSummary"
          }
        }
      },
      "TrendSignals": {
        "type": "object",
        "description": "Each category is 0-100 within the scope and day, or null when the category had no data that day.",
        "required": [
          "chart_momentum",
          "demand",
          "attention"
        ],
        "properties": {
          "chart_momentum": {
            "type": [
              "number",
              "null"
            ],
            "description": "Position, breadth, and movement across Top 10 charts inside the scope."
          },
          "demand": {
            "type": [
              "number",
              "null"
            ],
            "description": "Consumption and discovery intent. First-party activity is worldwide; discovery rankings follow the country scope and are summed on the global list."
          },
          "attention": {
            "type": [
              "number",
              "null"
            ],
            "description": "Broad web attention, worldwide."
          }
        }
      },
      "ChartPosition": {
        "type": "object",
        "required": [
          "provider",
          "country",
          "type",
          "rank"
        ],
        "properties": {
          "provider": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "movie",
              "tv"
            ]
          },
          "rank": {
            "type": "integer"
          }
        }
      },
      "TrendItem": {
        "type": "object",
        "properties": {
          "rank": {
            "type": "integer"
          },
          "previous_rank": {
            "type": [
              "integer",
              "null"
            ]
          },
          "rank_change": {
            "type": [
              "integer",
              "null"
            ]
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "previous_score": {
            "type": [
              "number",
              "null"
            ]
          },
          "score_change": {
            "type": [
              "number",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "rising",
              "steady",
              "peaking",
              "fading"
            ]
          },
          "chart_count": {
            "type": "integer",
            "description": "Top 10 charts inside the scope today, counted before plan filtering."
          },
          "on_charts": {
            "type": "array",
            "description": "Today's positions, filtered to the countries and providers your plan includes.",
            "items": {
              "$ref": "#/components/schemas/ChartPosition"
            }
          },
          "signals": {
            "$ref": "#/components/schemas/TrendSignals"
          },
          "title": {
            "$ref": "#/components/schemas/TitleSummary"
          }
        }
      },
      "TrendPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "rank": {
            "type": "integer"
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "rising",
              "steady",
              "peaking",
              "fading"
            ]
          },
          "chart_count": {
            "type": "integer"
          },
          "signals": {
            "$ref": "#/components/schemas/TrendSignals"
          }
        }
      },
      "SignalCategory": {
        "type": "object",
        "description": "One category on one day. Feeds are counted, never named.",
        "required": [
          "value",
          "feeds",
          "growth"
        ],
        "properties": {
          "value": {
            "type": [
              "number",
              "null"
            ],
            "description": "Category score, 0-100, or null when the category had no data that day."
          },
          "feeds": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Independent feeds behind the category that day, or null when not recorded."
          },
          "growth": {
            "type": [
              "number",
              "null"
            ],
            "minimum": -1,
            "maximum": 1,
            "description": "Clipped log growth against the category's own 7-day baseline, or null with no baseline."
          }
        }
      },
      "SignalPoint": {
        "type": "object",
        "description": "One day of category detail behind a title's trend score.",
        "required": [
          "date",
          "chart_momentum",
          "demand",
          "attention"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "chart_momentum": {
            "type": "object",
            "required": [
              "value",
              "charts"
            ],
            "properties": {
              "value": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "charts": {
                "type": "integer",
                "description": "Top 10 charts the title sat on inside the scope that day."
              }
            }
          },
          "demand": {
            "$ref": "#/components/schemas/SignalCategory"
          },
          "attention": {
            "$ref": "#/components/schemas/SignalCategory"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "rate_limited",
                  "quota_exceeded",
                  "plan_required",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "examples": [
          {
            "error": {
              "code": "plan_required",
              "message": "Country \"JP\" is not included in the sample scope without an API key.",
              "details": {
                "param": "country",
                "requested": "JP",
                "allowed_countries": [
                  "US"
                ],
                "hint": "Use country=US, or send a key for a plan that includes JP.",
                "upgrade_url": "https://streamrank.io/pricing",
                "docs_url": "https://streamrank.io/docs.md#authentication"
              }
            }
          }
        ]
      }
    },
    "examples": {
      "Chart": {
        "value": {
          "data": {
            "provider": "netflix",
            "country": "US",
            "type": "movie",
            "date": "2026-09-10",
            "updated_at": "2026-09-10T22:49:43.000Z",
            "rankings": [
              {
                "rank": 1,
                "previous_rank": 3,
                "rank_change": 2,
                "is_new": false,
                "days_in_top_10": 8,
                "peak_rank": 1,
                "first_charted_at": "2026-09-03",
                "title": {
                  "id": "ttl_5k2m9x1qzc7v",
                  "slug": "the-whisper-man-2026",
                  "name": "The Whisper Man",
                  "type": "movie",
                  "year": 2026,
                  "tmdb_id": 860508,
                  "imdb_id": "tt11561116",
                  "poster_url": "https://image.tmdb.org/t/p/w500/….jpg"
                }
              }
            ]
          }
        }
      },
      "TitleSearch": {
        "value": {
          "data": [
            {
              "id": "ttl_5k2m9x1qzc7v",
              "slug": "the-whisper-man-2026",
              "name": "The Whisper Man",
              "type": "movie",
              "year": 2026,
              "tmdb_id": 860508,
              "imdb_id": "tt11561116",
              "poster_url": "https://image.tmdb.org/t/p/w500/….jpg",
              "match": "name"
            }
          ],
          "meta": {
            "count": 1
          }
        }
      },
      "Title": {
        "value": {
          "data": {
            "id": "ttl_5k2m9x1qzc7v",
            "slug": "the-whisper-man-2026",
            "name": "The Whisper Man",
            "type": "movie",
            "year": 2026,
            "tmdb_id": 860508,
            "imdb_id": "tt11561116",
            "poster_url": "https://image.tmdb.org/t/p/w500/….jpg",
            "overview": "…",
            "backdrop_url": "https://image.tmdb.org/t/p/original/….jpg",
            "current_rankings": [
              {
                "date": "2026-09-10",
                "provider": "netflix",
                "country": "US",
                "type": "movie",
                "rank": 1,
                "previous_rank": 3,
                "rank_change": 2,
                "days_in_top_10": 8,
                "peak_rank": 1
              }
            ],
            "stats": {
              "total_top_10_days": 8,
              "peak_rank": 1,
              "days_at_number_one": 3,
              "countries_charted": 1,
              "first_charted_at": "2026-09-03",
              "last_charted_at": "2026-09-10"
            }
          }
        }
      },
      "TitleRankings": {
        "value": {
          "data": [
            {
              "date": "2026-09-10",
              "provider": "netflix",
              "country": "US",
              "type": "movie",
              "rank": 3,
              "previous_rank": 1,
              "rank_change": -2,
              "days_in_top_10": 13,
              "peak_rank": 1
            }
          ],
          "meta": {
            "title_id": "ttl_5k2m9x1qzc7v",
            "from": "2026-08-11",
            "to": "2026-09-10",
            "history_days": 30
          }
        }
      },
      "TrendingTitles": {
        "value": {
          "data": {
            "scope": "global",
            "date": "2026-09-10",
            "items": [
              {
                "rank": 1,
                "previous_rank": 4,
                "rank_change": 3,
                "score": 92.6,
                "previous_score": 81.4,
                "score_change": 11.2,
                "status": "rising",
                "chart_count": 9,
                "on_charts": [
                  {
                    "provider": "netflix",
                    "country": "US",
                    "type": "movie",
                    "rank": 1
                  },
                  {
                    "provider": "netflix",
                    "country": "GB",
                    "type": "movie",
                    "rank": 2
                  }
                ],
                "signals": {
                  "chart_momentum": 96.1,
                  "demand": 88.3,
                  "attention": 90.7
                },
                "title": {
                  "id": "ttl_5k2m9x1qzc7v",
                  "slug": "the-whisper-man-2026",
                  "name": "The Whisper Man",
                  "type": "movie",
                  "year": 2026,
                  "tmdb_id": 860508,
                  "imdb_id": "tt11561116",
                  "poster_url": "https://image.tmdb.org/t/p/w500/….jpg"
                }
              }
            ]
          },
          "meta": {
            "count": 1,
            "limit_max": 10,
            "history_days": 0
          }
        }
      },
      "TitleTrend": {
        "value": {
          "data": {
            "title_id": "ttl_5k2m9x1qzc7v",
            "scope": "US",
            "current": {
              "scope": "US",
              "date": "2026-09-10",
              "rank": 2,
              "previous_rank": 5,
              "rank_change": 3,
              "score": 90.1,
              "previous_score": 78.9,
              "score_change": 11.2,
              "status": "rising",
              "chart_count": 3,
              "signals": {
                "chart_momentum": 94,
                "demand": 86.2,
                "attention": 88.5
              }
            },
            "history": [
              {
                "date": "2026-09-10",
                "rank": 2,
                "score": 90.1,
                "status": "rising",
                "chart_count": 3,
                "signals": {
                  "chart_momentum": 94,
                  "demand": 86.2,
                  "attention": 88.5
                }
              },
              {
                "date": "2026-09-09",
                "rank": 5,
                "score": 78.9,
                "status": "new",
                "chart_count": 2,
                "signals": {
                  "chart_momentum": 81.3,
                  "demand": 74,
                  "attention": null
                }
              }
            ]
          },
          "meta": {
            "from": "2026-08-11",
            "to": "2026-09-10",
            "history_days": 30
          }
        }
      },
      "Breakouts": {
        "value": {
          "data": {
            "scope": "US",
            "date": "2026-09-15",
            "items": [
              {
                "position": 1,
                "score": 45.4,
                "score_change": 5.2,
                "status": "rising",
                "signals": {
                  "chart_momentum": 0,
                  "demand": 83.1,
                  "attention": 45.2
                },
                "why": [
                  "Lands Sep 19 on Netflix.",
                  "Demand 83 of 100.",
                  "Score up 5.2 today.",
                  "On no Top 10 in United States."
                ],
                "strength": "strong",
                "premiere": "2026-09-19",
                "providers": [
                  "netflix"
                ],
                "outcome": {
                  "first_chart_date": "2026-09-20",
                  "first_chart_provider": "netflix",
                  "first_chart_country": "US",
                  "first_chart_rank": 4,
                  "days_to_chart": 5,
                  "peak_rank": 2,
                  "days_on_chart": 6
                },
                "missed": false,
                "title": {
                  "id": "ttl_9q2h7v3zkm1d",
                  "slug": "obsession-2026",
                  "name": "Obsession",
                  "type": "movie",
                  "year": 2026,
                  "tmdb_id": 1364532,
                  "imdb_id": "tt31520893",
                  "poster_url": "https://image.tmdb.org/t/p/w500/obsession.jpg"
                }
              }
            ],
            "track_record": {
              "scope": "US",
              "from": "2026-08-02",
              "to": "2026-08-31",
              "window_days": 14,
              "long_window_days": 30,
              "types": [
                "tv"
              ],
              "picks": 96,
              "charted_7d": 29,
              "charted_14d": 41,
              "hit_rate_14d": 42.7,
              "median_days_to_chart": 4,
              "median_peak_rank": 3,
              "median_days_on_chart": 7,
              "picks_30d": 45,
              "charted_30d": 21,
              "hit_rate_30d": 46.7,
              "pool": 640,
              "pool_charted_14d": 122,
              "pool_hit_rate_14d": 19.1,
              "pool_30d": 300,
              "pool_charted_30d": 66,
              "pool_hit_rate_30d": 22,
              "by_type": {
                "tv": {
                  "picks": 96,
                  "charted_7d": 29,
                  "charted_14d": 41,
                  "hit_rate_14d": 42.7,
                  "median_days_to_chart": 4,
                  "median_peak_rank": 3,
                  "median_days_on_chart": 7,
                  "picks_30d": 45,
                  "charted_30d": 21,
                  "hit_rate_30d": 46.7,
                  "pool": 640,
                  "pool_charted_14d": 122,
                  "pool_hit_rate_14d": 19.1,
                  "pool_30d": 300,
                  "pool_charted_30d": 66,
                  "pool_hit_rate_30d": 22,
                  "control": {
                    "picks": 150,
                    "charted_7d": 9,
                    "charted_14d": 16,
                    "hit_rate_14d": 10.7,
                    "median_days_to_chart": 7,
                    "median_peak_rank": 7,
                    "median_days_on_chart": 2,
                    "picks_30d": 70,
                    "charted_30d": 11,
                    "hit_rate_30d": 15.7,
                    "pool": 640,
                    "pool_charted_14d": 122,
                    "pool_hit_rate_14d": 19.1,
                    "pool_30d": 300,
                    "pool_charted_30d": 66,
                    "pool_hit_rate_30d": 22
                  }
                },
                "movie": {
                  "picks": 104,
                  "charted_7d": 6,
                  "charted_14d": 9,
                  "hit_rate_14d": 8.7,
                  "median_days_to_chart": 9,
                  "median_peak_rank": 6,
                  "median_days_on_chart": 3,
                  "picks_30d": 50,
                  "charted_30d": 8,
                  "hit_rate_30d": 16,
                  "pool": 1570,
                  "pool_charted_14d": 76,
                  "pool_hit_rate_14d": 4.8,
                  "pool_30d": 730,
                  "pool_charted_30d": 88,
                  "pool_hit_rate_30d": 12.1,
                  "control": {
                    "picks": 150,
                    "charted_7d": 6,
                    "charted_14d": 11,
                    "hit_rate_14d": 7.3,
                    "median_days_to_chart": 8,
                    "median_peak_rank": 8,
                    "median_days_on_chart": 2,
                    "picks_30d": 70,
                    "charted_30d": 9,
                    "hit_rate_30d": 12.9,
                    "pool": 1570,
                    "pool_charted_14d": 76,
                    "pool_hit_rate_14d": 4.8,
                    "pool_30d": 730,
                    "pool_charted_30d": 88,
                    "pool_hit_rate_30d": 12.1
                  }
                }
              },
              "by_strength": {
                "strong": {
                  "picks": 30,
                  "charted_7d": 12,
                  "charted_14d": 16,
                  "hit_rate_14d": 53.3,
                  "median_days_to_chart": 3,
                  "median_peak_rank": 2,
                  "median_days_on_chart": 9,
                  "picks_30d": 14,
                  "charted_30d": 8,
                  "hit_rate_30d": 57.1,
                  "pool": 640,
                  "pool_charted_14d": 122,
                  "pool_hit_rate_14d": 19.1,
                  "pool_30d": 300,
                  "pool_charted_30d": 66,
                  "pool_hit_rate_30d": 22
                },
                "watch": {
                  "picks": 66,
                  "charted_7d": 17,
                  "charted_14d": 25,
                  "hit_rate_14d": 37.9,
                  "median_days_to_chart": 5,
                  "median_peak_rank": 4,
                  "median_days_on_chart": 6,
                  "picks_30d": 31,
                  "charted_30d": 13,
                  "hit_rate_30d": 41.9,
                  "pool": 640,
                  "pool_charted_14d": 122,
                  "pool_hit_rate_14d": 19.1,
                  "pool_30d": 300,
                  "pool_charted_30d": 66,
                  "pool_hit_rate_30d": 22
                }
              },
              "control": {
                "picks": 150,
                "charted_7d": 9,
                "charted_14d": 16,
                "hit_rate_14d": 10.7,
                "median_days_to_chart": 7,
                "median_peak_rank": 7,
                "median_days_on_chart": 2,
                "picks_30d": 70,
                "charted_30d": 11,
                "hit_rate_30d": 15.7,
                "pool": 640,
                "pool_charted_14d": 122,
                "pool_hit_rate_14d": 19.1,
                "pool_30d": 300,
                "pool_charted_30d": 66,
                "pool_hit_rate_30d": 22
              }
            }
          },
          "meta": {
            "count": 1,
            "locked": 0,
            "limit_max": 10,
            "history_days": 30
          }
        }
      },
      "BreakoutHistory": {
        "value": {
          "data": {
            "scope": "US",
            "from": "2026-08-16",
            "to": "2026-09-15",
            "items": [
              {
                "date": "2026-09-15",
                "position": 1,
                "score": 45.4,
                "score_change": 5.2,
                "status": "rising",
                "signals": {
                  "chart_momentum": 0,
                  "demand": 83.1,
                  "attention": 45.2
                },
                "why": [
                  "Lands Sep 19 on Netflix.",
                  "Demand 83 of 100.",
                  "Score up 5.2 today.",
                  "On no Top 10 in United States."
                ],
                "strength": "strong",
                "premiere": "2026-09-19",
                "providers": [
                  "netflix"
                ],
                "outcome": {
                  "first_chart_date": "2026-09-20",
                  "first_chart_provider": "netflix",
                  "first_chart_country": "US",
                  "first_chart_rank": 4,
                  "days_to_chart": 5,
                  "peak_rank": 2,
                  "days_on_chart": 6
                },
                "missed": false,
                "title": {
                  "id": "ttl_9q2h7v3zkm1d",
                  "slug": "obsession-2026",
                  "name": "Obsession",
                  "type": "movie",
                  "year": 2026,
                  "tmdb_id": 1364532,
                  "imdb_id": "tt31520893",
                  "poster_url": "https://image.tmdb.org/t/p/w500/obsession.jpg"
                }
              }
            ]
          },
          "meta": {
            "count": 1,
            "total": 310,
            "limit": 100,
            "offset": 0,
            "history_days": 30
          }
        }
      },
      "TitleSignals": {
        "value": {
          "data": {
            "title_id": "ttl_5k2m9x1qzc7v",
            "scope": "US",
            "threshold": 40,
            "history": [
              {
                "date": "2026-09-10",
                "chart_momentum": {
                  "value": 94,
                  "charts": 3
                },
                "demand": {
                  "value": 86.2,
                  "feeds": 2,
                  "growth": 0.31
                },
                "attention": {
                  "value": 88.5,
                  "feeds": 1,
                  "growth": 0.12
                }
              },
              {
                "date": "2026-09-09",
                "chart_momentum": {
                  "value": null,
                  "charts": 0
                },
                "demand": {
                  "value": 38.4,
                  "feeds": 1,
                  "growth": 0.44
                },
                "attention": {
                  "value": null,
                  "feeds": null,
                  "growth": null
                }
              }
            ]
          },
          "meta": {
            "from": "2026-08-11",
            "to": "2026-09-10",
            "history_days": 30
          }
        }
      },
      "Countries": {
        "value": {
          "data": [
            {
              "code": "US",
              "name": "United States",
              "providers": [
                "netflix",
                "prime",
                "disney",
                "max",
                "hulu",
                "apple",
                "paramount",
                "peacock",
                "starz"
              ],
              "included_in_plan": true
            }
          ]
        }
      },
      "Providers": {
        "value": {
          "data": [
            {
              "id": "netflix",
              "name": "Netflix",
              "countries": [
                "AU",
                "CA",
                "DE",
                "FR",
                "GB",
                "JP",
                "US"
              ],
              "included_in_plan": true
            },
            {
              "id": "prime",
              "name": "Prime Video",
              "countries": [
                "…"
              ],
              "included_in_plan": true
            }
          ]
        }
      },
      "Error": {
        "value": {
          "error": {
            "code": "plan_required",
            "message": "Country \"JP\" is not included in the sample scope without an API key.",
            "details": {
              "param": "country",
              "requested": "JP",
              "allowed_countries": [
                "US"
              ],
              "hint": "Use country=US, or send a key for a plan that includes JP.",
              "upgrade_url": "https://streamrank.io/pricing",
              "docs_url": "https://streamrank.io/docs.md#authentication"
            }
          }
        }
      }
    }
  }
}