Flick API · Beta

API Reference

Read your own Flick data — profile, reviews, watchlist, lists — and write reviews to your own account, over plain JSON. Every endpoint below has a built-in Try it console — paste a key once and send live requests right from the docs.

This API is in beta.

Endpoints, response shapes, limits, and policies can and will change without notice while we iterate — pin nothing, handle errors defensively, and expect breaking changes. Feedback, feature requests, and bug reports: Discord.

Stored only in this browser tab and sent only to http://localhost:8080. No key yet? Create one.

Introduction

The Flick API is scoped to yourdata: an API key acts on behalf of the account that created it. There is no OAuth and no access to other users' accounts — keys read and write the key owner's data only.

All endpoints live under https://flickmovies.com/api/beta and accept and return JSON.

OpenAPI is the industry-standard format for describing a REST API in a single machine-readable file — every path, parameter, and response shape. We publish ours at /api/beta/openapi.json. Point a tool at it to generate a typed client in your language (openapi-generator, Speakeasy, etc.), import it into Postman or Insomnia, or feed it to an AI assistant — no hand-copying of endpoints. The OpenAPI link in the top nav opens /api/beta/docs, a Swagger UI rendered from that same schema where you can browse and try endpoints against the live server. (For most things, the inline Try it consoles below are quicker.)

API access requires a Flick Pro subscription. By using the API you agree to the API Terms of Service.

Base URL
https://flickmovies.com/api/beta

Authentication

Create an API key on the API keys page — sign in with the same email or phone you use in the Flick app. Keys look like flick_sk_… and the full key is shown once, at creation; store it somewhere safe.

Pass the key on every request, either as a bearer token or an X-API-Key header. You can hold up to 5 active keys and revoke any of them at any time from the same page — revocation takes effect within about 30 seconds.

Keys are personal and non-transferable. Don't embed them in client-side code or public repos — anyone with your key can read and write your Flick data. If a key leaks, revoke it immediately.

Either header works
curl https://flickmovies.com/api/beta/me \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"

# or
curl https://flickmovies.com/api/beta/me \
  -H "X-API-Key: flick_sk_YOUR_KEY"

Rate limits

Default limits are 60 requests/minute and 5,000 requests/day per key (subject to change during beta — reach out on Discord if you need more). Daily windows reset at UTC midnight.

Exceeding a limit returns 429 with a Retry-After header (seconds). Back off and retry after that long.

X-RateLimit-LimitRequests allowed per minute
X-RateLimit-RemainingRemaining in the current minute window
X-RateLimit-ResetUnix time when the minute window resets
X-RateLimit-Limit-DayRequests allowed per day (UTC days)
X-RateLimit-Remaining-DayRemaining in the current UTC day
Retry-AfterOn 429 only — seconds to wait before retrying
On every response
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 41
X-RateLimit-Reset: 1781200560
X-RateLimit-Limit-Day: 5000
X-RateLimit-Remaining-Day: 4817
429 · rate_limited
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded for the minute window. Retry after 12 seconds."
  }
}

Errors

Every error — auth, validation, rate limiting, server faults — uses the same envelope: an error object with a stable machine-readable code and a human-readable message. Match on the code, not the message.

400invalid_requestMalformed body or query params
401invalid_api_keyMissing, malformed, or unknown key
401api_key_revokedKey was revoked
403pro_requiredAccount no longer has Pro
404not_foundResource doesn't exist or isn't yours
404media_not_foundNo such title on TMDB
429rate_limitedRate limit exceeded — back off per Retry-After
500internal_errorSomething broke on our side
503api_disabledAPI temporarily disabled (check Discord)
Error envelope
{
  "error": {
    "code": "media_not_found",
    "message": "No movie found on TMDB for tmdb_id 999999999."
  }
}

Pagination & media

List endpoints paginate with ?page=1&limit=50 (limit max 100) and return a { data, page, limit, total, has_more } envelope. Pagination style may change to cursors before GA.

Titles are identified by their TMDB id plus a media_type of movie, tv, tv_season, or tv_episode. For seasons and episodes, pass the show's TMDB id along with season_number (and episode_number for episodes).

Everywhere a title appears in a response it uses the same media object. The season_number, episode_number, and show_title fields are present only for seasons and episodes.

Paginated envelope
{
  "data": [ … ],
  "page": 1,
  "limit": 50,
  "total": 412,
  "has_more": true
}
Media object
{
  "tmdb_id": "1396",
  "type": "tv_episode",
  "title": "Pilot",
  "year": 2008,
  "poster_url": "https://image.tmdb.org/t/p/w500/…",
  "season_number": 1,
  "episode_number": 1,
  "show_title": "Breaking Bad"
}

Profile

Get your profile

GET/api/beta/me

The profile of the account that owns the API key.

curl https://flickmovies.com/api/beta/me \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "id": "abc123",
  "username": "moviebuff",
  "display_name": "Movie Buff",
  "profile_picture_url": "https://…",
  "is_pro": true
}

Media

Resolve a title to a TMDB id

GET/api/beta/resolve

Best-effort lookup from loose metadata you already have — a title, optionally a year and type — to the TMDB id and media_type the rest of the API expects.

Handy before a review write: most catalogs and spreadsheets carry a title and year, not a TMDB id. Resolve once, then POST to /me/reviews with the result.

This is a fuzzy match, not an authority. match is the strongest candidate (or null when nothing plausible turns up); candidates holds up to five ranked alternatives. Each carries a score (0–1) and a confidence of high, medium, or low — verify before trusting a low.

Only movie and tv are resolvable here. For a specific season or episode, resolve the show, then pass season_number / episode_number to the review endpoints.

Query parameters

titlestringrequired· 1–200 chars

The title to search for.

yearinteger

Release (or first-air) year. Narrows same-named titles.

media_typestring

Narrow to movie or tv. Omit to search both.

curl "https://flickmovies.com/api/beta/resolve?title=The%20Matrix&year=1999&media_type=movie" \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "query": { "title": "The Matrix", "year": 1999, "media_type": "movie" },
  "match": {
    "tmdb_id": "603",
    "media_type": "movie",
    "title": "The Matrix",
    "year": 1999,
    "poster_url": "https://image.tmdb.org/t/p/w500/…",
    "score": 0.97,
    "confidence": "high"
  },
  "candidates": [
    {
      "tmdb_id": "603",
      "media_type": "movie",
      "title": "The Matrix",
      "year": 1999,
      "poster_url": "https://image.tmdb.org/t/p/w500/…",
      "score": 0.97,
      "confidence": "high"
    }
  ]
}
No confident match
curl "https://flickmovies.com/api/beta/resolve?title=asdkjfhqwoeiu" \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"

Reviews

List your reviews

GET/api/beta/me/reviews

Your reviews, newest first.

source is app (logged in the app), import (Letterboxd/CSV import), or api (created via this API).

Query parameters

pageinteger· default 1

Page number, 1-indexed.

limitinteger· default 50, max 100· default 50

Items per page.

curl "https://flickmovies.com/api/beta/me/reviews?page=1&limit=2" \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "data": [
    {
      "id": "5f0c4f7a-…",
      "media": {
        "tmdb_id": "603",
        "type": "movie",
        "title": "The Matrix",
        "year": 1999,
        "poster_url": "https://image.tmdb.org/t/p/w500/…"
      },
      "rating": 9.2,
      "review": "Still holds up.",
      "watched_date": "2026-06-01T00:00:00+00:00",
      "created_at": "2026-06-02T18:21:09.123456+00:00",
      "tags": [],
      "source": "app"
    }
  ],
  "page": 1,
  "limit": 2,
  "total": 412,
  "has_more": true
}

Create a review

POST/api/beta/me/reviews

Add one review to your account.

Re-POSTing an identical review (same title, rating, text, watched date) is deduplicated and returns 200 with deduplicated: true instead of creating a copy.

Reviews created via the API are tagged source: "api" and show up in the app like imported reviews. Rewatch numbering and rating-tier ordering normalize the next time you edit in the app — a known beta limitation.

Body parameters

tmdb_idstringrequired

The TMDB id of the title. For seasons and episodes, pass the show’s TMDB id.

media_typeenumrequired

What kind of title this is.

movietvtv_seasontv_episode
season_numberintegerrequired if media_type is tv_season or tv_episode

Season being reviewed.

episode_numberintegerrequired if media_type is tv_episode

Episode being reviewed.

ratingnumber· 0–10

Your rating. Omit for an unrated log.

reviewstring· max 10,000 chars

Review text.

watched_datedate· YYYY-MM-DD

When you watched it. Not in the future.

tagsarray of strings· max 20 tags, 64 chars each

Tags to attach.

Endpoint errors

404media_not_foundThe tmdb_id / media_type combination doesn’t exist on TMDB
curl -X POST https://flickmovies.com/api/beta/me/reviews \
  -H "Authorization: Bearer flick_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tmdb_id": "603",
    "media_type": "movie",
    "rating": 9,
    "review": "Whoa.",
    "watched_date": "2026-06-01"
  }'
Response · 201
{
  "created": true,
  "deduplicated": false,
  "review": {
    "id": "5f0c4f7a-…",
    "media": {
      "tmdb_id": "603",
      "type": "movie",
      "title": "The Matrix",
      "year": 1999,
      "poster_url": "https://image.tmdb.org/t/p/w500/…"
    },
    "rating": 9,
    "review": "Whoa.",
    "watched_date": "2026-06-01",
    "created_at": "2026-06-10T18:21:09+00:00",
    "tags": [],
    "source": "api"
  }
}
Review a TV season
curl -X POST https://flickmovies.com/api/beta/me/reviews \
  -H "Authorization: Bearer flick_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tmdb_id": "1396",
    "media_type": "tv_season",
    "season_number": 1,
    "rating": 9.5
  }'
Review a TV episode
curl -X POST https://flickmovies.com/api/beta/me/reviews \
  -H "Authorization: Bearer flick_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tmdb_id": "1396",
    "media_type": "tv_episode",
    "season_number": 1,
    "episode_number": 1,
    "rating": 9
  }'

Create reviews in batch

POST/api/beta/me/reviews/batch

Add up to 50 reviews in one request.

Items are processed independently; the response reports per-item outcomes in input order.

Duplicates — against your existing reviews or within the batch — are skipped and counted in deduplicated_count.

There is no all-or-nothing rollback: check each item’s created / error instead of the HTTP status.

Body parameters

reviewsarray of objectsrequired· 1–50 items

The reviews to create.

each item

tmdb_idstringrequired

The TMDB id of the title. For seasons and episodes, pass the show’s TMDB id.

media_typeenumrequired

What kind of title this is.

movietvtv_seasontv_episode
season_numberintegerrequired if media_type is tv_season or tv_episode

Season being reviewed.

episode_numberintegerrequired if media_type is tv_episode

Episode being reviewed.

ratingnumber· 0–10

Your rating. Omit for an unrated log.

reviewstring· max 10,000 chars

Review text.

watched_datedate· YYYY-MM-DD

When you watched it. Not in the future.

tagsarray of strings· max 20 tags, 64 chars each

Tags to attach.

Endpoint errors

404media_not_foundReported per item in results[].error, not as a top-level status
curl -X POST https://flickmovies.com/api/beta/me/reviews/batch \
  -H "Authorization: Bearer flick_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reviews": [
      {
        "tmdb_id": "550",
        "media_type": "movie",
        "rating": 8
      },
      {
        "tmdb_id": "1396",
        "media_type": "tv",
        "rating": 10,
        "review": "Peak TV."
      }
    ]
  }'
Response · 200
{
  "created_count": 2,
  "deduplicated_count": 0,
  "failed_count": 0,
  "results": [
    { "index": 0, "created": true, "deduplicated": false, "review_id": "…", "error": null },
    { "index": 1, "created": true, "deduplicated": false, "review_id": "…", "error": null }
  ]
}

Watchlist

List your watchlist

GET/api/beta/me/watchlist

Your watchlist, most recently added first.

Query parameters

pageinteger· default 1

Page number, 1-indexed.

limitinteger· default 50, max 100· default 50

Items per page.

curl https://flickmovies.com/api/beta/me/watchlist \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "data": [
    {
      "media": {
        "tmdb_id": "693134",
        "type": "movie",
        "title": "Dune: Part Two",
        "year": 2024,
        "poster_url": "https://image.tmdb.org/t/p/w500/…"
      },
      "added_at": "2026-05-30T02:11:00+00:00"
    }
  ],
  "page": 1,
  "limit": 50,
  "total": 23,
  "has_more": false
}

Lists

List your lists

GET/api/beta/me/lists

Custom lists you own. The built-in watchlist is excluded — use /me/watchlist for that.

curl https://flickmovies.com/api/beta/me/lists \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "data": [
    {
      "id": "list_abc",
      "title": "Best of the 90s",
      "description": "",
      "is_ranked": true,
      "num_media": 25,
      "created_at": "2026-01-12T09:00:00+00:00",
      "updated_at": "2026-06-01T17:30:00+00:00"
    }
  ]
}

List items in a list

GET/api/beta/me/lists/{list_id}/items

Items in one of your lists. Ranked lists come back in rank order.

Returns 404 not_found for lists you don’t own.

Path parameters

list_idstringrequired

A list id from GET /me/lists.

Query parameters

pageinteger· default 1

Page number, 1-indexed.

limitinteger· default 50, max 100· default 50

Items per page.

Endpoint errors

404not_foundThe list doesn’t exist or belongs to someone else
curl https://flickmovies.com/api/beta/me/lists/list_abc/items \
  -H "Authorization: Bearer flick_sk_YOUR_KEY"
Response · 200
{
  "data": [
    {
      "media": {
        "tmdb_id": "550",
        "type": "movie",
        "title": "Fight Club",
        "year": 1999,
        "poster_url": "https://image.tmdb.org/t/p/w500/…"
      },
      "rank": 1,
      "notes": "",
      "added_at": "2026-01-12T09:00:00+00:00"
    }
  ],
  "page": 1,
  "limit": 50,
  "total": 25,
  "has_more": false
}

Changelog & support

  • 2026-06 — Initial beta: own-data reads (profile, reviews, watchlist, lists) and review writes (single + batch).

This beta exists to learn what you want to build. Feature requests, bug reports, and questions all go to our Discord or hello@flickmovies.com.