I work on OnePassApps, the team behind app.onepassapps.com. This is our own API host, and every number below was measured on it today, 10 November 2026, from outside the browser: signed out, plain HTTPS, no session, no cookie, no writes.
We have written about what our API host answers to a write, and about what the catalogue route holds. This post is about a layer neither one covered: what a query string does to a GET on our API. The short answer is nothing at all.
The short version
Our API host reads no query parameters. On every public route we probed, a GET with a query string and a GET without one returned the same bytes and the same records in the same order. The catalogue route answered all 10 query shapes we tried with the same 43 records.
What I measured
Seven public routes on api.onepassapps.com - /api/products, /api/plans, /api/runtime, /api/health, /api/auth/config, /api/config/feature-flags, /api/voting - each fetched twice: once plain, once with ?page=2&per_page=1&limit=1&offset=5 appended. Fourteen requests, one server, one day.
Every pair came back the same length:
| Route | Plain bytes | With query string |
|---|---|---|
/api/products | 15,650 | 15,650 |
/api/plans | 4,020 | 4,020 |
/api/runtime | 471 | 471 |
/api/health | 410 | 410 |
/api/auth/config | 371 | 371 |
/api/config/feature-flags | 1,771 | 1,771 |
/api/voting | 4,146 | 4,146 |
All 7 pairs were byte-for-byte identical once the per-request id and the clock fields were masked. That is the whole comparison: with the per-request id and the clock fields masked, adding a query string changed nothing at all on any of the seven routes. The clock fields are there because they move on their own: two plain fetches of /api/runtime differ in generatedAt exactly the way two plain fetches of /api/health differ in now, and neither field is affected by the query string.
10 query shapes, one answer
On the catalogue route we tried 10 shapes: no query string, ?page=2, ?page=99, ?per_page=1, ?per_page=5, ?limit=1, ?offset=10, ?page=2&per_page=5, ?page=1&per_page=5, ?zzz=1.
All 10 answered 200 with 15,650 bytes. All 10 carried 43 records. All 10 put signaldesk first and screen-recorder last. With the per-request id masked, all 10 bodies hashed to the same SHA-256, so the 10 answers were one answer sent 10 times.
A client asking for page 2 got page 1. A client asking for one record got all 43. A client sending a parameter we have never heard of got the same 43 records, which means the host does not reject unknown query strings either: it does not read them.
The envelope gives a client nothing to paginate against
All seven routes answer with the same three top-level keys - ok, data and meta - and on every one of them the meta object carries a single key, requestId. Five plain fetches of the catalogue route produced five different ids, so the id is fresh per request and not a handle to a stored response.
There is no total, no page count, no next cursor and no previous link anywhere in the envelope. A client that wanted to walk the catalogue in pages has nothing to walk against and nothing that would tell it the walk was never necessary.
The query string is not part of any cache key
The catalogue route answers with Cache-Control: private, no-store, max-age=0 and Vary: Accept-Encoding, Origin, and it answers with both headers whether or not a query string is attached. So there is no caching argument here either: the response is not cached at all, and the header that names the varying inputs does not name the query string.
What this means for a client
- A query string on our API is inert. Do not build a client that paginates against it, and do not read a short answer as a filter.
- The whole catalogue is one response: 43 records, 11 fields each, 22 of them enabled.
- If you need a slice, slice it yourself after the single fetch.
- The route is uncached, so a client that wants to watch for changes has to make the request every time.
What I did not do
Every answer came from an unauthenticated request, so an authenticated route may answer differently. We probed the seven public GET routes we knew of, not every route the host serves. We sent no body and made no write. One build, one region, one day, and an edge sits in front of the origin in every measurement, so a different point of the network may answer differently. The byte counts are what these seven routes returned today; they are not a promise about future builds.
The parts we have covered already
The document host's own query-string contract, the catalogue route and its 43 records, and the write-method layer each have their own post:
And the app itself, plus the guides that walk through what each one does:
I work on OnePassApps, so this is our own service and our own copy, measured today rather than described from memory.
