Skip to content

Conventions

  • Base address: https://getrefract.app/v1. Every response is JSON, in UTF-8.
  • Field names are snake_case. A missing value is null, 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 with Deprecation and Sunset headers on the old one.

Every show or movie carries an ids object:

"ids": { "refract": "8b0e5c1a-…", "tmdb": 95396, "imdb": "tt11280740", "tvdb": null }
  • refract is Refract’s own id; use it to ask for one library title (/v1/library/{id}).
  • tmdb, imdb and tvdb are the ids we hold; a missing one is null.
  • Always pair tmdb or tvdb with type. A TMDB id names a film and a show, and so does a TheTVDB id.
  • An episode is its show, its season and its number, in TMDB numbering. season 0 holds specials. Some anime are numbered differently on TheTVDB; the API always uses TMDB’s numbering.

type is show or movie. Anime are shows or movies with is_anime: true.

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 _at and 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" }

    local is 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. tz is the IANA zone it was lived in, or null for a zone-free day. The whole value is null when 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.

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.

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.