# Build a "Where to Watch" feature in 50 lines with the StreamWatchHub API

> Source: <https://dev.to/kavelaltd/build-a-where-to-watch-feature-in-50-lines-with-the-streamwatchhub-api-5aob>
> Published: 2026-05-23 17:47:14+00:00

Most teams shipping a "where can I watch X?" feature run into the same set of problems:

- JustWatch does not offer a public API.
- TMDB watch-providers covers the major markets only, without rent prices or deep links.
- Live sports availability requires a separate broadcaster feed.
- Platform names, regional catalogs, and deep-link formats all need to be reconciled.

**StreamWatchHub** consolidates this into a single REST endpoint and one consistent schema, covering every streaming service plus live football broadcasters across 10 countries. The API is now live on [RapidAPI](https://rapidapi.com/kavela-kavela-default/api/streamwatchhub-movies-series/pricing) with a free tier (1,000 calls/month), so it can be evaluated without a payment method.

This post walks through wiring a production-ready "where to watch" feature in roughly 50 lines of Node.js plus a small React component.

## What the API returns

A single call per title, with the monetization type flagged on every offer:

```
curl "https://streamwatchhub.p.rapidapi.com/v1/search?q=the+bear&country=US" \
  -H "X-RapidAPI-Key: $KEY" \
  -H "X-RapidAPI-Host: streamwatchhub.p.rapidapi.com"
```

Response (trimmed):

```
{
  "results": [{
    "tmdb_id": 136315,
    "title": "The Bear",
    "type": "series",
    "year": 2022,
    "offers": [
      { "platform": "hulu",     "type": "flatrate", "url": "https://hulu.com/series/..." },
      { "platform": "disney",   "type": "flatrate", "url": "https://disneyplus.com/..." },
      { "platform": "apple",    "type": "rent",     "price": "$2.99", "url": "https://tv.apple.com/..." }
    ]
  }]
}
```

No per-platform SDKs, no scraping fallbacks. The same response shape applies to movies, series, and football matches — sports responses substitute `kickoff_at`

and `broadcasters[]`

for `offers[]`

.

## 1. Sign up and obtain an API key

- Visit the
[RapidAPI listing](https://rapidapi.com/kavela-kavela-default/api/streamwatchhub-movies-series/pricing)and select the free plan. - Copy the issued RapidAPI key and export it:
`export RAPIDAPI_KEY=...`

## 2. A minimal Node client

``` js
// swh.js
const HOST = "streamwatchhub.p.rapidapi.com";
const BASE = `https://${HOST}/v1`;

export async function whereToWatch(query, country = "US") {
  const url = new URL(`${BASE}/search`);
  url.searchParams.set("q", query);
  url.searchParams.set("country", country);

  const res = await fetch(url, {
    headers: {
      "X-RapidAPI-Key":  process.env.RAPIDAPI_KEY,
      "X-RapidAPI-Host": HOST,
    },
  });
  if (!res.ok) throw new Error(`SWH ${res.status}`);
  return res.json();
}
```

No client library is required. The full surface is seven GET endpoints (`/search`

, `/title/{id}/offers`

, `/series/{id}/season/{n}/offers`

, `/match/{id}/broadcasters`

, `/fixtures`

, `/platforms`

, `/changes`

).

## 3. A drop-in React component

``` js
import { useEffect, useState } from "react";
import { whereToWatch } from "./swh";

export function WhereToWatch({ title, country = "US" }) {
  const [data, setData] = useState(null);
  const [err,  setErr]  = useState(null);

  useEffect(() => {
    whereToWatch(title, country).then(setData).catch(setErr);
  }, [title, country]);

  if (err)        return <p>Couldn't load options.</p>;
  if (!data)      return <p>Loading…</p>;
  const hit = data.results?.[0];
  if (!hit)       return <p>No streaming match in {country}.</p>;

  return (
    <div>
      <h3>{hit.title} <small>({hit.year})</small></h3>
      <ul>
        {hit.offers.map((o, i) => (
          <li key={i}>
            <a href={o.url} target="_blank" rel="noopener">
              <strong>{o.platform}</strong> — {o.type}
              {o.price && <> · {o.price}</>}
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

Usage: `<WhereToWatch title="The Bear" country="US" />`

.

## Current coverage

-
**14,000+ titles**(movies and TV series), refreshed daily -
**70+ providers**— Netflix, Disney+, HBO Max, Apple TV, OSN+, Shahid, Movistar Plus+, Kinopoisk, Now TV, Sky Go, Paramount+, and others -
**10 countries** at launch — US, GB, DE, ES, IT, FR, TR, BR, IN, SA (more being added) -
**Live football**— 23 leagues including the Big Five plus UCL / UEL / UECL and the Saudi Pro League, with per-country broadcaster resolution (the same fixture airs on different channels in each market, and the API resolves the correct one) -
**Confidence scores** on broadcaster matches so low-confidence entries can be filtered out client-side -
**Deep links** that open the correct detail page on each platform

## Roadmap

- A dedicated
**Sports** RapidAPI listing is launching in the coming weeks; football fixtures are already accessible inside the current Movies & Series listing. - Additional countries are scheduled: Mexico, Argentina, Australia, Japan, and Korea.
- A natural-language
`/recommend`

endpoint is under evaluation ("where can I watch the Champions League final in Romania tonight?") — the team is still assessing whether it adds enough value beyond the structured endpoints.

## Try it

- 🌐 Landing and documentation:
[streamwatchhub.com/api](https://streamwatchhub.com/api/) - 💚 Free tier on RapidAPI:
[Movies & Series listing](https://rapidapi.com/kavela-kavela-default/api/streamwatchhub-movies-series/pricing) - 📦 Source examples (cURL, Node, Python, PHP):
[github.com/Kaveladev/streamwatchhub](https://github.com/Kaveladev/streamwatchhub)

Feedback is welcome before the v1 schema is frozen. One open question for readers: how should `confidence_score`

be exposed — as a raw number, a `low / medium / high`

enum, or hidden entirely below a threshold? Comments are appreciated.

Thanks for reading.
