Requests and responses
Section titled “Requests and responses”- Base address:
https://getrefract.app/v1. Every response is JSON, in UTF-8. - Field names are
snake_case. A missing value isnull, never an absent field. - Ignore what you do not know. New fields and new enum values can appear in any release: your client must not
break on them. Removing or renaming a field is a breaking change, and breaking changes only ship under a new
version (
/v2), announced in the changelog withDeprecationandSunsetheaders on the old one.
Every show or movie carries an ids object:
"ids": { "refract": "8b0e5c1a-…", "tmdb": 95396, "imdb": "tt11280740", "tvdb": null }refractis Refract’s own id; use it to ask for one library title (/v1/library/{id}).tmdb,imdbandtvdbare the ids we hold; a missing one isnull.- Always pair
tmdbortvdbwithtype. A TMDB id names a film and a show, and so does a TheTVDB id. - An episode is its show, its
seasonand itsnumber, in TMDB numbering.season0 holds specials. Some anime are numbered differently on TheTVDB; the API always uses TMDB’s numbering.
Shows, movies and anime
Section titled “Shows, movies and anime”type is show or movie. Anime are shows or movies with is_anime: true.
Library statuses
Section titled “Library statuses”| Status | Meaning |
|---|---|
in_progress |
Started, with aired episodes left to watch. |
up_to_date |
Every aired episode watched; more are coming. |
completed |
Finished. For a show: it has ended and every episode is watched. |
planned |
On the watchlist. |
on_hold |
Paused by the member. |
dropped |
Abandoned by the member. |
A rewatch in progress (Revisiting, in the app) is not a status. The title keeps its own status, and carries a
revisit object with the rewatch’s number, its start, its range and its own progress.
Two kinds of dates, never mixed:
-
Instants end in
_atand are RFC 3339 strings in UTC:"2026-10-27T20:41:55.120Z". They say when something happened on Refract’s side: a title added, a rating changed. -
Days the member lived, such as when they watched an episode, are calendar facts:
"watched_at": { "local": "2026-10-27T21:40:00.000000+01:00", "tz": "Europe/Paris" }localis either a day ("2026-10-26") or a local time with its UTC offset, and a time appears only when the member’s clock is known.tzis the IANA zone it was lived in, ornullfor a zone-free day. The whole value isnullwhen the date is unknown. Refract never invents a time it does not know.
These are the dates of Refract’s account export (format 3), so an export and the API always agree.
Caching
Section titled “Caching”Every answer carries an ETag. Send it back as If-None-Match: when nothing changed you get 304 Not Modified
and an empty body, so there is nothing to download again. It still counts against your
rate limit. Answers are
Cache-Control: private, no-cache: keep them on the device, revalidate before reuse, never in a shared cache.
Hidden titles
Section titled “Hidden titles”The API shows what the app shows. Titles TMDB no longer publishes are left out of every list, and so are media other than shows and movies.