# Episode guide API

> The episode guide API lists every episode of a series through GET /3/tv/{tv_id}/season/{season_number}. Each episode has a name, overview, air date, runtime and still image. The episode_groups list names alternate orders such as DVD or absolute. Paths and JSON match TMDB v3, so existing clients only need a new base URL.

## Get every episode of a season

`GET /3/tv/{tv_id}/season/{season_number}` returns a season with its full `episodes` array. Each episode has `episode_number`, `name`, `overview`, `air_date`, `runtime` and `still_path`. Ids are the numeric ids TMDB uses, for example `1396` for Breaking Bad.

You get seasons, episodes with dates and runtimes, stills, the next and last aired episode of a series, and the list of alternate episode orders. Text fields follow the `language` parameter, and an overview stays empty when no translation exists.

## What data you get

| Endpoint                                                            | Returns                                                                                        |
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `GET /3/tv/{tv_id}`                                                 | `seasons` summary, `number_of_seasons`, `status`, `next_episode_to_air`, `last_episode_to_air` |
| `GET /3/tv/{tv_id}/season/{season_number}`                          | One season with all its `episodes`                                                             |
| `GET /3/tv/{tv_id}/season/{season_number}/episode/{episode_number}` | One episode with `crew` and `guest_stars`                                                      |
| `GET /3/tv/{tv_id}/episode_groups`                                  | Name, `type` and episode count of each alternate order defined for the series                  |

Fields of an episode:

| Field                             | Type            | Notes                                                                                                               |
| --------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `id`, `show_id`                   | integer         | Episode id and series id. `show_id` is in season lists and in `next_episode_to_air`, not on the single episode path |
| `episode_number`, `season_number` | integer         | Position in the season                                                                                              |
| `episode_type`                    | string          | For example `standard`                                                                                              |
| `name`, `overview`                | string          | Localized with `language`                                                                                           |
| `air_date`                        | string or null  | `YYYY-MM-DD`, empty or null when not announced                                                                      |
| `runtime`                         | integer or null | Minutes                                                                                                             |
| `still_path`                      | string or null  | Join to `https://img.amodb.dev/t/p/{size}`                                                                          |
| `vote_average`, `vote_count`      | number, integer | Currently `0` on episodes                                                                                           |
| `production_code`                 | string          | Studio code, often empty                                                                                            |
| `crew`, `guest_stars`             | array           | People credited on the episode, with the same fields as a cast member                                               |

## Start in 3 steps

1. Choose a plan on [pricing](https://amodb.dev/pricing/). All plans return the same episode data, and only the request rate differs.
2. Create a key in your account dashboard and store it in an environment variable.
3. Request `/3/tv/{tv_id}/season/1` with the key as a Bearer header or as `api_key`.

## Example request

The sample fetches season 1 of Breaking Bad (series id `1396`) in English. The Go program decodes it into typed structs and prints one line per episode with the air date, the runtime and the still URL.

```bash
curl -s "https://api.amodb.dev/3/tv/1396/season/1?language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

type Episode struct {
	EpisodeNumber int     `json:"episode_number"`
	Name          string  `json:"name"`
	AirDate       string  `json:"air_date"`
	Runtime       int     `json:"runtime"`
	StillPath     *string `json:"still_path"`
}

type Season struct {
	Name         string    `json:"name"`
	SeasonNumber int       `json:"season_number"`
	Episodes     []Episode `json:"episodes"`
}

func main() {
	client := &http.Client{Timeout: 10 * time.Second}
	url := "https://api.amodb.dev/3/tv/1396/season/1?language=en-US"
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("amodb returned %s", res.Status))
	}
	var season Season
	if err := json.NewDecoder(res.Body).Decode(&season); err != nil {
		panic(err)
	}
	fmt.Println(season.Name)
	for _, e := range season.Episodes {
		still := "no still"
		if e.StillPath != nil {
			still = "https://img.amodb.dev/t/p/w300" + *e.StillPath
		}
		fmt.Printf("S%02dE%02d  %s  %3d min  %s  %s\n",
			season.SeasonNumber, e.EpisodeNumber, e.AirDate, e.Runtime, e.Name, still)
	}
}
```

Trimmed response: 2 of the 7 episodes, with one crew member and one guest star each.

```json
{
  "air_date": "2008-01-20",
  "episodes": [
    {
      "air_date": "2008-01-20",
      "episode_number": 1,
      "episode_type": "standard",
      "id": 62085,
      "name": "Pilot",
      "overview": "When an unassuming high school chemistry teacher discovers he has a rare form...",
      "production_code": "",
      "runtime": 59,
      "season_number": 1,
      "show_id": 1396,
      "still_path": "/ydlY3iPfeOAvu8gVqrxPoMvzNCn.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "crew": [
        {
          "department": "Camera",
          "job": "Director of Photography",
          "credit_id": "52b7029219c29533d00dd2c1",
          "adult": false,
          "gender": 2,
          "id": 2483,
          "known_for_department": "Camera",
          "name": "约翰·托尔",
          "original_name": "约翰·托尔",
          "popularity": 1.1957,
          "profile_path": "/cfL9A6tC7L5Ps5fq1o3WpVKGMb1.jpg"
        }
      ],
      "guest_stars": [
        {
          "character": "Steven Gomez",
          "credit_id": "5271b489760ee35b3e0881a7",
          "order": 8,
          "adult": false,
          "gender": 2,
          "id": 61535,
          "known_for_department": "Acting",
          "name": "史蒂文·迈克尔·奎扎达",
          "original_name": "史蒂文·迈克尔·奎扎达",
          "popularity": 1.7511,
          "profile_path": "/pVYrDkwI6GWvCNL2kJhpDJfBFyd.jpg"
        }
      ]
    },
    {
      "air_date": "2008-01-27",
      "episode_number": 2,
      "episode_type": "standard",
      "id": 62086,
      "name": "Cat's in the Bag...",
      "overview": "Walt and Jesse attempt to tie up loose ends. The desperate situation gets mor...",
      "production_code": "",
      "runtime": 49,
      "season_number": 1,
      "show_id": 1396,
      "still_path": "/AbMoecO0ZZio0LcgeLxlzdyGs6X.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "crew": [
        {
          "department": "Camera",
          "job": "Director of Photography",
          "credit_id": "52b7049c19c2953b63015013",
          "adult": false,
          "gender": 2,
          "id": 17948,
          "known_for_department": "Camera",
          "name": "Reynaldo Villalobos",
          "original_name": "Reynaldo Villalobos",
          "popularity": 0.904,
          "profile_path": "/4YlfhHDRZWhbRgeqT2Bwl1u5p9j.jpg"
        }
      ],
      "guest_stars": [
        {
          "character": "Krazy-8",
          "credit_id": "52725845760ee3046b09426e",
          "order": 504,
          "adult": false,
          "gender": 2,
          "id": 1046460,
          "known_for_department": "Acting",
          "name": "Max Arciniega",
          "original_name": "Max Arciniega",
          "popularity": 1.4399,
          "profile_path": "/eqKAJKPpt41KpsLIkkBnAY4HMAL.jpg"
        }
      ]
    }
  ],
  "name": "Season 1",
  "overview": "High school chemistry teacher Walter White's life is suddenly transformed by...",
  "id": 3572,
  "poster_path": "/91EIXdWxmp2mHNRsSuDW3WyDJLj.jpg",
  "season_number": 1,
  "vote_average": 0
}
```

## Fetch a whole series

amodb does not accept `season/1` style values in `append_to_response`, so the season calls stay separate. Read `number_of_seasons` and the `seasons` list from the TV details first, then request each season in a loop.

```js
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };

async function get(path) {
  const res = await fetch(base + path, { headers });
  if (!res.ok) throw new Error(`amodb returned ${res.status} for ${path}`);
  return res.json();
}

const show = await get('/tv/1396');
for (const { season_number } of show.seasons) {
  const season = await get(`/tv/1396/season/${season_number}`);
  console.log(season.name, season.episodes.length);
}
```

`seasons` includes season 0 when the series has specials, so Breaking Bad costs 1 details call plus 6 season calls. A series with 10 seasons costs 11 requests. Details are cached at the edge for 6 hours, so store the result and refresh it on a schedule.

## Air dates and what comes next

`GET /3/tv/{tv_id}` holds `next_episode_to_air` and `last_episode_to_air`, full episode objects with `name`, `air_date`, `season_number`, `episode_number`, `runtime` and `still_path`. `next_episode_to_air` is `null` when nothing is announced. Combine it with `status` (for example `Returning Series`, `Ended` or `Canceled`) to decide whether to show a countdown.

`air_date` is a calendar date without a time of day. Compare it with today's date to mark new episodes. For a schedule of what is on, the `airing_today` and `on_the_air` lists on [trending and lists](https://amodb.dev/trending-lists/) are cached for 30 minutes.

## Stills and runtimes

Use `w185` or `w300` for list rows and `original` for full size. The still sizes are `w92`, `w185`, `w300` and `original`. An episode can have no still, so render a placeholder when `still_path` is `null`. The image host needs no key, see [images](https://amodb.dev/images-api/).

`runtime` is in minutes and can be `null`. To show a binge time for a season, add up `runtime` over `episodes` and count `null` as 0. Add `append_to_response=credits,images` to the single episode path for a `credits` object and a `stills` list. The episode `cast` array is empty, and the people sit in `crew` and `guest_stars`. Details are on [seasons and episodes](https://amodb.dev/tv-seasons-episodes/) and [credits](https://amodb.dev/credits/).

## Alternate orders with episode groups

Some series are watched in a different order than the one they aired in. `GET /3/tv/{tv_id}/episode_groups` lists the orders defined for a series. Each entry has `id`, `name`, `description`, `type`, `episode_count`, `group_count` and `network`. The `results` array is empty when none are defined.

| `type` | Order             |
| ------ | ----------------- |
| 1      | Original air date |
| 2      | Absolute          |
| 3      | DVD               |
| 4      | Digital           |
| 5      | Story arc         |
| 6      | Production        |
| 7      | TV                |

amodb returns only this list. It does not offer `GET /3/tv/episode_group/{id}`, so the episodes inside a group are not available. Use the season endpoints for the episode data.

## How it compares

| Capability           | Scrape episode pages      | Free-tier metadata API | amodb                                            |
| -------------------- | ------------------------- | ---------------------- | ------------------------------------------------ |
| Full season          | One page fetch per season | Check their docs       | One call, `episodes` array included              |
| Whole series         | Crawl every season        | Check their docs       | One call per season, listed in `seasons`         |
| Air dates            | Parse text                | Check their docs       | `air_date` plus `next_episode_to_air`            |
| Stills               | Download and resize       | Check their docs       | Fixed sizes on `img.amodb.dev`, no key           |
| Other episode orders | Not available             | Check their docs       | `episode_groups` list, group contents not served |
| Languages            | One locale per site       | Check their docs       | 14 languages via `language`                      |

## Pricing

Plans are prepaid for 1, 3, 6, 12 or 24 months, with 0, 10, 20, 30 or 40 percent off for the longer periods, and they never renew on their own. The 20, 40 and 120 requests per minute plans return every endpoint on this page. Refreshing a series costs one request for the details and one per season. There is no free tier. Pick a plan on [pricing](https://amodb.dev/pricing/).

## Questions and answers

### How do I list all episodes of a TV series?

Read number_of_seasons from GET /3/tv/{tv_id}, then call GET /3/tv/{tv_id}/season/{season_number} for each season. Every season reply contains the full episodes array, so you need no separate call per episode. A few seasons come back with an empty episodes array when no episode data is held.

### Can I get several seasons in one request?

No. amodb ignores season/1 style values in append_to_response, so each season is its own request. A series with 10 seasons costs 11 requests, one for the details and one per season.

### What is an episode group?

An episode group is an alternate order of the same episodes, such as DVD, absolute or story arc order. GET /3/tv/{tv_id}/episode_groups lists them with name, type and episode count. amodb does not serve the episodes inside a group.

### How do I find out when the next episode airs?

GET /3/tv/{tv_id} returns next_episode_to_air with its air_date, season_number and episode_number. The value is null when nothing is announced. last_episode_to_air gives the most recent one.

### Where do episode images come from?

Each episode has a still_path. Join it to https://img.amodb.dev/t/p/{size}, for example w300 for list rows. Images need no key. A still_path can be null, so keep a placeholder ready.

## Related pages

- [TV seasons and episodes API](https://amodb.dev/tv-seasons-episodes/): TV seasons and episodes API with the same paths and JSON as TMDB v3. Read a season with all its episodes, or one episode with air date, runtime and still.
- [TV series API](https://amodb.dev/tv-series/): TV series API with the same paths and JSON as TMDB v3. Get a show by id with seasons, networks and the next episode, plus content ratings and watch providers.
- [Images API and image host](https://amodb.dev/images-api/): Movie images API with TMDB v3 paths: list posters, backdrops, logos and stills per title, then load them from img.amodb.dev in 10 sizes with no key.
- [Credits API](https://amodb.dev/credits/): Credits API with the same paths and JSON as TMDB v3. Get cast and crew for movies, series, seasons and episodes, with order, department and job fields.
- [TV show API for series, seasons and episodes](https://amodb.dev/tv-show-api/): TV show API with series status, networks, seasons, episodes and next_episode_to_air. TMDB v3 compatible JSON in 14 languages, from 20 requests per minute.
- [Quickstart](https://amodb.dev/quickstart/): Make your first amodb call: get a key, request movie details in curl, JavaScript, Python, PHP or Go, then load the poster from img.amodb.dev. Under 2 minutes.

Updated: 2026-10-18. Source: https://amodb.dev/episode-guide-api/
