DEV Community

OnePassApps
OnePassApps

Posted on Edited on

MovieMatcherAI Guest Data: Two Apps, Two Upstreams, One Shared Snapshot

Full disclosure: I work on OnePassApps.

MovieMatcherAI is one of the two hosted apps in the OnePassApps membership - the seven studios run inside your browser tab, this one runs on our servers. This post is about the layer a signed-out visitor meets first: the guest data endpoint that fills the movie cards before there is any account, where it fetches from, and what it refuses to do.

Everything here was measured from outside the browser with plain HTTPS on 7 November 2026 - no account, no cookie, no API key, one GET at a time.

The endpoint that answers before you sign in

GET https://api.onepassapps.com/api/guest-data/movie-tracker

HTTP 200, content-type: application/json, 2,764 bytes of body. No session, no cookie, no token - an anonymous request is enough, which is what makes it the guest path.

The body is one envelope with three top-level keys - ok, data, meta - and data holds nine keys: appId, label, cacheKey, fetchedAt, staleAt, expiresAt, cache, source and payload.

The catalogue: two apps, two different upstreams

GET https://api.onepassapps.com/api/guest-data is the index over those guest endpoints - 200, 954 bytes, and data.apps holds exactly two entries.

  • signaldesk, labelled NewsFlow: source.type is existing-cache, the upstream URL is https://toolpass.ai/apps/newsflow, and the response cap is 2,097,152 bytes.
  • movie-tracker, labelled MovieMatcherAI: source.type is public-api, the source id is ghibli-films, the source label is Studio Ghibli public films API, the upstream URL is https://ghibliapi.vercel.app/films, and the response cap is 524,288 bytes.

The timings are identical on both: refreshIntervalMs 1,800,000 (30 minutes), staleWhileRevalidateMs 21,600,000 (6 hours), timeoutMs 8,000. The caps differ by a factor of four - 2,097,152 against 524,288.

Both upstream descriptors carry the same accept header: application/json, text/plain;q=0.9, text/html;q=0.8, */*;q=0.5 - a JSON source that ranks HTML above the wildcard.

The receipt the upstream leaves behind

Inside source, the endpoint records what it saw upstream: checkedAt 2026-11-07T15:49:23.567Z, httpStatus 200, contentType application/json; charset=utf-8, byteLength 32,416, bodyHash cf4300a1, lastError null.

32,416 bytes of upstream JSON against a 524,288-byte cap is 6.18% of the ceiling - the cap is a safety limit, not a description of the payload.

Three cards, and the guest boundary written out

payload.items holds exactly three entries: ghibli-castle-in-the-sky (Castle in the Sky), ghibli-my-neighbor-totoro (My Neighbor Totoro) and ghibli-spirited-away (Spirited Away). Each one carries the subtitle Studio Ghibli API, the URL https://ghibliapi.vercel.app/films, a sourceType of web and its own tags.

payload.headline reads Public film metadata watchlist preview, and payload.description reads Guest movie cards come from public film metadata and stay isolated from authenticated watchlists.

payload.metrics is three rows, each with a label, a value and a note:

  • Titles - Public metadata - No user diary or watchlist entries in guest mode
  • Mutations - Sign-in required - Add/remove/rate actions remain account-backed
  • Fallback - Last-known-good - Cached source records stay available during provider failures

payload.readOnlyActions says it in two sentences: Add, edit, delete, import, export, connect-provider, and download actions require a signed-in account. and Guest sample data is never written to a user workspace or mixed into authenticated state.

payload.sourceNotes is three lines, and one of them decides how the three cards should be read: Primary source: Studio Ghibli public films API for non-sensitive film metadata., Authenticated MovieMatcherAI search still uses the configured server-side provider/cache. and Source checked successfully at 2026-11-07T15:49:23.567Z; guests share cache bucket 996703.

So the three Ghibli titles are the guest preview, and the endpoint states outright that signed-in search runs against a different provider and a different cache.

One snapshot for every guest

Two fetches 4.3 seconds apart returned byte-identical payloads: the same fetchedAt of 2026-11-07T15:49:23.567Z, the same cacheKey of guest:movie-tracker:ghibli-films:996703, the same bodyHash of cf4300a1, the same cache.cacheStatus of fresh and the same cache.intervalBucket of 996703. A third fetch 5 minutes 47 seconds after the first returned the same
snapshot, the same bodyHash of cf4300a1 and the same weak ETag.

staleAt is 2026-11-07T16:19:23.567Z - 30 minutes after the fetch - and expiresAt is 2026-11-07T22:19:23.567Z, six and a half hours after it. Between those two stamps a guest can be served the snapshot while a refresh runs behind it.

The headers say: do not store this

cache-control: private, no-store, max-age=0, x-robots-tag: noindex, cf-cache-status: DYNAMIC, vary: Accept-Encoding, Origin, and x-ratelimit-limit: 120 - the remaining count read 115 on one request and 118 on another.

Nothing on this path may be cached by a browser or an edge, and nothing on it may be indexed: a guest's copy of the catalogue is one shared snapshot, not a per-person record.

Limits

  • One build, one network, one day (7 November 2026), plain HTTPS, no browser, no account, no cookie.
  • Two fetches of the movie-tracker endpoint, not a series, and no conditional request.
  • The byte counts, the hash, the timestamps and the cache bucket are a snapshot; the timestamps and the bucket move.
  • I did not sign in, so nothing here describes what an authenticated session returns - the payload itself says that path uses a different provider and cache.
  • I did not call the Studio Ghibli API directly, so the upstream is described only as this endpoint recorded it.
  • The rate limit was read from a header, not tested.

If you want to see the app itself: MovieMatcherAI and its guide.

Top comments (0)