> ## Documentation Index
> Fetch the complete documentation index at: https://api.simkl.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Calendar data files

> CDN-hosted JSON for upcoming episodes, premieres, and movie releases.

<Note>
  **No auth required.** Calendar data is public — send the standard [required URL parameters](/conventions/headers#required-url-parameters) (`client_id`, `app-name`, `app-version`) and a `User-Agent` header, but no user `Authorization` token.
</Note>

<Tip>
  **Which IDs can I send/expect?** All accepted input identifiers and the keys you'll see echoed back in responses are listed at [**Standard media objects → Supported ID keys**](/conventions/standard-media-objects#supported-id-keys). Send every ID you have on writes — Simkl picks the first that resolves and ignores the rest. Reminder: `slug` is **response-only** (never send it on a request).
</Tip>

Simkl publishes pre-built JSON calendars on its CDN. Use them to power the **"Upcoming"**, **"Next"**, **"Schedule"**, or **"Calendar"** sections of your app — without per-user API calls.

The files are regenerated **every 6 hours** and cached on a CDN for **5 hours**. Check the response's `Last-Modified` header to know when they were last refreshed.

<Warning>
  The CDN ignores all query strings. Don't append `?random=...` or similar — you'll just bust the cache for everyone with no benefit. The same URL serves identical content.
</Warning>

## Why use these instead of API calls

* No user `Authorization` token required (still send `client_id`, `app-name`, `app-version`, and `User-Agent` like every Simkl request).
* Hugely cheaper — one file covers thousands of titles.
* Cacheable on the user's device for hours.

A typical pattern: when the user opens their watchlist, **combine** the calendar JSON (cached locally for 3–6 hours) with the user's [synced watchlist](/guides/sync) (also cached) to compute "Next episode airs in 3 days" — without re-syncing the user's watchlist every time.

## Files

### Airing next (rolling window — yesterday + next 33 days)

| Catalog        | URL                                                                                                                                                                                                                                        |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| TV             | [https://data.simkl.in/calendar/tv.json?client\_id=YOUR\_CLIENT\_ID\&app-name=my-app-name\&app-version=1.0](https://data.simkl.in/calendar/tv.json?client_id=YOUR_CLIENT_ID\&app-name=my-app-name\&app-version=1.0)                        |
| Anime          | [https://data.simkl.in/calendar/anime.json?client\_id=YOUR\_CLIENT\_ID\&app-name=my-app-name\&app-version=1.0](https://data.simkl.in/calendar/anime.json?client_id=YOUR_CLIENT_ID\&app-name=my-app-name\&app-version=1.0)                  |
| Movie releases | [https://data.simkl.in/calendar/movie\_release.json?client\_id=YOUR\_CLIENT\_ID\&app-name=my-app-name\&app-version=1.0](https://data.simkl.in/calendar/movie_release.json?client_id=YOUR_CLIENT_ID\&app-name=my-app-name\&app-version=1.0) |

### Monthly archives

Three regeneration tiers:

* **Current month + next 3 months ahead** — regenerated **every 6 hours**. Future-month files contain only what's already been scheduled or announced, so item counts taper off the further ahead you go (typically thousands for the current month, hundreds at +3 months).
* **Previous 12 months** — regenerated **every 24 hours**.
* **Older than 12 months** — archived in place. Files remain queryable indefinitely but are no longer regenerated; `Last-Modified` freezes at end-of-month.

URL pattern:

```
https://data.simkl.in/calendar/{YEAR}/{MONTH}/{tv|anime|movie_release}.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
```

Examples for the past month (`{{PAST_YEAR}}/{{PAST_MONTH}}`) and the furthest future month available right now (`{{FUTURE_YEAR}}/{{FUTURE_MONTH}}`, which is `currentMonth + 3`). **These dates substitute on page load** — they always reflect today:

```
# Past month (last month from today)
https://data.simkl.in/calendar/{{PAST_YEAR}}/{{PAST_MONTH}}/tv.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
https://data.simkl.in/calendar/{{PAST_YEAR}}/{{PAST_MONTH}}/anime.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
https://data.simkl.in/calendar/{{PAST_YEAR}}/{{PAST_MONTH}}/movie_release.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0

# Future month — currentMonth + 3 (furthest future month available; regenerated alongside the current month)
https://data.simkl.in/calendar/{{FUTURE_YEAR}}/{{FUTURE_MONTH}}/tv.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
https://data.simkl.in/calendar/{{FUTURE_YEAR}}/{{FUTURE_MONTH}}/anime.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
https://data.simkl.in/calendar/{{FUTURE_YEAR}}/{{FUTURE_MONTH}}/movie_release.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0
```

Requesting any month beyond `currentMonth + 3` returns **404**.

## What's in each item

Every calendar entry carries everything you need to render the schedule without a second API call per item — display title + slug, [poster image path](/conventions/images), Simkl rank + ratings, an airing timestamp with a timezone offset, plus IDs across Simkl, TMDB, IMDB, TVDB, MAL, AniDB, AniList, and Kitsu where available.

```json Sample item (TV) theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "title": "Ruin Road",
  "poster": "94/941b16f3a4d2f5e0c8",
  "date": "2026-05-16T00:00:00-05:00",
  "release_date": "2016-10-15",
  "rank": 0,
  "url": "https://simkl.com/tv/1520136/ruin-road",
  "ratings": {
    "simkl": { "rating": 7.4, "votes": 132 },
    "imdb":  { "rating": 7.6, "votes": 4218 }
  },
  "ids": {
    "simkl_id": 1520136,
    "slug": "ruin-road",
    "imdb": "tt12345678",
    "tmdb": "204821",
    "tvdb": "418273"
  },
  "episode": {
    "season": 2,
    "episode": 7,
    "url": "https://simkl.com/tv/1520136/ruin-road/season-2/episode-7"
  }
}
```

### Field reference

<ResponseField name="title" type="string" required>
  Display title.
</ResponseField>

<ResponseField name="poster" type="string | null">
  Image path fragment. Combine with the prefixes in [Image conventions](/conventions/images) — for example `https://wsrv.nl/?url=https://simkl.in/posters/{poster}_m.webp&q=90`. `null` when no poster is on file (Type 4 null — see [Null and missing values](/conventions/null-values#type-4)); fall back to `https://simkl.in/poster_no_pic.png` (see [fallbacks](/conventions/images#fallback-when-images-are-missing)).
</ResponseField>

<ResponseField name="date" type="string" required>
  Air / release timestamp **with the catalog's timezone offset** (e.g. `2026-05-16T00:00:00-05:00` for US TV, `+09:00` for Japanese anime). Use this for chronological sorting and timezone-aware display.
</ResponseField>

<ResponseField name="release_date" type="string (YYYY-MM-DD)" required>
  Original premiere date — the show or movie's first-ever release, not the per-episode air date (that's in `date`).
</ResponseField>

<ResponseField name="rank" type="integer" required>
  Simkl popularity rank. `0` for items that aren't yet ranked (common on new / regional titles). Lower non-zero values = more popular.
</ResponseField>

<ResponseField name="url" type="string" required>
  Absolute `simkl.com` URL with slug (e.g. `https://simkl.com/tv/1520136/ruin-road`).
</ResponseField>

<ResponseField name="ratings" type="object">
  Aggregate ratings keyed by source. Only sources with on-file data appear.

  <Expandable title="properties">
    <ResponseField name="simkl" type="{ rating, votes }">Simkl community rating.</ResponseField>
    <ResponseField name="imdb" type="{ rating, votes }">IMDb rating (TV / movies).</ResponseField>
    <ResponseField name="mal" type="{ rating, votes }">MyAnimeList rating (anime).</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="ids" type="object" required>
  External and Simkl IDs. Always carries `simkl_id` + `slug`. `tmdb` is near-universal; `imdb` appears on TV / movies, `mal` / `anidb` / `anilist` / `kitsu` on anime. Additional slug variants (`letterslug`, `traktmslug`, `tvdbslug`, `mdlslug`, …) may appear on items with those platform links — the response is permissive.

  <Expandable title="properties">
    <ResponseField name="simkl_id" type="integer" required>Canonical Simkl ID — primary key for `/movies/{id}`, `/tv/{id}`, `/anime/{id}`.</ResponseField>
    <ResponseField name="slug" type="string" required>URL-safe slug.</ResponseField>
    <ResponseField name="imdb" type="string">IMDb ID, e.g. `tt12345678`.</ResponseField>
    <ResponseField name="tmdb" type="string">TMDB ID.</ResponseField>
    <ResponseField name="tvdb" type="string">TVDB ID (TV / anime).</ResponseField>
    <ResponseField name="mal" type="string">MyAnimeList ID (anime).</ResponseField>
    <ResponseField name="anidb" type="string">AniDB ID (anime).</ResponseField>
    <ResponseField name="anilist" type="string">AniList ID (anime).</ResponseField>
    <ResponseField name="kitsu" type="string">Kitsu ID (anime).</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="episode" type="object">
  **TV / anime only — omitted on movie files.** Episode reference for the airing.

  <Expandable title="properties">
    <ResponseField name="season" type="integer">Season number. **Present on TV; omitted on anime** (anime uses AniDB sequential numbering — no seasons). Type 2 null (key absence) on anime — see [Null and missing values](/conventions/null-values#type-2).</ResponseField>
    <ResponseField name="episode" type="integer" required>Episode number within the season (1-based).</ResponseField>
    <ResponseField name="url" type="string" required>Absolute `simkl.com` URL for the episode.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="anime_type" type="string">
  **Anime files only — omitted on TV and movie files.** Catalog format. One of `tv`, `movie`, `ova`, `ona`, `special`, `music`.
</ResponseField>
