TV show API for series, seasons and episodes
The TV show API returns a series at GET /3/tv/{series_id} with its status, networks, season list and next_episode_to_air. Season and episode endpoints add air dates, runtimes and stills. The JSON matches TMDB v3, in 14 languages, on prepaid plans of 20, 40 or 120 requests per minute.
A TV show API with status, seasons and next episode
GET /3/tv/{series_id} returns a series with its status, networks, seasons list, last_episode_to_air and next_episode_to_air. Season and episode endpoints add air dates, runtimes and stills. amodb is an independent API that speaks the TMDB v3 protocol, so a client written for TMDB works after you change the base URL to https://api.amodb.dev/3.
What you get:
- Series records with the number of seasons and episodes, plus first and last air dates.
- A
statusstring and anin_productionflag. - Networks with ids, logos and origin country.
- One call per season, returning every episode of that season.
- Lists of series that air today or within the next 7 days.
What data you get
| You need | Call | Key fields |
|---|---|---|
| Series record | GET /3/tv/{series_id} | name, original_name, status, in_production, number_of_seasons, number_of_episodes |
| Next and last episode | same call | next_episode_to_air, last_episode_to_air |
| One season | GET /3/tv/{series_id}/season/{season_number} | episodes, air_date, poster_path |
| One episode | GET /3/tv/{series_id}/season/{season_number}/episode/{episode_number} | name, overview, runtime, still_path, air_date |
| A network | GET /3/network/{network_id} | name, headquarters, origin_country |
The full field lists are on TV series and seasons and episodes.
Start in 3 steps
- Open pricing and choose the plan with the request rate you need: 20, 40 or 120 per minute.
- Create an API key in your account dashboard.
- Send
GET /3/tv/{series_id}withAuthorization: Bearer YOUR_API_KEY, or addapi_keyas a query parameter.
Example request
The script reads Breaking Bad (series id 1396), prints its status and next episode, then lists season 1. Save it as check.mjs and run it with Node 18 or newer.
curl -s "https://api.amodb.dev/3/tv/1396?language=en-US&append_to_response=ratings" \
-H "Authorization: Bearer $AMODB_KEY"
curl -s "https://api.amodb.dev/3/tv/1396/season/1?language=en-US" \
-H "Authorization: Bearer $AMODB_KEY"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?language=en-US');
const next = show.next_episode_to_air;
console.log(`${show.name}: ${show.status}, ${show.number_of_seasons} seasons`);
console.log(next
? `Next: S${next.season_number}E${next.episode_number} on ${next.air_date}`
: 'No upcoming episode is scheduled');
const season = await get('/tv/1396/season/1?language=en-US');
for (const ep of season.episodes) {
console.log(`E${ep.episode_number} ${ep.air_date} ${ep.name}`);
}A trimmed series reply for language=en-US. Only some fields are kept, and seasons shows its first 2 of 6 entries. Some names do not follow language in this data: the season 0 name is Chinese and the name inside last_episode_to_air is Hebrew.
{
"first_air_date": "2008-01-20",
"id": 1396,
"in_production": false,
"last_air_date": "2013-09-29",
"last_episode_to_air": {
"air_date": "2013-09-29",
"episode_number": 16,
"episode_type": "standard",
"id": 62161,
"name": "פלינה",
"overview": "הסדרה זוכת הפרסים מגיעה לסיום דרמתי בפרק החותם אותה.",
"production_code": "",
"runtime": 56,
"season_number": 5,
"show_id": 1396,
"still_path": "/pA0YwyhvdDXP3BEGL2grrIhq8aM.jpg",
"vote_average": 0,
"vote_count": 0
},
"name": "Breaking Bad",
"next_episode_to_air": null,
"number_of_episodes": 62,
"number_of_seasons": 5,
"original_name": "Breaking Bad",
"seasons": [
{
"air_date": "2009-02-17",
"episode_count": 9,
"id": 3577,
"name": "特别篇",
"overview": "",
"poster_path": "/ikBSCmgG5Z4jequUUAjKpf1QG3T.jpg",
"season_number": 0,
"vote_average": 0
},
{
"air_date": "2008-01-20",
"episode_count": 7,
"id": 3572,
"name": "Season 1",
"overview": "High school chemistry teacher Walter White's life is suddenly transformed by a dire medical diagn...",
"poster_path": "/91EIXdWxmp2mHNRsSuDW3WyDJLj.jpg",
"season_number": 1,
"vote_average": 0
}
],
"status": "Ended"
}Reading status and the next episode
The status string tells you how to label a series. next_episode_to_air is an object only while an episode is scheduled, so it is null between seasons as well as after the end. Test status before you show "ended".
status | Meaning | What to show |
|---|---|---|
| Returning Series | More episodes are expected | Next air date if the object exists, otherwise "returning" |
| In Production | Being made, not on air yet | "In production" |
| Planned | Announced only | "Planned" |
| Pilot | Only a pilot exists | "Pilot" |
| Ended | The run is finished | "Ended" and last_air_date |
| Canceled | Stopped before the planned end | "Canceled" |
Fields inside next_episode_to_air and last_episode_to_air: air_date, season_number, episode_number, episode_type, id, show_id, name, overview, runtime and still_path. The status string can also be empty on a few titles, so keep a neutral label ready.
Details are cached at the edge for 6 hours, so asking for the same series more than four times a day returns the same body. Poll your followed shows once or twice a day and refresh the one a user opens.
Seasons, episodes and what is on air
Season 0, when a series has one, holds specials. Regular seasons start at 1.
| Call | Returns | Parameters |
|---|---|---|
GET /3/tv/{series_id}/season/{season_number} | Season record with an episodes array | language, append_to_response |
GET /3/tv/airing_today | Series with an episode airing today | page, language |
GET /3/tv/on_the_air | Series airing in the coming week | page, language |
GET /3/discover/tv | Series filtered by network, status and more | with_networks, with_status, sort_by, page |
Lists and discover results are cached for 30 minutes, so one request per half hour is enough for an "airing soon" badge. Match the returned ids against the series your users follow. Season and episode details are covered on the episode guide page.
Building a follow list with countdowns
A "shows I follow" screen needs one stored id per show and a small daily job.
- Save the series
idwhen a user follows a show. - Once a day, call
/3/tv/{series_id}for each followed id and storestatus,next_episode_to_airandlast_air_date. - When
next_episode_to_airis an object, showair_dateas a date. It carries no time of day and no time zone, so do not count down to the minute. - When it is null and
statusis Returning Series, show "new season not scheduled". - Fetch the season call only when a user opens the show, because it is the largest reply.
A 404 with status_code 34 means the id is unknown, and a 429 means you went over your requests per minute: wait for Retry-After seconds. With 200 followed shows, one daily pass is 200 requests, about ten minutes at 20 requests per minute. See rate limits and errors.
How it compares
| Capability | Scrape pages yourself | Free-tier metadata API | amodb |
|---|---|---|---|
| Season and episode structure | Rebuilt from page layouts | Varies, check the docs | Season call with an episodes array |
| Next air date | Parsed from a schedule page | Varies, check the docs | next_episode_to_air, null when none is scheduled |
| Show status | Free text on a page | Varies, check the docs | status string and in_production flag |
| Airing this week | Scrape a schedule | Varies, check the docs | /3/tv/on_the_air and /3/tv/airing_today |
| Languages | Whatever the page offers | Varies | 14, chosen with language |
| Access terms | The site's terms apply | Free tier with usage terms | Paid, prepaid, no free tier |
Pricing
Pay once for 1, 3, 6, 12 or 24 months. Longer periods take 10, 20, 30 or 40 percent off, and nothing renews automatically. Every plan gets all TV data, with 20, 40 or 120 requests per minute as the only difference. See pricing, create a key, and your first series call takes one request.
Questions and answers
How do I know if a TV show is still airing?
Read status on /3/tv/{id}. Returning Series means more episodes are expected, while Ended and Canceled mean none. The field next_episode_to_air holds the next scheduled episode and is null when nothing is scheduled.
Can I fetch every episode of a series in one request?
One season per call. GET /3/tv/{id}/season/{n} returns all episodes of that season in an episodes array, so a five season show takes five season calls plus one series call.
What do I get for a network?
The networks array on a series lists id, name, logo_path and origin_country. GET /3/network/{id} adds details, and with_networks in /3/discover/tv lists the series of one network.
Can I list the shows that air today?
Yes. /3/tv/airing_today lists series with an episode airing today and /3/tv/on_the_air covers the next 7 days. Both are paged, take language, and sit in the edge cache for 30 minutes.
Is there a free tier for the TV show API?
No free tier and no trial. You prepay for 1, 3, 6, 12 or 24 months and nothing renews by itself. Every plan returns all data, and plans differ only in requests per minute.