> ## 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.

# Handling anime

> Learn how to sync and interact with Simkl's anime catalog. Whether your app is TMDB-primary or Anime-native, this guide covers the mapping, payloads, and edge cases.

Simkl uses AniDB as its primary metadata source for anime. Because the anime catalog is modeled differently than Western TV shows (often split per-cour or numbered absolutely), Simkl provides an automated cross-mapping system. This allows developers to interact with the anime catalog using standard TVDB/TMDB season-and-episode coordinates.

This guide outlines the two primary integration paths, how the cross-mapping works under the hood with real-world examples, and how to write watch history and read catalog data.

***

<Tip>
  ### Recommendation: Adopt Simkl's Native Anime Catalog

  If you are designing a new application or have the flexibility to add a dedicated **Anime** content type to your existing app, we strongly recommend using **Simkl's Native Anime Catalog (Path B)** instead of treating anime as TV Shows.

  **Why this is better:**

  * **No Season Discrepancies:** Completely bypasses TMDB vs. TVDB season boundary disagreements.
  * **1:1 Native Syncing:** Matches the data shape of major anime trackers (MyAnimeList, AniList, Kitsu, AniDB) for seamless 1:1 cross-platform syncing.
  * **Rich Metadata:** Access to anime-specific metadata like animation studios, airing calendars, and comprehensive franchise relationships (prequels, sequels, summaries, spin-offs).
</Tip>

***

## The Two Integration Paths

Choose the path that fits your app's existing metadata system:

<CardGroup cols={2}>
  <Card title="Path A: TVDB/TMDB-Primary Tracker" icon="tv" href="#path-a-tmdb-or-tvdb-primary-integration">
    Your app tracks general TV and uses TMDB or TVDB IDs. You want to sync anime without changing your TV-centric seasons/episodes structure.

    *Uses Simkl's automatic cross-mapping via the `use_tvdb_anime_seasons` flag.*
  </Card>

  <Card title="Path B: Anime-Native App" icon="ticket" href="#path-b-anime-native-integration">
    Your app is dedicated to anime and uses MAL, AniDB, AniList, or Kitsu IDs. You deal with flat/absolute episode numbers directly.

    *Bypasses cross-mapping and interacts directly with Simkl's anime endpoints.*
  </Card>
</CardGroup>

***

## Integration Guide by App Type

Different app types require different integration strategies. Check the recommendations below to see which path and endpoints you should focus on:

<AccordionGroup>
  <Accordion title="General TV Trackers (e.g., TV season dashboards, multi-media trackers)" icon="chart-line">
    **Recommendation:** Use **Path A** (TMDB/TVDB-Primary) for convenience, but see the best practices below for handling TMDB-primary boundary issues.

    * **Syncing lists:** Send history updates using TMDB or TVDB IDs, always passing `"use_tvdb_anime_seasons": true`.
    * **Fetching library:** Query `GET /sync/all-items/anime?extended=full_anime_seasons`. Use the `mapped_tvdb_seasons` array to know which seasons to render, and map the episodes back to your UI using `tvdb.season` and `tvdb.episode`.
    * **Detail views:** Use [`GET /anime/{id}`](/api-reference/simkl/get-anime) to fetch details like `studios` and `relations` for anime shows.
  </Accordion>

  <Accordion title="Media Players & Scrobblers (e.g., Plex, Kodi, MPV, VLC plugins)" icon="play-pause">
    **Recommendation:** Use **Path A** (TMDB/TVDB coordinates) for automated matching.

    * **Real-time scrobbling:** Send playback state to [`POST /scrobble/start`](/api-reference/simkl/scrobble-start) using standard TVDB or TMDB IDs under the **`show`** key.
    * **Why this is easy:** You do not need to convert TVDB season/episodes to absolute numbers client-side. Simkl's scrobbler handles the translation to absolute/cour-split anime entries automatically.
    * **File-based scrobbling:** If your scrobbler parses absolute numbers directly from filenames, you can optionally scrobble using absolute numbers under the `anime` object.
  </Accordion>

  <Accordion title="Anime-Native Trackers (e.g., MAL, AniList, Kitsu clients)" icon="ticket-direct">
    **Recommendation:** Use **Path B** (Anime-Native IDs).

    * **Syncing lists:** Send history updates using native database IDs (`mal`, `anilist`, `anidb`, `kitsu`) under the **`anime`** key.
    * **Absolute numbering:** Send flat, absolute episode numbers directly. Do not supply season coordinates.
  </Accordion>
</AccordionGroup>

***

## Best Practices for TMDB-Primary Applications

Since **TMDB** is the most common metadata source for general media tracking applications, Simkl supports it fully. However, because TMDB's season/episode definitions occasionally disagree with TVDB's (which Simkl uses for mapping coordinates), you should use the following safe integration workflows:

### The Safe Integration Workflow

If your application's primary metadata source is TMDB, follow these rules to ensure perfect matching:

1. **Send Both IDs:** Whenever writing to Simkl, include both the `tmdb` ID and the `tvdb` ID in your `ids` object. Simkl will resolve the show using the most reliable record.
2. **Translate to TVDB Coordinates on Writes:** If you know TMDB and TVDB disagree on season boundaries for a specific anime, prioritize sending **TVDB season and episode coordinates** in the write payload when `use_tvdb_anime_seasons: true` is set.
3. **Use Simkl's Native IDs as Fallbacks:** If a show's TVDB/TMDB seasons are severely misaligned or fragmented, look up the show on Simkl using Title + Year or external anime IDs (MAL/AniList), and sync it using **Path B** instead.

***

## How the Cross-Mapping Works

Simkl stores a **per-episode TVDB coordinate** (`tvdb.season`, `tvdb.episode`) on every anime episode in the catalog. That coordinate maps directly from any TVDB- or TMDB-shaped `seasons[N].episodes[M]` payload to the exact Simkl record + episode the user means. The mapping handles every catalog shape uniformly.

### Real-World Mapping Examples

<Tabs>
  <Tab title="Per-cour-split (e.g., Attack on Titan)">
    The main TV story is split into six separate Simkl titles (one per broadcast cour). Each title's episodes start at `1`, and carry the TVDB coordinate it maps to:

    | Simkl cour-title                                                                                                 | Eps | First episode → TVDB    |
    | ---------------------------------------------------------------------------------------------------------------- | --- | ----------------------- |
    | [AOT S1](https://simkl.com/anime/39687/shingeki-no-kyojin) (`39687`, 2013)                                       | 25  | Simkl ep 1 → TVDB S1E1  |
    | [AOT Season 2](https://simkl.com/anime/439744/shingeki-no-kyojin-season-2) (`439744`, 2017)                      | 12  | Simkl ep 1 → TVDB S2E1  |
    | [AOT Season 3 part 1](https://simkl.com/anime/694485/shingeki-no-kyojin-season-3) (`694485`, 2018)               | 12  | Simkl ep 1 → TVDB S3E1  |
    | [AOT Season 3 part 2](https://simkl.com/anime/931899/shingeki-no-kyojin-season-3) (`931899`, 2019)               | 10  | Simkl ep 1 → TVDB S3E13 |
    | [AOT Final Season](https://simkl.com/anime/1120029/shingeki-no-kyojin-the-final-season) (`1120029`, 2020)        | 16  | Simkl ep 1 → TVDB S4E1  |
    | [AOT Final Season part 2](https://simkl.com/anime/1579947/shingeki-no-kyojin-the-final-season) (`1579947`, 2022) | 12  | Simkl ep 1 → TVDB S4E17 |

    All six share TVDB ID `267440` and TMDB ID `1429`. When you write to `Season 3 Episode 13`, Simkl automatically uses the episode offset mapping to route the write to episode `1` of *AOT Season 3 Part 2* (`931899`).

    #### Franchise Extensions (OVAs, Specials, Movies)

    AniDB models specials, OVAs, films, and spin-offs as separate entries, which Simkl mirrors. Below is the inventory beyond the main TV cours:

    | Simkl title                                                                       | Type      | Eps | TVDB cross-ref       | TMDB cross-ref             |
    | --------------------------------------------------------------------------------- | --------- | --- | -------------------- | -------------------------- |
    | [AOT The Final Season special](https://simkl.com/anime/1883416) (`1883416`, 2023) | `special` | 2   | `267440` (parent TV) | `1429` (parent TV)         |
    | [AOT: The Last Attack](https://simkl.com/anime/2544548) (`2544548`, 2024)         | `movie`   | 1   | —                    | `1333100` (dedicated film) |
    | [AOT OAD](https://simkl.com/anime/38688) (`38688`, 2013)                          | `ova`     | 8   | `267440` (parent TV) | `1429` (parent TV)         |
    | [AOT: No Regrets](https://simkl.com/anime/419356) (`419356`, 2014)                | `ova`     | 2   | —                    | —                          |
    | [AOT: Wings of Freedom](https://simkl.com/anime/49394) (`49394`, 2014)            | `movie`   | 2   | `7398` (dedicated)   | `1429` (parent TV) ⚠️      |
    | [AOT: Roar of Awakening](https://simkl.com/anime/732309) (`732309`, 2018)         | `movie`   | 1   | `13398` (dedicated)  | `1429` (parent TV) ⚠️      |
    | [AOT: Chronicle](https://simkl.com/anime/1358719) (`1358719`, 2020)               | `movie`   | 1   | `140480` (dedicated) | `1429` (parent TV) ⚠️      |
    | [AOT: Junior High](https://simkl.com/anime/513950) (`513950`, 2015)               | `tv`      | 12  | `299882` (dedicated) | `63510` (dedicated TV)     |

    *Note: ⚠️ entries indicate parent-show fallback links on TMDB/TVDB instead of dedicated ones.*
  </Tab>

  <Tab title="Absolute-numbered (e.g., One Piece)">
    One Piece is represented as a single Simkl title (`38636`) with 1100+ episodes, numbered absolutely. Every episode carries its TVDB season + episode coordinate:

    | Simkl episode (absolute) | TVDB coordinate | Title                                                  |
    | ------------------------ | --------------- | ------------------------------------------------------ |
    | 1                        | S1E1            | I'm Luffy! The Man Who's Gonna Be King of the Pirates! |
    | 9                        | S2E1            | The Honorable Liar? Captain Usopp!                     |
    | 31                       | S3E1            | The Worst Man in the Eastern Seas!                     |
    | 48                       | S4E1            | The Town of the Beginning and the End!                 |
    | 196                      | S10E1           | A State of Emergency Is Issued!                        |
    | 326                      | S12E1           | The Mysterious Band of Pirates!                        |
    | 878                      | S20E1           | The World Is Stunned! The Fifth Emperor of the Sea!    |
    | 1156                     | S23E1           | The Long-Sought Elbaph!                                |

    The single Simkl title shares TVDB ID `81797` and TMDB ID `37854`. Writing to TVDB season `10` episode `4` maps to absolute episode `199` on the single One Piece Simkl record.
  </Tab>
</Tabs>

***

## Path A: TMDB or TVDB Primary Integration

If your app uses TMDB or TVDB show IDs, you do not need to convert seasons/episodes to absolute numbers client-side. Simkl maps them automatically on both writes and reads.

### 1. Writing to Simkl (Syncing history/list additions)

When marking an episode as watched or adding a show to a list, send your TMDB/TVDB show ID along with standard seasons and episodes, and set **`use_tvdb_anime_seasons: true`**.

Under the hood, this flag instructs the Simkl API to fetch the mapped franchise seasons/titles and route the TVDB coordinates to the correct under-the-hood Simkl anime record and episode.

#### Example Payload

For **Attack on Titan Season 2 Episode 4** (using parent TV show TMDB ID `1429`):

```json POST /sync/history theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "shows": [
    {
      "ids": { "tmdb": "1429" },
      "use_tvdb_anime_seasons": true,
      "seasons": [
        {
          "number": 2,
          "episodes": [{ "number": 4 }]
        }
      ]
    }
  ]
}
```

For **One Piece Season 10 Episode 4** (using TMDB ID `37854`):

```json POST /sync/history theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "shows": [
    {
      "ids": { "tmdb": "37854" },
      "use_tvdb_anime_seasons": true,
      "seasons": [
        {
          "number": 10,
          "episodes": [{ "number": 4 }]
        }
      ]
    }
  ]
}
```

<Tip>
  **Pro-tip:** You can set `use_tvdb_anime_seasons: true` on all TV shows in your payload. For non-anime shows, the flag is a safe no-op. For anime, it automatically handles both per-cour split titles and absolute-numbered shows.
</Tip>

### 2. Reading from Simkl (Syncing watchlist & watch history)

When reading the user's library, use **`extended=full_anime_seasons`**. This includes the TVDB/TMDB season cross-mapping in the response.

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl "https://api.simkl.com/sync/all-items/anime?extended=full_anime_seasons&client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
  -H "User-Agent: my-app-name/1.0" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

#### Understanding the Response Fields

For anime shows, the response includes:

* **`mapped_tvdb_seasons`**: An array of TVDB season numbers covered by this Simkl title. (e.g., `[2]` for *Attack on Titan Season 2*).
* **`tvdb: { season, episode }`**: Attached to each episode object to map the AniDB/absolute episode back to the TMDB/TVDB coordinates.

Example response snippet:

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "anime": [
    {
      "show": {
        "title": "Shingeki no Kyojin Season 2",
        "ids": { "simkl": 439744, "tmdb": "1429" }
      },
      "mapped_tvdb_seasons": [2],
      "seasons": [
        {
          "number": 1,
          "episodes": [
            {
              "number": 1,
              "tvdb": { "season": 2, "episode": 1 }
            }
          ]
        }
      ]
    }
  ]
}
```

### 3. Scrobbling Playback

For media players, scrobble payloads are single-item envelopes. You do **not** need to set `use_tvdb_anime_seasons`. Send the payload under the standard **`show`** key using your TMDB/TVDB coordinates, and Simkl will resolve the anime mapping automatically.

```json POST /scrobble/start theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "progress": 0,
  "show": {
    "ids": { "tmdb": "1429" }
  },
  "episode": {
    "season": 2,
    "number": 4
  }
}
```

***

## Path B: Anime-Native Integration

If your app uses anime-native IDs (MAL, AniList, AniDB, Kitsu), you bypass Simkl's cross-mapping engine. External anime IDs have a 1:1 relationship with Simkl's anime records.

### 1. Writing to Simkl

Use the **`anime`** array envelope, and supply flat/absolute episode numbers under `episodes[]` (do not include a `season` field).

#### Example Payload: Cour-Split Anime (Attack on Titan S2 Ep 4)

```json POST /sync/history theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "anime": [
    {
      "ids": {
        "mal": 25777,
        "anilist": 20958,
        "anidb": 10944
      },
      "episodes": [{ "number": 4 }]
    }
  ]
}
```

#### Example Payload: Absolute-Numbered Anime (One Piece Absolute Ep 403)

```json POST /sync/history theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "anime": [
    {
      "ids": {
        "mal": 21,
        "anilist": 21,
        "anidb": 69
      },
      "episodes": [{ "number": 403 }]
    }
  ]
}
```

### 2. Reading from Simkl (Syncing watchlist & watch history)

When reading the user's library, perform a GET request to the anime-specific library endpoint:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl "https://api.simkl.com/sync/all-items/anime?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
  -H "User-Agent: my-app-name/1.0" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

The response returns entries in the `anime` array, with all mapped external IDs (MAL, AniList, AniDB, Kitsu, etc.) populated in the `ids` block. You can map these IDs directly to your app's local database without any coordinate translation layers.

#### Example Response Snippet

```json theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "anime": [
    {
      "added_to_watchlist_at": "2026-05-20T03:00:00-04:00",
      "status": "watching",
      "watched_episodes_count": 4,
      "total_episodes_count": 12,
      "anime": {
        "title": "Shingeki no Kyojin Season 2",
        "ids": {
          "simkl": 439744,
          "mal": "25777",
          "anilist": "20958",
          "anidb": "10944",
          "kitsu": "8756"
        }
      }
    }
  ]
}
```

***

## Anime-Specific Catalog Fields

When querying Simkl's catalog endpoints (e.g., [`GET /anime/{id}`](/api-reference/simkl/get-anime)), you will encounter fields unique to the anime catalog:

### 1. `anime_type`

Differentiates the format of the entry. Useful for client-side filtering:

| Type          | Meaning                                    |
| ------------- | ------------------------------------------ |
| `tv`          | Standard broadcast television series       |
| `movie`       | Theatrical film                            |
| `ova`         | Original Video Animation (direct-to-video) |
| `ona`         | Original Net Animation (web-released)      |
| `special`     | Specials, OADs, side stories               |
| `music video` | Music videos                               |

### 2. `relations[]`

Lists prequels, sequels, summaries, and side-stories.

* `relation_type`: Describes the relationship (e.g., `prequel`, `sequel`, `summary`, `side story`).
* `is_direct`: `true` for immediate narrative continuations; `false` for spin-offs or wider connections.

### 3. Flat Episode Lists

Unlike standard TV episode lists, [`GET /anime/episodes/{id}`](/api-reference/simkl/get-anime-episodes) returns a flat array of episodes. Standard episodes and specials alike omit the `season` field, carrying only `episode` (flat/absolute number) and a `tvdb` coordinate block.

***

## Anime-Specific Endpoints + Parameters Reference

### Writes

| Endpoint                                                                | Anime-specific behavior                                                                                                                                                                                                              |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [`POST /sync/history`](/api-reference/simkl/add-to-history)             | Accepts `anime[]` envelope (alternative to `shows[]`). The `use_tvdb_anime_seasons: true` flag on a `shows[]` entry routes TVDB season/episode coordinates to the correct under-the-hood Simkl record via per-episode cross-mapping. |
| [`POST /sync/history/remove`](/api-reference/simkl/remove-from-history) | Same shape and flags as `/sync/history`.                                                                                                                                                                                             |
| [`POST /sync/add-to-list`](/api-reference/simkl/add-to-list)            | Same shape and flags. Used to move anime into `watching` / `plantowatch` / `hold` / `completed` / `dropped`.                                                                                                                         |
| [`POST /scrobble/start`](/api-reference/simkl/scrobble-start)           | Single-item envelope: `anime: { ids: {...} }` + `episode: { season, number }` (for TMDB/TVDB IDs) or `episode: { number }` (for anime-native IDs). Resolves the title and matches the episode through the same cross-map.            |

### Reads — User Library

| Endpoint                                                                                | Anime-specific behavior                                                                                                                                   |
| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`GET /sync/all-items/anime`](/api-reference/simkl/get-all-items)                       | Type-scoped library read — returns only the user's anime entries.                                                                                         |
| [`GET /sync/all-items?extended=full_anime_seasons`](/api-reference/simkl/get-all-items) | Adds `mapped_tvdb_seasons: [N, ...]` to anime show entries and adds a `tvdb: { season, episode }` cross-map block to every anime episode in the response. |
| [`GET /sync/all-items?anime_type=tv`](/api-reference/simkl/get-all-items)               | Filter anime entries by `anime_type` (`tv`, `movie`, `ova`, `ona`, `special`, `music video`).                                                             |
| [`GET /sync/activities`](/api-reference/simkl/get-activities)                           | Returns an `anime` block separate from `tv_shows` and `movies`, each with its own per-status timestamps.                                                  |

### Reads — Catalog

| Endpoint                                                              | Anime-specific behavior                                                                                                                                                          |
| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`GET /anime/{id}`](/api-reference/simkl/get-anime)                   | Anime detail. Returns: `anime_type`, `mapped_tvdb_seasons[]`, `relations[]`, `en_title`, `alt_titles[]`, `season_name_year`, and `studios`. (Does not include the episode list). |
| [`GET /anime/episodes/{id}`](/api-reference/simkl/get-anime-episodes) | Returns flat episode array (no `season` fields; `episode` number is 1-N). Includes `tvdb: { season, episode }` blocks on each episode.                                           |
| [`GET /search/anime`](/api-reference/simkl/search-by-text)            | Text search scoped to anime catalog. Returns `anime_type`, `title_romaji`, and `title_en`.                                                                                       |

***

## Integration Edge Cases

<AccordionGroup>
  <Accordion title="TMDB and TVDB Season Boundary Disagreements">
    Because TMDB and TVDB are community-maintained, they occasionally disagree on season numbering for newer or split-cour anime (e.g., *Solo Leveling*).

    Since Simkl's cross-mapping is based on **TVDB season coordinates**, sending TMDB-only IDs with TMDB-style season numbers can sometimes route to the wrong cour.

    **Solutions:**

    1. **Send the TVDB ID** (`ids.tvdb`) alongside the TMDB ID, using the TVDB season numbering in your payload.
    2. **Provide anime-native IDs** (`mal`, `anilist`, `anidb`) if your app has access to them, which maps 1:1 and avoids the translation step.
    3. **Send Title + Year** (`title` and `year`). Simkl's server-side title resolver is robust and resolves directly to the right cour.
  </Accordion>

  <Accordion title="Parent-Show Fallbacks (One-to-Many IDs)">
    OVAs, specials, and recap films often inherit the parent TV show's TMDB or TVDB ID on Simkl because a dedicated film entry does not exist or wasn't linked.

    * **Implied Action:** Do not assume the Simkl `tmdb` / `tvdb` ID maps 1:1 to a unique external entry. To deep-link to external catalogs, treat these IDs as references rather than canonical links.
  </Accordion>

  <Accordion title="Multi-Part Movies (e.g., Kara no Kyoukai)">
    Some multi-part film series are grouped as a single Simkl entry with multiple episodes (each representing a film part).

    Check the `total_episodes` field to determine if a `movie` entry contains multiple parts.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Mark as watched" icon="circle-check" href="/guides/mark-as-watched">
    `POST /sync/history` — payload shape, batching, mixing movies / shows / anime in one call.
  </Card>

  <Card title="Sync watch state" icon="arrows-rotate" href="/guides/sync">
    Initial sync + continuous deltas, `/sync/activities` gating, `extended=full_anime_seasons`, supported IDs, write operations, edge cases.
  </Card>

  <Card title="Scrobbling playback" icon="play" href="/guides/scrobble">
    Real-time start / pause / stop / checkin. Includes anime-episode-numbering examples for both anime-native and TMDB / TVDB-shaped scrobbles.
  </Card>

  <Card title="Standard media objects" icon="cube" href="/conventions/standard-media-objects">
    The `ids` table, `anime[]` vs `shows[]` envelope rule, and how episode objects work across every endpoint.
  </Card>
</CardGroup>
