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

# Authorize a user

> Step 1 of the OAuth 2.0 authorization-code flow. Redirect the user's browser to this URL on **simkl.com** (not api.simkl.com). Simkl shows a consent screen and, once the user approves, redirects to your `redirect_uri` with `?code=…`.

> ⚠️ **Do not use a WebView on mobile.** Use the system browser or a Custom Tab. WebViews are blocked for security reasons.

#### Parameters

| Param | Required | Notes |
|---|---|---|
| `response_type` | yes | Must be `code`. |
| `client_id` | yes | Your app's `client_id`. |
| `redirect_uri` | conditional | Required for confidential clients and for any app that has a redirect URI registered. Optional only when using **PKCE** *and* your app has no registered redirect URI — in that case Simkl completes the consent flow on simkl.com itself. When sent, must match the URL registered for the app **byte-for-byte**. |
| `state` | no | Random string you generate; echoed back to your `redirect_uri` for **CSRF protection**. Strongly recommended. |
| `code_challenge` | conditional | Required for **PKCE** (public clients without `client_secret`). Base64url-encoded SHA-256 of your `code_verifier`. See the [Public PKCE walkthrough](/api-reference/oauth-pkce). |
| `code_challenge_method` | no | `S256` (default, recommended) or `plain`. Case-sensitive — lowercase variants are silently ignored and your token exchange will then fail with `Wrong Secret`. |

The user is redirected to:

```
YOUR_REDIRECT_URI?code=AUTHORIZATION_CODE&state=YOUR_STATE
```

Exchange the `code` for an `access_token` via [`POST /oauth/token`](/api-reference/simkl/exchange-token). Codes are short-lived; exchange immediately.

<CardGroup cols={2}>
  <Card title="OAuth 2.0 walkthrough" icon="lock" href="/api-reference/oauth" horizontal>
    Confidential-client (server-side) flow with `client_secret`.
  </Card>
  <Card title="Public PKCE walkthrough" icon="shield-keyhole" href="/api-reference/oauth-pkce" horizontal>
    Public-client (mobile / SPA / desktop) flow with `code_verifier` + `code_challenge`.
  </Card>
</CardGroup>



## OpenAPI

````yaml /openapi.json get /oauth/authorize
openapi: 3.1.0
info:
  title: Simkl API
  version: 1.0.0
  description: >-
    The **Simkl API** lets you build apps that track Movies, TV Shows, and Anime
    — scrobble playback, sync watch history, and pull rich metadata.


    All requests use HTTPS and return JSON. The base URL is
    `https://api.simkl.com`.


    **Every request needs three URL parameters and a `User-Agent` header:**


    ```

    /endpoint?client_id=YOUR_CLIENT_ID&app-name=my-app&app-version=1.0

    ```


    See [Headers and required parameters](/conventions/headers) for the full
    reference. Endpoints that read or modify a user's data also need an
    `Authorization: Bearer <token>` header — see [OAuth
    2.0](/api-reference/oauth) or the [PIN flow](/api-reference/pin).


    > ⚠️ **About the auto-rendered cURL examples on each endpoint page:** they
    omit `?client_id=…&app-name=…&app-version=…` from the URL for brevity. **You
    must add them yourself when copy-pasting**, or use the interactive **"Try
    it"** playground (it fills them in for you). This is a Mintlify rendering
    convention — every Mintlify-built API doc behaves the same way.


    **Get started**


    - [Quickstart](/quickstart) — first request in 60 seconds

    - [API rules](/api-rules) — what's allowed, what isn't

    - [Standard media objects](/conventions/standard-media-objects) — the shapes
    every endpoint speaks

    - [Errors](/conventions/errors) — every status code Simkl returns
  contact:
    name: Simkl Developer Support
    url: https://support.simkl.com
  termsOfService: https://simkl.com/about/policies/terms/
  license:
    name: Simkl API Terms of Use
    url: https://simkl.com/about/policies/terms/
  x-logo:
    url: https://i.simkl.com/img_tv/apiary_logo_api.png
    backgroundColor: '#0E5DAB'
    altText: Simkl
servers:
  - url: https://api.simkl.com
    description: Production API
  - url: https://data.simkl.in
    description: CDN for static, public data files (Calendar + Trending). No auth required.
security:
  - clientId: []
  - simklApiKey: []
tags:
  - name: OAuth 2.0
    description: >-
      OAuth 2.0 authorization-code flow for web and mobile apps. The user is
      redirected to Simkl, signs in, approves your app, and is redirected back
      with a `code` you exchange for an `access_token`. Long-lived tokens — no
      refresh-token flow needed.
    externalDocs:
      description: OAuth 2.0 walkthrough
      url: https://api.simkl.org/api-reference/oauth
  - name: PIN
    description: >-
      Device flow for TVs, consoles, smart watches, CLI tools — anywhere typing
      a URL is hard. Show a 5-character code; user enters it on simkl.com/pin;
      you poll for the access token. **No `client_secret` required.**
    externalDocs:
      description: PIN flow walkthrough
      url: https://api.simkl.org/api-reference/pin
  - name: Redirect
    description: >-
      Helper redirects for one-click "mark as watched", trailers, sharing, and
      more.
  - name: Search
    description: Find shows, movies, and anime by ID, text query, file name, or randomly.
    externalDocs:
      description: Search guide
      url: https://api.simkl.org/guides/search
  - name: Movies
    description: >-
      Browse the Simkl movies catalog: details, premieres, top-of-best, and
      genre filters.
  - name: TV
    description: >-
      Browse the Simkl TV catalog: details, episodes, what's airing, premieres,
      top-of-best, and genre filters.
  - name: Anime
    description: >-
      Browse the Simkl anime catalog: details, episodes, what's airing,
      premieres, top-of-best, and genre filters.
  - name: Ratings
    description: >-
      Read Simkl's average community rating, rank, drop rate, and external
      ratings (IMDB, MAL) for any item, or for every item in a user's lists.
  - name: Scrobble
    description: >-
      Report real-time playback to Simkl with `start`, `pause`, and `stop`. At ≥
      80 % progress Simkl marks the item as watched automatically; below 80 %
      the session is saved as a paused playback the user can resume from any
      device.


      See [Standard media objects](/conventions/standard-media-objects) for the
      supported ID keys.


      <!-- IDS_TABLE_START -->


      ### Supported ID keys


      Inside any `ids` object, pass as many of these as you have. Simkl resolves
      to the canonical record.


      | ID key | Type | Example |

      |---|---|---|

      | `simkl` | integer | `49108`. Simkl's canonical ID. Most reliable. |

      | `imdb` | string | `tt1520211` |

      | `tmdb` | integer | `76757` (for TV, specify `type`) |

      | `tvdb` | int / string | `153021` or `the-walking-dead` |

      | `mal` | integer | `4246` (MyAnimeList) |

      | `anidb` | integer | `10846`. Specifying just this is enough for anime
      lookups. |

      | `anilist` | integer | `21` |

      | `kitsu` | integer | `12` |

      | `anisearch` | integer | `2227` |

      | `animeplanet` | string | `one-piece` |

      | `livechart` | integer | `321` |

      | `letterboxd` | string | `the-truman-show` |

      | `netflix` | integer | `70210890` (movie ID) |

      | `traktslug` | string | `john-wick-chapter-4-2023` |


      > 📖 Full reference: [Standard media
      objects](/conventions/standard-media-objects)


      <!-- IDS_TABLE_END -->
    externalDocs:
      description: Scrobble guide
      url: https://api.simkl.org/guides/scrobble
  - name: Sync
    description: >-
      Use Simkl as a cloud backup for the user's watch history and lists
      (Watching, Plan to Watch, On Hold, Dropped, Completed). **Always check
      [`/sync/activities`](/api-reference/simkl/get-activities) first** and sync
      only the lists that have moved.


      All write endpoints accept arrays — batch aggressively. See [Standard
      media objects](/conventions/standard-media-objects) for the supported ID
      keys.


      <!-- IDS_TABLE_START -->


      ### Supported ID keys


      Inside any `ids` object, pass as many of these as you have. Simkl resolves
      to the canonical record.


      | ID key | Type | Example |

      |---|---|---|

      | `simkl` | integer | `49108`. Simkl's canonical ID. Most reliable. |

      | `imdb` | string | `tt1520211` |

      | `tmdb` | integer | `76757` (for TV, specify `type`) |

      | `tvdb` | int / string | `153021` or `the-walking-dead` |

      | `mal` | integer | `4246` (MyAnimeList) |

      | `anidb` | integer | `10846`. Specifying just this is enough for anime
      lookups. |

      | `anilist` | integer | `21` |

      | `kitsu` | integer | `12` |

      | `anisearch` | integer | `2227` |

      | `animeplanet` | string | `one-piece` |

      | `livechart` | integer | `321` |

      | `letterboxd` | string | `the-truman-show` |

      | `netflix` | integer | `70210890` (movie ID) |

      | `traktslug` | string | `john-wick-chapter-4-2023` |


      > 📖 Full reference: [Standard media
      objects](/conventions/standard-media-objects)


      <!-- IDS_TABLE_END -->
    externalDocs:
      description: Sync guide
      url: https://api.simkl.org/guides/sync
  - name: Users
    description: User profile, settings, and watch statistics.
externalDocs:
  description: Simkl API documentation
  url: https://api.simkl.org
paths:
  /oauth/authorize:
    get:
      tags:
        - OAuth 2.0
      summary: Authorize a user
      description: >-
        Step 1 of the OAuth 2.0 authorization-code flow. Redirect the user's
        browser to this URL on **simkl.com** (not api.simkl.com). Simkl shows a
        consent screen and, once the user approves, redirects to your
        `redirect_uri` with `?code=…`.


        > ⚠️ **Do not use a WebView on mobile.** Use the system browser or a
        Custom Tab. WebViews are blocked for security reasons.


        #### Parameters


        | Param | Required | Notes |

        |---|---|---|

        | `response_type` | yes | Must be `code`. |

        | `client_id` | yes | Your app's `client_id`. |

        | `redirect_uri` | conditional | Required for confidential clients and
        for any app that has a redirect URI registered. Optional only when using
        **PKCE** *and* your app has no registered redirect URI — in that case
        Simkl completes the consent flow on simkl.com itself. When sent, must
        match the URL registered for the app **byte-for-byte**. |

        | `state` | no | Random string you generate; echoed back to your
        `redirect_uri` for **CSRF protection**. Strongly recommended. |

        | `code_challenge` | conditional | Required for **PKCE** (public clients
        without `client_secret`). Base64url-encoded SHA-256 of your
        `code_verifier`. See the [Public PKCE
        walkthrough](/api-reference/oauth-pkce). |

        | `code_challenge_method` | no | `S256` (default, recommended) or
        `plain`. Case-sensitive — lowercase variants are silently ignored and
        your token exchange will then fail with `Wrong Secret`. |


        The user is redirected to:


        ```

        YOUR_REDIRECT_URI?code=AUTHORIZATION_CODE&state=YOUR_STATE

        ```


        Exchange the `code` for an `access_token` via [`POST
        /oauth/token`](/api-reference/simkl/exchange-token). Codes are
        short-lived; exchange immediately.


        <CardGroup cols={2}>
          <Card title="OAuth 2.0 walkthrough" icon="lock" href="/api-reference/oauth" horizontal>
            Confidential-client (server-side) flow with `client_secret`.
          </Card>
          <Card title="Public PKCE walkthrough" icon="shield-keyhole" href="/api-reference/oauth-pkce" horizontal>
            Public-client (mobile / SPA / desktop) flow with `code_verifier` + `code_challenge`.
          </Card>
        </CardGroup>
      operationId: get-oauth-authorize
      parameters:
        - name: response_type
          in: query
          description: must be "code"
          required: true
          schema:
            type: string
          example: code
        - $ref: '#/components/parameters/ClientIdQuery'
        - name: redirect_uri
          in: query
          description: >-
            Where Simkl sends the user back after they approve consent. Must
            match a URI pre-registered in your [app
            settings](https://simkl.com/settings/developer/) **byte-for-byte**
            (scheme, host, port, path, trailing slash, casing — all of it).
            Required for confidential-client flows. Optional when using PKCE
            *and* your app has no registered redirect URI — in that case the
            consent page completes the flow on simkl.com directly.
          required: false
          schema:
            type: string
          example: http://yourdomain.com/oauth.html
        - name: state
          in: query
          description: >-
            Random string you generate; Simkl echoes it back unchanged on the
            redirect to your `redirect_uri`. Use this for CSRF protection —
            verify on the redirect that the value matches what you originally
            sent. Strongly recommended for browser-based clients.
          schema:
            type: string
          example: state
        - $ref: '#/components/parameters/AppNameQuery'
        - $ref: '#/components/parameters/AppVersionQuery'
        - $ref: '#/components/parameters/UserAgentHeader'
        - name: code_challenge
          in: query
          required: false
          schema:
            type: string
          example: E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
          description: >-
            PKCE code challenge — base64url-encoded SHA-256 hash of the code
            verifier. Required for the PKCE flow (mobile/desktop/SPA clients
            without `client_secret`). Pair with the matching `code_verifier`
            when exchanging at [`POST
            /oauth/token`](/api-reference/simkl/exchange-token).
        - name: code_challenge_method
          in: query
          required: false
          schema:
            type: string
            enum:
              - S256
              - plain
            default: S256
          example: S256
          description: >-
            Hash method used to derive `code_challenge`. `S256` (SHA-256,
            default) is recommended; `plain` is accepted for legacy clients but
            discouraged.
      responses:
        '302':
          description: >-
            User approved. Browser is redirected to
            `redirect_uri?code=…&state=…`. Exchange the `code` immediately via
            [`POST /oauth/token`](/api-reference/simkl/exchange-token).
          headers:
            Location:
              description: >-
                Your registered `redirect_uri` with `code` and (if you sent it)
                `state` appended.
              schema:
                type: string
                format: uri
                example: >-
                  https://yourdomain.com/oauth.html?code=AUTHORIZATION_CODE&state=YOUR_STATE
      security:
        - simklApiKey: []
      servers:
        - url: https://simkl.com
          description: Authorization is hosted on simkl.com (not api.simkl.com).
components:
  parameters:
    ClientIdQuery:
      name: client_id
      in: query
      required: true
      description: >-
        Your **`client_id`** from your [Simkl developer
        settings](https://simkl.com/settings/developer/). Required on every
        request.
      schema:
        type: string
      example: YOUR_CLIENT_ID
    AppNameQuery:
      name: app-name
      in: query
      required: true
      description: >-
        Short, lowercase identifier for your app (e.g. `plex-scrobbler`,
        `kodi-bridge`). Helps Simkl identify which apps are using the API.
      schema:
        type: string
      example: my-app
    AppVersionQuery:
      name: app-version
      in: query
      required: true
      description: >-
        Your app's current version (e.g. `1.0`, `2.4.1`). Helps Simkl debug
        issues you report.
      schema:
        type: string
      example: '1.0'
    UserAgentHeader:
      name: User-Agent
      in: header
      required: true
      description: >-
        Descriptive identifier for your app, ideally `name/version`. Examples:
        `PlexMediaServer/1.43.1.10540`, `kodi-simkl/0.9.2`, `MyApp/2.4.1
        (https://myapp.com)`.
      schema:
        type: string
      example: my-app/1.0
  securitySchemes:
    clientId:
      type: apiKey
      in: query
      name: client_id
      description: >-
        Preferred form: your `client_id` as a URL query parameter on every
        request. Self-describing in logs and curl commands. See [Headers and
        required parameters](/conventions/headers).
      x-default: YOUR_CLIENT_ID
    simklApiKey:
      type: apiKey
      in: header
      name: simkl-api-key
      description: >-
        Optional alias for the `client_id` query parameter. Simkl accepts your
        `client_id` either as the `simkl-api-key` request header **or** as the
        `?client_id=…` query parameter — pick one. The query-parameter form is
        preferred because it makes the request fully self-describing in URL
        form.
      x-default: YOUR_CLIENT_ID

````