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

# Quickstart

> From zero to writing user data in 5 minutes — see real data, get an access_token, read a watchlist, and mark a movie as watched.

<Note>
  **This site has three tabs** — switch via the header bar at the top of the page.
</Note>

<CardGroup cols={3}>
  <Card title="Documentation" icon="book-open">
    **You're here.** Concepts, walkthroughs, and recipes.
  </Card>

  <Card title="API Reference" icon="terminal" href="/api-reference/introduction">
    Every endpoint with parameter docs and a try-it-now playground.
  </Card>

  <Card title="Changelog" icon="clock-rotate-left" href="/changelog">
    What's new and what changed across the API and the docs.
  </Card>
</CardGroup>

By the end of this page you'll have:

* Made your first API call in **10 seconds** with no setup
* Created an app and obtained an `access_token` for a user
* Read the user's "Watching" anime watchlist
* Marked **Inception** as completed in that user's history

Total time: about 5 minutes.

<Note>
  **Before you ship to users, read [API rules](/api-rules).** It's a short page covering attribution, free-for-non-commercial terms, and the threshold where a commercial license kicks in. Skipping it is the most common reason apps get throttled or revoked.
</Note>

## 0. See real Simkl data right now

Trending data files are public CDN — no token required. Like every Simkl URL, the call still includes the standard `client_id` / `app-name` / `app-version` params plus a `User-Agent` header for consistency:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl "https://data.simkl.in/discover/trending/today_100.json?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
  -H "User-Agent: my-app-name/1.0"
```

You'll get back the top 100 trending titles across Movies, TV, and Anime. These [data files](/api-reference/trending) update on a schedule and are perfect for "What's hot right now" surfaces.

The rest of this guide reads and writes **user-specific** data, which needs an `access_token` on top of the API key.

## 1. Get an API key

<Steps>
  <Step title="Create a Simkl account">
    [Sign up](https://passport.simkl.com/register/) — free.
  </Step>

  <Step title="Create an application">
    Go to [your developer settings](https://simkl.com/settings/developer/) and create a new app. You'll receive a `client_id` (and a `client_secret` for confidential clients).

    Pick an `app-name` (lowercase identifier like `plex-scrobbler`) and an `app-version` (e.g. `1.0`). These three values — `client_id`, `app-name`, `app-version` — go on **every** API request as URL parameters. See [Headers and required parameters](/conventions/headers).
  </Step>
</Steps>

## 2. Make your first authenticated catalog call

Catalog endpoints (Movies, TV, Anime metadata) need the API key but no user token. Fetch the **Game of Thrones** summary by its Simkl ID — `tv/17465` is heavily cached, so this is the cheapest endpoint to hit while you're testing:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl "https://api.simkl.com/tv/17465?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
    -H "User-Agent: my-app-name/1.0"
  ```

  ```js JavaScript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const params = new URLSearchParams({
    client_id:     'YOUR_CLIENT_ID',
    'app-name':    'my-app-name',
    'app-version': '1.0',
  });
  const r = await fetch(`https://api.simkl.com/tv/17465?${params}`, {
    headers: { 'User-Agent': 'my-app-name/1.0' },
  });
  console.log(await r.json());
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import requests
  r = requests.get(
      'https://api.simkl.com/tv/17465',
      params={
          'client_id':   'YOUR_CLIENT_ID',
          'app-name':    'my-app-name',
          'app-version': '1.0',
      },
      headers={'User-Agent': 'my-app-name/1.0'},
  )
  print(r.json())
  ```
</CodeGroup>

You'll get back a JSON object with the full record — `title`, `year`, `ids`, `overview`, `genres`, `ratings`, `poster`, `fanart`, `trailers`, `users_recommendations`, and more. Summary endpoints (`/movies/:id`, `/tv/:id`, `/anime/:id`, plus the `/episodes/:id` variants) return this rich shape by default — no `?extended=full` needed. If anything errors out, [Errors and status codes](/conventions/errors) lists every code with cause / fix — `412` typically means a typo in `client_id`.

## 3. Pick an authentication flow

To touch **user-specific** data (watchlist, history, ratings), you need a user `access_token`. Two flows:

| Your app runs on...                                   | Use           |
| ----------------------------------------------------- | ------------- |
| iOS, Android, web, desktop — anywhere a browser opens | **OAuth 2.0** |
| TV, console, watch, CLI tool, media-server plugin     | **PIN**       |

<Tip>
  Full per-platform recommendations and multi-language samples (Swift, Kotlin, etc.) live in [Authentication](/authentication) and [Auth — full guide](/api-reference/auth).
</Tip>

## 4. Get an access\_token

<Tabs>
  <Tab title="OAuth 2.0">
    Send the user to the consent page (note the host: **`simkl.com`**, not `api.simkl.com`):

    ```
    https://simkl.com/oauth/authorize
      ?response_type=code
      &client_id=YOUR_CLIENT_ID
      &redirect_uri=YOUR_REDIRECT_URI
      &app-name=my-app-name
      &app-version=1.0
    ```

    After approval, Simkl redirects to `YOUR_REDIRECT_URI?code=AUTH_CODE`. Exchange the code on your server (this one hits **`api.simkl.com`**):

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST "https://api.simkl.com/oauth/token?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
      -H "Content-Type: application/json" \
      -H "User-Agent: my-app-name/1.0" \
      -d '{
        "code":          "AUTH_CODE",
        "client_id":     "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET",
        "redirect_uri":  "YOUR_REDIRECT_URI",
        "grant_type":    "authorization_code"
      }'
    ```

    The response is `{"access_token": "...", "token_type": "bearer", "scope": "public", "expires_in": 157680000}` — a \~5-year token. Save it; treat any future 401 as "user revoked, re-run the flow".

    Public clients (mobile apps, SPAs, desktop binaries) should use **PKCE** instead of shipping `client_secret` — see [PKCE for public clients](/api-reference/auth#pkce-for-public-clients).
  </Tab>

  <Tab title="PIN flow">
    Request a code:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl "https://api.simkl.com/oauth/pin?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
      -H "User-Agent: my-app-name/1.0"
    ```

    Show the returned `user_code` to the user and tell them to visit `https://simkl.com/pin`. Then poll until they approve:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl "https://api.simkl.com/oauth/pin/USER_CODE?client_id=YOUR_CLIENT_ID&app-name=my-app-name&app-version=1.0" \
      -H "User-Agent: my-app-name/1.0"
    ```

    Respect the response's `interval` between polls (default 5 sec). When the user approves, the next poll returns `result: "OK"` with an `access_token`.
  </Tab>
</Tabs>

## 5. Read the user's library

With the `access_token` in hand, fetch the user's "Watching" anime watchlist:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl "https://api.simkl.com/sync/all-items/anime/watching?extended=full&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 ACCESS_TOKEN"
  ```

  ```js JavaScript theme={"theme":{"light":"github-light","dark":"vesper"}}
  const params = new URLSearchParams({
    extended:      'full',
    client_id:     'YOUR_CLIENT_ID',
    'app-name':    'my-app-name',
    'app-version': '1.0',
  });
  const r = await fetch(
    `https://api.simkl.com/sync/all-items/anime/watching?${params}`,
    {
      headers: {
        'User-Agent':    'my-app-name/1.0',
        'Authorization': `Bearer ${accessToken}`,
      },
    },
  );
  console.log(await r.json());
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import requests
  r = requests.get(
      'https://api.simkl.com/sync/all-items/anime/watching',
      params={
          'extended':    'full',
          'client_id':   'YOUR_CLIENT_ID',
          'app-name':    'my-app-name',
          'app-version': '1.0',
      },
      headers={
          'User-Agent':    'my-app-name/1.0',
          'Authorization': f'Bearer {access_token}',
      },
  )
  print(r.json())
  ```
</CodeGroup>

<Note>
  **Per-type watchlist rules:** TV and anime accept all five statuses (`watching`, `plantowatch`, `hold`, `dropped`, `completed`). Movies skip `watching` and `hold` (single-session content). See [Watchlist statuses](/conventions/list-statuses) for the full matrix.
</Note>

## 6. Write something back

Mark **Inception** as completed in the user's library. Sending the title, year, and multiple IDs at once gives Simkl the best chance of matching the right record — handy when one of the external IDs is missing or out of date in Simkl's catalog:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://api.simkl.com/sync/history?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 ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "movies": [{
      "title": "Inception",
      "year": 2010,
      "ids": {
        "simkl": 472214,
        "imdb":  "tt1375666",
        "tmdb":  "27205"
      }
    }]
  }'
```

A `201 Created` response means the movie is now in the user's history. To undo it later, hit [`POST /sync/history/remove`](/api-reference/simkl/remove-from-history) with the same payload shape.

<Tip>
  **Send everything you have.** If you only know the IMDB ID, send just `imdb`. If you have a Simkl ID, that's the fastest match. When you have title + year + a couple of external IDs, Simkl walks the IDs in order and falls back to title/year fuzzy match — so the more you send, the more reliably the right title gets credited. Full key list: [Supported ID keys](/conventions/standard-media-objects#supported-id-keys).
</Tip>

<Tip>
  `POST /sync/history` is the right endpoint for "Mark as watched" buttons and one-shot history writes. For real-time playback tracking with progress percentages, see the [Scrobble guide](/guides/scrobble).
</Tip>

## Token reminder

Your `access_token` is **long-lived** — store it once, reuse it on every call. It only stops working when the user revokes your app from [Connected Apps settings](https://simkl.com/settings/connected-apps/), which surfaces as a `401 Unauthorized`. Detect that and re-run the auth flow from Step 4.

## Useful side-trips

<CardGroup cols={3}>
  <Card title="Cheapest way to resolve an IMDB ID" icon="hashtag" href="/api-reference/redirect">
    `GET /redirect?to=simkl&imdb=tt1375666` 301-redirects to the Simkl URL. Parse the ID from the path, no JSON to read.
  </Card>

  <Card title="Trending without auth" icon="fire" href="/api-reference/trending">
    Pre-built JSON for "Most Watched" surfaces — Today / Week / Month, per type. CDN-cached, free.
  </Card>

  <Card title="Calendar without auth" icon="calendar" href="/api-reference/calendar">
    Upcoming TV / anime / movie releases as static JSON. Per-month archives going back 12 months.
  </Card>
</CardGroup>

## What's next

<CardGroup cols={3}>
  <Card title="Sync guide" icon="arrows-rotate" href="/guides/sync">
    Read and write watchlists, history, and ratings — the full sync loop.
  </Card>

  <Card title="Scrobble guide" icon="play" href="/guides/scrobble">
    Real-time playback tracking with start / pause / stop / checkin.
  </Card>

  <Card title="Mark as watched" icon="circle-check" href="/guides/mark-as-watched">
    Single-call recipes that don't go through scrobble.
  </Card>

  <Card title="Search guide" icon="magnifying-glass" href="/guides/search">
    Find titles by ID, text, file name, or randomly.
  </Card>

  <Card title="Standard media objects" icon="film" href="/conventions/standard-media-objects">
    The Movie / Show / Anime / Episode shapes every endpoint speaks.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/conventions/errors">
    Every status code with cause / fix / example.
  </Card>

  <Card title="Auth — full reference" icon="shield-halved" href="/api-reference/auth">
    Multi-language samples (Swift / Kotlin / Node / Python), PKCE, common pitfalls.
  </Card>

  <Card title="API Reference" icon="terminal" href="/api-reference/introduction">
    Every endpoint with an interactive playground.
  </Card>

  <Card title="Changelog" icon="clock-rotate-left" href="/changelog">
    What's new across endpoints, schemas, and the docs.
  </Card>
</CardGroup>
