Full disclosure: I work on OnePassApps, the team behind app.onepassapps.com.

Two of the OnePassApps apps fill their first screen from a shared guest endpoint, so a signed-out visitor sees something before making an account. I measured those two in a separate post (https://dev.to/onepassapps/moviematcherai-guest-data-two-apps-two-upstreams-one-shared-snapshot-23je) - where they fetch from and what the payload carries. This one is about everything the same endpoint answers when the app is not one of the two.

Everything below was measured from outside the browser with plain HTTPS on 7 November 2026: one request at a time, no cookie, no session, no API key, one network.

The endpoint, and the 22 slugs on the site

GET https://api.onepassapps.com/api/guest-data/<appId>

The site serves 22 app routes today. Asking the guest endpoint for each of those 22 slugs returns three different shapes, and the split does not follow the URL.

  • movie-tracker answers HTTP 200 with the guest payload.
  • newsflow answers HTTP 400 with error.code VALIDATION_ERROR, even though NewsFlow is one of the two apps that does have guest data.
  • The other 20 slugs answer HTTP 404 with error.code NOT_FOUND.

All 20 of the 404s carry the same message: "Guest data source is not configured for that app." That is the honest answer for the browser-local studios and for the hosted apps that need no server-side seed data - the endpoint is not broken for them, it simply has nothing to serve.

Why newsflow is not a valid app id

The index at GET https://api.onepassapps.com/api/guest-data lists exactly two entries, and their ids are signaldesk and movie-tracker. NewsFlow's public slug on the site is newsflow; its API app id is signaldesk.

So the slug a visitor sees in the URL is not the id the API knows:

  • GET /api/guest-data/newsflow -> 400, error.code VALIDATION_ERROR, error.message "Guest data source is not configured for that app.", and error.details.issues[0].path ["appId"] with the issue message "Invalid input".
  • GET /api/guest-data/signaldesk -> 200, 11002 bytes of body, data.appId "signaldesk", data.label "NewsFlow".

The 400 body and the 404 body carry the same human-readable message and different codes, so the only way to tell "that app has no guest source" from "that is not an app id at all" is to read error.code - or to read the index first.

One envelope, one request id

Every answer - 200, 400 and 404 - uses the same three top-level keys: ok, data or error, and meta. The meta object carries one field, requestId, and it looks like req_ followed by twelve characters. The x-request-id header on the same response carries the same value, and it changes on every request.

The 404 body for a missing source is 147 bytes. The 400 body for a wrong app id is 238 bytes, because it carries the extra details.issues array.

The method matters

POST /api/guest-data/movie-tracker answers 404, not 405. There is no separate error for "wrong verb" on this route - a wrong method simply does not match the route, and you get the same not-found shape the unknown slugs get.

The headers every answer carries

The successful answer is content-type: application/json, cache-control: private, no-store, max-age=0, and it adds the machine-readable ones:

  • x-ratelimit-limit: 120, with x-ratelimit-remaining counting down - 94 on the first of three calls in a row, 93 on the second and 92 on the third.
  • x-concurrency-limit: 64, with x-concurrency-remaining reporting the free slots.
  • x-request-id with the same req_... value as meta.requestId.
  • x-robots-tag: noindex, plus x-content-type-options: nosniff, x-frame-options: SAMEORIGIN, x-permitted-cross-domain-policies: none, x-xss-protection: 0, x-dns-prefetch-control: off and x-download-options: noopen.

The rejected answers carry the same headers as the successful one, and they spend the same budget. In one sweep of the three shapes in a row - the 200, then the 400, then the 404 - x-ratelimit-remaining came back 94, 93 and 92, one lower each time. A client that spends its budget on bad app ids spends it against the same 120-request budget.

What the browser is allowed to do

An OPTIONS preflight from the app's own origin answers 204 with the API host's fixed cross-origin policy - the same allow-methods, allow-headers, expose-headers and max-age values on every route (I measured that policy across the host on 4 November: https://dev.to/onepassapps/the-origin-allow-list-of-apionepassappscom-two-allowed-origins-one-fixed-preflight-and-40la).

The limits of this measurement

One build, one network, plain HTTPS, 7 November 2026. The counters move with every request, so the remaining numbers above are a snapshot, not a contract. I made no request with a session or a key, I did not test any other origin, and I did not test the endpoint under load. The successful body I measured was 2764 bytes.

The app this is about, and the guide for it:

https://app.onepassapps.com/apps/newsflow?utm_source=devto&utm_medium=post&utm_campaign=guest-data-contract&utm_content=newsflow-link

https://app.onepassapps.com/guides/newsflow?utm_source=devto&utm_medium=post&utm_campaign=guest-data-contract&utm_content=guides-link

I work on OnePassApps. If you want the two configured guest sources measured the same way, the earlier post has them.