{"openapi":"3.1.1","info":{"title":"Refract API","version":"1.0.0","summary":"Read a Refract member's shows, movies and anime.","description":"Guides, quickstart and error pages: https://getrefract.app/developers. Every endpoint acts for one member, who approved your app or created the personal key you send. Fields are snake_case; clients must ignore fields and enum values they do not know.","termsOfService":"https://getrefract.app/terms","contact":{"name":"Refract","url":"https://getrefract.app/support"}},"servers":[{"url":"https://getrefract.app","description":"Production","x-internal":false}],"tags":[{"name":"Profile","description":"Who the credential acts for."},{"name":"Library","description":"Titles the member tracks, and the watchlist."},{"name":"History","description":"What the member watched, and when."},{"name":"Ratings","description":"The member's ratings, 1 to 10."},{"name":"Lists","description":"Lists the member owns."}],"externalDocs":{"description":"Developer portal","url":"https://getrefract.app/developers"},"paths":{"/v1/me":{"get":{"operationId":"getMe","summary":"Get the member","description":"The member who approved the credential: who your app is acting for.","tags":["Profile"],"security":[{"bearer":[]},{"oauth2":["profile:read"]}],"x-required-scope":"profile:read","parameters":[],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Member"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `profile:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/library":{"get":{"operationId":"listLibrary","summary":"List the library","description":"Shows and movies in the member's library, in a stable order. Filter by type, status, anime or rewatch. Titles TMDB no longer publishes are left out, as in the app.","tags":["Library"],"security":[{"bearer":[]},{"oauth2":["library:read"]}],"x-required-scope":"library:read","parameters":[{"in":"query","name":"type","schema":{"$ref":"#/components/schemas/MediaType"}},{"in":"query","name":"status","schema":{"$ref":"#/components/schemas/LibraryStatus"}},{"in":"query","name":"anime","schema":{"description":"`true` keeps only anime, `false` leaves them out.","type":"string","enum":["true","false"]},"description":"`true` keeps only anime, `false` leaves them out."},{"in":"query","name":"revisiting","schema":{"description":"`true` keeps only titles with a rewatch in progress.","type":"string","enum":["true","false"]},"description":"`true` keeps only titles with a rewatch in progress."},{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `library:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/library/{id}":{"get":{"operationId":"getLibraryItem","summary":"Get a library title","description":"One title of the library, by its `ids.refract`. Answers 404 when the title is not in the library.","tags":["Library"],"security":[{"bearer":[]},{"oauth2":["library:read"]}],"x-required-scope":"library:read","parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"The `ids.refract` of the work, or the list's `id`."},"required":true,"description":"The `ids.refract` of the work, or the list's `id`."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryItem"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `library:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found for this member (`NOT_FOUND`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/watchlist":{"get":{"operationId":"listWatchlist","summary":"List the watchlist","description":"Titles the member plans to watch: the library entries whose status is `planned`.","tags":["Library"],"security":[{"bearer":[]},{"oauth2":["library:read"]}],"x-required-scope":"library:read","parameters":[{"in":"query","name":"type","schema":{"$ref":"#/components/schemas/MediaType"}},{"in":"query","name":"anime","schema":{"description":"`true` keeps only anime, `false` leaves them out.","type":"string","enum":["true","false"]},"description":"`true` keeps only anime, `false` leaves them out."},{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `library:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/history/episodes":{"get":{"operationId":"listEpisodeHistory","summary":"List watched episodes","description":"Every episode the member has watched, grouped by show then in episode order. Each carries the day it was watched when known, and how many times it was watched again.","tags":["History"],"security":[{"bearer":[]},{"oauth2":["history:read"]}],"x-required-scope":"history:read","parameters":[{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EpisodeWatchPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `history:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/history/movies":{"get":{"operationId":"listMovieHistory","summary":"List movie plays","description":"Every time the member watched a movie, rewatches included, each with the day it was watched when known.","tags":["History"],"security":[{"bearer":[]},{"oauth2":["history:read"]}],"x-required-scope":"history:read","parameters":[{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoviePlayPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `history:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/ratings":{"get":{"operationId":"listRatings","summary":"List ratings","description":"The member's ratings of shows, movies and episodes, on a 1 to 10 scale.","tags":["Ratings"],"security":[{"bearer":[]},{"oauth2":["ratings:read"]}],"x-required-scope":"ratings:read","parameters":[{"in":"query","name":"target","schema":{"type":"string","enum":["show","movie","episode"]}},{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `ratings:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists":{"get":{"operationId":"listLists","summary":"List the member's lists","description":"Lists the member owns, smart lists included.","tags":["Lists"],"security":[{"bearer":[]},{"oauth2":["lists:read"]}],"x-required-scope":"lists:read","parameters":[{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `lists:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/lists/{id}/items":{"get":{"operationId":"listListItems","summary":"List the titles in a list","description":"Titles in one of the member's lists, in the list's order. A smart list answers 422 `SMART_LIST_UNSUPPORTED`: its titles are computed from its filters and are not served in v1.","tags":["Lists"],"security":[{"bearer":[]},{"oauth2":["lists:read"]}],"x-required-scope":"lists:read","parameters":[{"in":"query","name":"limit","schema":{"description":"Items per page, 1 to 200. A larger value is lowered to 200.","example":50,"default":50,"type":"integer","minimum":1,"maximum":10000,"format":"int32"},"description":"Items per page, 1 to 200. A larger value is lowered to 200."},{"in":"query","name":"cursor","schema":{"description":"`next_cursor` from the previous page, passed back as it came.","type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_-]+$"},"description":"`next_cursor` from the previous page, passed back as it came."},{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"The `ids.refract` of the work, or the list's `id`."},"required":true,"description":"The `ids.refract` of the work, or the list's `id`."}],"responses":{"200":{"description":"OK","headers":{"ETag":{"required":true,"description":"Send it back as `If-None-Match` to get a 304 when nothing changed.","schema":{"type":"string","maxLength":64,"pattern":"^W\\/\".+\"$","description":"Send it back as `If-None-Match` to get a 304 when nothing changed."}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}},"Link":{"description":"The next page, as `<url>; rel=\"next\"`.","schema":{"description":"The next page, as `<url>; rel=\"next\"`.","type":"string","maxLength":2048,"pattern":"^<https:\\/\\/.+>; rel=\"next\"$"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListItemPage"}}}},"304":{"description":"Not modified since the ETag you sent: an empty body, nothing to download again. It counts against the rate limit like any request."},"400":{"description":"A parameter is invalid, or the cursor was changed (`INVALID_REQUEST`, `INVALID_CURSOR`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"The key or token is missing, expired or revoked (`INVALID_TOKEN`).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The credential lacks the `lists:read` scope (`INSUFFICIENT_SCOPE`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found for this member (`NOT_FOUND`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"A smart list's titles are not served in v1 (`SMART_LIST_UNSUPPORTED`).","headers":{"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Too many requests for this credential (`RATE_LIMITED`). Wait the seconds in `Retry-After`.","headers":{"Retry-After":{"required":true,"schema":{"type":"string","maxLength":6,"pattern":"^\\d+$","example":"17"}},"RateLimit":{"required":true,"description":"Quota left in the current window (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"Quota left in the current window (IETF draft).","example":"\"api-v1\";r=118;t=42"}},"RateLimit-Policy":{"required":true,"description":"The quota policy (IETF draft).","schema":{"type":"string","maxLength":256,"pattern":"^\".+\";","description":"The quota policy (IETF draft).","example":"\"api-v1\";q=120;w=60"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Something went wrong on our side (`SERVER_ERROR`). Retry later; quote the `request_id`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"components":{"schemas":{"MediaType":{"type":"string","enum":["show","movie"],"description":"A show or a movie. Anime is either, with `is_anime` set."},"LibraryStatus":{"type":"string","enum":["in_progress","up_to_date","completed","planned","on_hold","dropped"],"description":"Where the title sits in the member's library. `planned` is the watchlist. A show is `up_to_date` when every aired episode is watched but more are coming, `completed` when it has ended and every episode is watched. New values may appear."},"Member":{"type":"object","properties":{"id":{"type":"string","example":"3f2a9c4e-6b1d-4e8a-9c27-5d0b8e41f6a2"},"username":{"example":"florent","type":["string","null"]},"display_name":{"example":"Florent","type":["string","null"]},"avatar_url":{"type":["string","null"]},"bio":{"type":["string","null"]},"country":{"description":"ISO 3166-1 alpha-2.","example":"FR","type":["string","null"]},"locale":{"type":"string","example":"fr"},"timezone":{"type":"string","description":"IANA time zone the member's dates are lived in.","example":"Europe/Paris"},"profile_url":{"example":"https://getrefract.app/u/florent","type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the account was created. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"}},"required":["id","username","display_name","avatar_url","bio","country","locale","timezone","profile_url","created_at"],"additionalProperties":false,"description":"The member who approved the credential."},"Problem":{"type":"object","properties":{"type":{"type":"string","description":"A page of the developer portal that explains the error.","example":"https://getrefract.app/developers/errors/invalid-token"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},"code":{"type":"string","description":"Stable machine code, UPPER_SNAKE_CASE.","example":"INVALID_TOKEN"},"detail":{"type":"string"},"request_id":{"description":"Quote it when you contact us.","type":"string"},"errors":{"description":"One entry per invalid parameter.","maxItems":50,"type":"array","items":{"type":"object","properties":{"detail":{"type":"string"},"parameter":{"type":"string"},"pointer":{"type":"string"}},"required":["detail"],"additionalProperties":false}}},"required":["type","title","status","code"],"additionalProperties":false,"description":"An error, as RFC 9457 problem details (`application/problem+json`)."},"LibraryPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/LibraryItem"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"LibraryItem":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/MediaType"},"is_anime":{"type":"boolean"},"ids":{"$ref":"#/components/schemas/Ids"},"title":{"description":"The title in the member's language and title setting.","example":"Severance","type":["string","null"]},"original_title":{"description":"The original-language title.","example":"Severance","type":["string","null"]},"year":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"example":2022},"status":{"$ref":"#/components/schemas/LibraryStatus"},"rewatch_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Times the member finished the title again.","example":0,"format":"int32"},"added_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the title entered the library. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the library entry last changed. A rating alone does not move it. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},"progress":{"anyOf":[{"$ref":"#/components/schemas/LibraryProgress"},{"type":"null"}],"description":"Shows only; `null` for a movie."},"revisit":{"anyOf":[{"$ref":"#/components/schemas/Revisit"},{"type":"null"}],"description":"`null` unless a rewatch is in progress."}},"required":["type","is_anime","ids","title","original_title","year","status","rewatch_count","added_at","updated_at","progress","revisit"],"additionalProperties":false},"Ids":{"type":"object","properties":{"refract":{"type":"string","description":"Refract's id for the work.","example":"8b0e5c1a-4f2d-4b7e-9a31-2c6d0f5e9b14"},"tmdb":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"description":"TMDB id. Pair it with `type`: a TMDB id names a film and a show.","example":95396},"imdb":{"example":"tt11280740","type":["string","null"]},"tvdb":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"description":"TheTVDB id. Pair it with `type`, like `tmdb`.","example":null}},"required":["refract","tmdb","imdb","tvdb"],"additionalProperties":false,"description":"Every id Refract holds for the work. A missing id is `null`."},"LibraryProgress":{"type":"object","properties":{"watched_episodes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Episodes watched at least once.","example":13,"format":"int32"},"last_watched":{"anyOf":[{"$ref":"#/components/schemas/EpisodeRef"},{"type":"null"}]},"last_watched_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the member last marked an episode. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},{"type":"null"}]}},"required":["watched_episodes","last_watched","last_watched_at"],"additionalProperties":false,"description":"Where the member is in a show. Aired counts and the next episode belong to Up next."},"EpisodeRef":{"type":"object","properties":{"season":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Season number, TMDB numbering. `0` holds specials.","example":2,"format":"int32"},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Episode number in the season, TMDB numbering.","example":4,"format":"int32"}},"required":["season","number"],"additionalProperties":false,"description":"An episode's place in its show."},"Revisit":{"type":"object","properties":{"run_number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"2 for the first rewatch, then 3, and so on. The first watch is run 1.","example":2,"format":"int32"},"started_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When this rewatch started. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},"start":{"anyOf":[{"$ref":"#/components/schemas/EpisodeRef"},{"type":"null"}],"description":"First episode of the rewatch. `null` = the show's first episode."},"end":{"anyOf":[{"$ref":"#/components/schemas/EpisodeRef"},{"type":"null"}],"description":"Last episode the member chose for the rewatch. `null` = no chosen end."},"watched_episodes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Episodes watched again in this rewatch.","example":5,"format":"int32"},"skipped_episodes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},"total_episodes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"description":"Aired episodes the rewatch covers, when known."}},"required":["run_number","started_at","start","end","watched_episodes","skipped_episodes","total_episodes"],"additionalProperties":false,"description":"A rewatch in progress (Revisiting in the app). It is laid over the title, which keeps its own status."},"WatchlistPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/LibraryItem"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"EpisodeWatchPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/EpisodeWatch"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"EpisodeWatch":{"type":"object","properties":{"show":{"$ref":"#/components/schemas/Work"},"episode":{"$ref":"#/components/schemas/EpisodeRef"},"episode_tmdb_id":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]},"watched_at":{"anyOf":[{"$ref":"#/components/schemas/CalendarFact"},{"type":"null"}]},"rewatch_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Times the member watched the episode again.","format":"int32"},"is_special":{"type":"boolean"},"runtime_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]}},"required":["show","episode","episode_tmdb_id","watched_at","rewatch_count","is_special","runtime_minutes"],"additionalProperties":false,"description":"An episode the member has watched."},"Work":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/MediaType"},"is_anime":{"type":"boolean"},"ids":{"$ref":"#/components/schemas/Ids"},"title":{"description":"The title in the member's language and title setting.","example":"Severance","type":["string","null"]},"original_title":{"description":"The original-language title.","example":"Severance","type":["string","null"]},"year":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"example":2022}},"required":["type","is_anime","ids","title","original_title","year"],"additionalProperties":false,"description":"A show or a movie."},"CalendarFact":{"type":"object","properties":{"local":{"type":"string","description":"The member's own calendar. Either a day (`2026-10-26`) or a local time with its UTC offset (`2026-10-27T21:40:00.000000+01:00`); a time appears only when the member's clock is known.","example":"2026-10-27T21:40:00.000000+01:00"},"tz":{"description":"IANA time zone the local value was lived in. `null` for a zone-free day.","example":"Europe/Paris","type":["string","null"]}},"required":["local","tz"],"additionalProperties":false,"description":"A date the member lived, exactly as Refract knows it. The whole object is `null` when the date is unknown."},"MoviePlayPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/MoviePlay"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"MoviePlay":{"type":"object","properties":{"id":{"type":"string","description":"Stable id of this play."},"movie":{"$ref":"#/components/schemas/Work"},"kind":{"type":"string","enum":["first_watch","rewatch"],"description":"The first time the member watched it, or a rewatch."},"watched_at":{"anyOf":[{"$ref":"#/components/schemas/CalendarFact"},{"type":"null"}]}},"required":["id","movie","kind","watched_at"],"additionalProperties":false,"description":"One time the member watched a movie."},"RatingPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/Rating"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"Rating":{"type":"object","properties":{"target":{"type":"string","enum":["show","movie","episode"]},"value":{"type":"integer","minimum":1,"maximum":10,"description":"1 to 10. The app shows half stars: 7 is 3.5 stars.","example":8,"format":"int32"},"work":{"anyOf":[{"$ref":"#/components/schemas/Work"},{"type":"null"}],"description":"The rated show or movie. `null` for an episode."},"episode":{"anyOf":[{"type":"object","properties":{"show_tmdb_id":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]},"season":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]},"number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]},"episode_tmdb_id":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}]}},"required":["show_tmdb_id","season","number","episode_tmdb_id"],"additionalProperties":false},{"type":"null"}],"description":"The rated episode. `null` for a show or a movie."},"completed_on":{"anyOf":[{"$ref":"#/components/schemas/CalendarFact"},{"type":"null"}],"description":"The day the member finished what they rated, when they said so."},"rated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the rating was first given. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the rating last changed. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"}},"required":["target","value","work","episode","completed_on","rated_at","updated_at"],"additionalProperties":false},"ListPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/List"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"List":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Best of 2025"},"description":{"type":["string","null"]},"visibility":{"type":"string","description":"`public`, `followers` or `private`. New values may appear.","example":"public"},"is_smart":{"type":"boolean","description":"A smart list is computed from filters; its items are not served in v1."},"item_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},"url":{"description":"Public page of the list, when it has one.","type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the list was created. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the list last changed. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"}},"required":["id","name","description","visibility","is_smart","item_count","url","created_at","updated_at"],"additionalProperties":false,"description":"A list the member owns."},"ListItemPage":{"type":"object","properties":{"data":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/ListItem"}},"next_cursor":{"description":"Pass it as `cursor` to get the next page. `null` on the last page.","type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"],"additionalProperties":false},"ListItem":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/MediaType"},"is_anime":{"type":"boolean"},"ids":{"$ref":"#/components/schemas/Ids"},"title":{"description":"The title in the member's language and title setting.","example":"Severance","type":["string","null"]},"original_title":{"description":"The original-language title.","example":"Severance","type":["string","null"]},"year":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"format":"int32"},{"type":"null"}],"example":2022},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Order in the list, ascending.","format":"int32"},"note":{"type":["string","null"]},"added_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the title was added to the list. RFC 3339, UTC.","example":"2026-10-27T20:41:55.120Z"}},"required":["type","is_anime","ids","title","original_title","year","position","note","added_at"],"additionalProperties":false}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"A personal key (`rfk_…`) created in the app, or an OAuth access token issued for this API."},"oauth2":{"type":"oauth2","description":"Sign in with Refract: OAuth 2.1, authorization code with PKCE (S256). Devices without a keyboard use the device code grant. Access tokens are signed JWTs following RFC8725 (JWT best current practices): asymmetric signatures (keys at /api/auth/jwks), audience and expiry checked.","flows":{"authorizationCode":{"authorizationUrl":"https://getrefract.app/api/auth/oauth2/authorize","tokenUrl":"https://getrefract.app/api/auth/oauth2/token","refreshUrl":"https://getrefract.app/api/auth/oauth2/token","scopes":{"profile:read":"See the member's profile: username, display name, avatar.","library:read":"See the member's library, watchlist and lists of titles in progress.","library:write":"Change the member's library (arrives with writes).","history:read":"See what the member watched and when.","history:write":"Mark episodes and movies watched (arrives with writes).","ratings:read":"See the member's ratings.","ratings:write":"Rate titles (arrives with writes).","lists:read":"See the member's lists.","lists:write":"Change the member's lists (arrives with writes)."},"x-usePkce":"SHA-256"}}}}}}