> For the complete documentation index, see [llms.txt](https://wiki.crosswatch.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.crosswatch.app/blueprint-architecture/sync/_mod_anilist/watchlist.md).

# watchlist

AniList watchlist is supported by this sync module.

Related:

* Pair setting: [Watchlist](/crosswatch/configure-pairs/features/watchlist.md)
* Pair options: [AniList pair options](/crosswatch/configure-pairs/anilist-pair-options.md)
* Matching: [Anime ID Mapping](/crosswatch/providers/metadata-id-mapping/anime-id-mapping.md)
* Engine semantics: [Watchlist (engine-level)](/blueprint-architecture/sync/engine-level-features/watchlist.md)

{% tabs %}
{% tab title="End users" %}

### What syncs

CrossWatch maps the AniList watchlist to media list entries with the `PLANNING` status.

This is the AniList **Planning** list.

It is commonly used as **Plan to Watch**.

Only the AniList anime catalog is queried.

Manga entries are not included.

### Supported media types

* Anime movies: supported
* Anime series: supported
* Manga: not supported
* Seasons: not supported
* Episodes: not supported

AniList stores anime formats as separate media entries.

Entries with the AniList `MOVIE` format map to movies.

TV, ONA, OVA, and similar formats map to shows when CrossWatch needs that distinction.

### Reads vs writes

* Reads: fetch entries with the AniList `PLANNING` status.
* Writes:
  * `add` creates or updates an AniList media list entry with status `PLANNING`.
  * `remove` deletes the AniList media list entry.

Watchlist is a set-like feature.

An item is either present in the Planning list or absent.

There is no separate watchlist update operation.

### Matching note

Use **Anime ID Mapping** for AniList pairs.

It improves matches when the other side uses TMDb, TVDb, or IMDb IDs.

Guide: [Anime ID Mapping](/crosswatch/providers/metadata-id-mapping/anime-id-mapping.md)

When **Anime-only sync** is on, CrossWatch writes only items that resolve through AniList or MAL IDs.

Items that would need title search are skipped.

### Add and remove behavior

Adds write an AniList media list entry with:

```json
{
  "status": "PLANNING"
}
```

Removes delete the AniList media list entry.

Use **Remove** carefully in two-way sync.

It is destructive.

### Dry run note

Dry runs report planned additions and removals without calling the AniList API.
{% endtab %}

{% tab title="Power users" %}

### Index behavior

CrossWatch queries AniList `MediaListCollection` for the authenticated user.

It requests:

* media type: `ANIME`
* media list status: `PLANNING`

If the filtered Planning query fails, CrossWatch fetches the full anime collection and filters locally.

Only entries with the `PLANNING` status enter the live watchlist index.

Each indexed item can include:

* `type`
* `title`
* `year`
* `ids.anilist`
* `ids.mal`
* AniList list entry ID
* AniList list status
* Anime mapping details
* Shadow state metadata

Title preference order:

1. English
2. Romaji
3. Native

The index uses `present` semantics.

AniList does not expose observed watchlist deletion events.

### Resolution order

Before CrossWatch writes an item to AniList, it resolves the target in this order:

1. Existing AniList ID
2. Existing or mapped MAL ID
3. AniList title search

Title search considers:

* exact title matches
* partial title matches
* release year
* movie or show format

Low-confidence matches are rejected.

When **Anime-only sync** is on, title search is skipped.

### Use Anime ID Mapping

When **Use Anime ID Mapping** is enabled, CrossWatch enriches source IDs through the local AniBridge index.

That can bridge:

* TMDb
* TVDb
* IMDb
* AniDB
* MAL
* AniList

A mapped AniList or MAL ID is preferred over title search.

Mapping also helps when AniList is the source.

It can enrich AniList entries with IDs that media servers and trackers understand.

### Anime-only sync

When **Anime-only sync** is enabled, CrossWatch writes only items that resolve through an AniList or MAL ID.

If no usable ID exists after mapping, the item is skipped.

Items rejected by Anime-only sync are reported as skipped.

If the mapping index is unavailable, CrossWatch logs a warning and falls back to normal title resolution for that run.

### Add behavior

Before CrossWatch writes, it checks whether the item already exists in AniList.

If the item already has a `PLANNING` entry, CrossWatch treats it as confirmed.

It stores the AniList list entry ID in the local shadow state.

If the item exists with another status, the save operation sets its status to `PLANNING`.

That can move an item from another AniList list into Planning.

### Unresolved and skipped additions

If CrossWatch cannot resolve an AniList media ID, the item is skipped.

The skipped item is stored in the AniList watchlist shadow with an ignore reason, such as:

* `anime_only_unmapped`
* `not_anime_or_no_match`

Ignored shadow entries prevent repeated add attempts on later runs.

Ignored entries appear in the destination index as local placeholders.

No AniList media list entry is created for them.

When the item is later removed from the source, CrossWatch removes the ignored shadow entry without calling AniList.

### Remove behavior

Removing an item uses `DeleteMediaListEntry`.

CrossWatch finds the required list entry ID in this order:

1. list entry ID on the indexed item
2. list entry ID stored in the watchlist shadow
3. resolved AniList media ID plus a live media list lookup

If no list entry ID can be found, the removal stays unresolved.

A successful removal deletes the media list entry.

It does not simply change the status away from `PLANNING`.

### Existing entries

Before adding an item, CrossWatch checks for an existing AniList media list entry for the resolved media ID.

If the entry already has the `PLANNING` status, no duplicate write is made.

The existing list entry ID and source IDs are saved in shadow state for later compares and removals.

### Code map

* `providers/sync/_mod_ANILIST.py`
* `providers/sync/anilist/_watchlist.py`
* `cw_platform/anime_mapping/service.py`
* `cw_platform/anime_mapping/storage.py`

### Shadow state

* `anilist_watchlist_shadow.json`

The shadow can store:

* source canonical key
* source identifiers
* AniList ID
* MAL ID
* AniList list entry ID
* media type
* title
* year
* ignore state
* ignore reason
* last update timestamp

The shadow is used to:

* preserve the original source key after AniList mapping
* associate AniList entries with source IDs
* avoid repeated attempts for skipped items
* find the correct list entry during removal
* keep compare behavior stable when providers prefer different IDs

When a live AniList entry matches a shadow entry, CrossWatch adopts the original source key while building the index.

Shadow entries are removed when the live AniList entry no longer exists.

### Two-way behavior

This feature supports bidirectional sync.

When AniList is the source, Planning entries can be added to the other provider.

When AniList is the target, source watchlist items can be added to AniList Planning.

In two-way mode, both indexes participate in planning.

**Add** and **Remove** controls decide which changes can be written in each direction.

### Authentication

This module needs a valid AniList access token.

The authenticated AniList viewer ID is used for:

* reading the Planning list
* checking existing media list entries
* resolving removal targets

If the viewer cannot be resolved, index building returns no entries and removals stay unresolved.

### Provider capabilities

* Bidirectional: supported
* Provides stable IDs: supported
* Index semantics: `present`
* Add to Planning: supported
* Remove list entry: supported
* Observed deletes: not supported
* Anime movies: supported
* Anime shows: supported
* Manga: not supported
* Seasons: not supported
* Episodes: not supported
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.crosswatch.app/blueprint-architecture/sync/_mod_anilist/watchlist.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
