GET /app/{orgCode}/list/{entity} is the query layer. It picks its engine per request: DynamoDB for structural queries (always available, immediately consistent) and OpenSearch for full-text search, arbitrary field filters, and facets (when search is enabled for the entity).
Common query parameters
GET /list/order default list
GET /list/order?sortby=name sort by a structural field
GET /list/order?status=active filter by a field
GET /list/order?price=100&price_op=gt range filter
GET /list/order?q=urgent full-text search (OpenSearch)
GET /list/order?facets=status|category bucket counts
GET /list/order?pagesize=20&nexttoken=… cursor pagination
GET /list/order?view=compact apply a named view Which engine runs
A query that uses only structural fields (name, created_at, updated_at, created_by, updated_by, parent key, owner field) always runs on DynamoDB. The moment you add ?q=, ?facets=, or a filter on a non-structural field, OpenSearch is used — if it's enabled for the entity.
GET /list/order -> DDB primary scan
?sortby=name -> DDB NameIndex
?created_by=alice -> DDB (structural)
?{parentKey}=val -> DDB ParentIndex
?q=urgent -> OpenSearch (full-text)
?status=active -> OpenSearch if enabled, else DDB filter
?facets=status -> OpenSearch Search is opt-in per entity
Full-text and facets need OpenSearch enabled. With it off, a non-structural filter falls back to a best-effort DynamoDB filter; ?q= and facets are unavailable. Structural filters and sorting always work without it.
Scoping a list
- Owner-scoped — if the entity has an owner index, a plain
GET /list/{entity}returns only the caller's records. - `?all=true` — skip the owner filter and return all of the org's records (needs a broad ACL).
- `?owner=user456` — filter to a specific owner (needs a broad ACL).
- Parent-scoped —
?{parentKey}={value}returns only children of that parent.
ACL applies to both engines
The authorizer checks list{entity} before the handler runs and sets a mandatory workspace scope. Search never widens what a user is allowed to see.
Pagination & counts
Both engines paginate by cursor: pass the nexttoken from the previous response to fetch the next page (?pagesize= up to 500). OpenSearch can also return a true totalcount; DynamoDB returns the page count only.