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

# Custom lists

> Read a user's custom lists and the items inside them. Beta, read-only, and requires a Simkl PRO or VIP access token.

**Custom lists are user-curated collections** — "Best of 2026", "Comfort rewatches", "Anime to show my sister". This API reads them.

<Warning>
  **Custom lists requires [AUTH V2](/api-reference/auth-v2), and is a PRO and VIP feature.** It is the first API that V1 `client_id`s cannot reach. There is no anonymous access either. Every call needs an `Authorization: Bearer ...` token belonging to a Simkl **PRO or VIP** account. An anonymous caller counts as a free account, so calling without a token does not get you a public subset — it gets you the `premium_only` body described below.

  Users can upgrade at [simkl.com/vip](https://simkl.com/vip/).
</Warning>

<Note>
  **Beta.** The response shape may still change. These pages are updated when it does, and the changelog records anything that would break a client.
</Note>

## What you can and cannot do

|                                  |                                                                   |
| -------------------------------- | ----------------------------------------------------------------- |
| Read a list's metadata and items | [`GET /lists/{id}`](/api-reference/simkl/get-list)                |
| Read a user's lists              | [`GET /lists/user/{userId}`](/api-reference/simkl/get-user-lists) |
| Create, rename or delete a list  | Not in the API — website only                                     |
| Add or remove items              | Not in the API — website only                                     |

Writes are on the roadmap. Until they land, an app can display lists but not edit them.

## A 200 does not always mean a list

<Warning>
  **A free or anonymous caller gets `HTTP 200`, not an error.** The body carries `premium_only` rather than list data:

  ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "error": "premium_only",
    "message": "Custom list items are available to Simkl PRO and VIP members only.",
    "item": {
      "title": "Upgrade to Simkl PRO/VIP to unlock this list",
      "description": "Subscribe to Simkl PRO or VIP to view this list",
      "poster": "https://simkl.in/poster_upgrade.webp"
    }
  }
  ```

  **Check for an `error` key on a 200 before you read `items`.** A client that branches only on the status code treats this as a successful list and renders the placeholder as real content — a user sees one fake entry titled "Upgrade to Simkl PRO/VIP" sitting in what looks like their list.

  Three details worth pinning down:

  * `error` is lowercase `premium_only`.
  * There is **no `items` array and no `pagination` object** here. This is a different shape, not a degraded one, so `items` is undefined rather than empty.
  * `item` is singular and renderable — real title, description and poster URL. Displaying it as-is is the simplest way to show the user why the list is empty.
</Warning>

## Shared query parameters

Both endpoints accept the same paging controls.

| Parameter   | Default | Notes                                                                                                           |
| ----------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| `limit`     | 50      | 1 to 500. Out-of-range values are **clamped silently**, so `limit=99999` returns 500 items with a `200`.        |
| `page`      | 1       | Also clamped. `page` times `limit` cannot exceed 10000, so at the default limit the last reachable page is 200. |
| `direction` | —       | `asc` or `desc`. Anything else is a `400`.                                                                      |

A non-numeric `limit` or `page` is normally a `400` naming the parameter, so out-of-range is silent while wrong-type is loud.

<Warning>
  **On [`GET /lists/{id}`](/api-reference/simkl/get-list) that validation is not guaranteed.** That endpoint is served from an edge cache which coerces `limit` and `page` itself before deciding what to return. When the request hits a cached entry, a malformed `limit=abc` is **silently replaced with the default and answered `200`** rather than rejected — verified against production.

  So the same malformed request can return `400` or `200` depending only on whether that list happens to be cached. **Validate your own paging input**; do not rely on a `400` to catch it. `direction` is checked verbatim and always rejects, and `GET /lists/user/{userId}` is not edge-cached, so both of those behave predictably.
</Warning>

<Note>
  **The two endpoints validate `sort` differently, on purpose.**

  On [`GET /lists/user/{userId}`](/api-reference/simkl/get-user-lists), `sort` is a fixed set — `updated`, `created`, `name`, `likes`, `followers`, `items`, `popularity` — and anything else is a `400`.

  On [`GET /lists/{id}`](/api-reference/simkl/get-list) it is free-form: an unrecognised value falls back to the list's own stored order rather than erroring. Do not rely on a typo failing loudly there.
</Note>

## Account limits

These are limits on what a user can build, enforced when a list is saved on the website. The read API cannot return them, but they explain why a list stops accepting items.

| Tier | Items per list | Lists | Items across all lists |
| ---- | -------------- | ----- | ---------------------- |
| PRO  | 2,000          | 30    | 60,000                 |
| VIP  | 10,000         | 1,000 | 500,000                |

There are three separate ceilings, and a user can hit any of them independently: too many items in one list, too many lists, or too many items across everything.

## See also

<CardGroup cols={2}>
  <Card title="GET /lists/{id}" icon="list" href="/api-reference/simkl/get-list">
    One list and its items, with sorting and paging.
  </Card>

  <Card title="GET /lists/user/{userId}" icon="user" href="/api-reference/simkl/get-user-lists">
    Every list belonging to one user.
  </Card>

  <Card title="Custom lists guide" icon="book" href="/guides/custom-lists">
    What custom lists are, and how they fit alongside the watchlist.
  </Card>

  <Card title="AUTH V2" icon="shield-halved" href="/api-reference/auth-v2">
    How to get the user token these endpoints require.
  </Card>
</CardGroup>
