Retrieves a paginated list of users filtered by the provided query parameters.
Results are sorted by createdAt in descending order.
The response format defaults to JSON, but CSV can be requested via the Content-Type header.
count semantics: the count field in the response is the retailer's
total user count, not the filtered total. The divergence grows as
filters (status, teams, role, ...) narrow the result set — clients
must not use count to size filtered result pages.
status field semantics (read): the field remains visible to any
authenticated user of the retailer (parity with the current behavior; a
future restriction stays possible behind a flag). On the DynamoDB-served
paths, items persisted before the presence pipeline have no stored
status and are answered as LOGGEDOUT. On the Parse-served paths (the
name text-search fallback and order=-totalActiveChats), a missing
status is currently answered as absent, not LOGGEDOUT — that default
is not applied there.
Technical users (per-retailer flag user-listing-exclude-technical-users):
when active, users flagged apiUser/botUser/supportUser are excluded
from every listing by default. The pre-existing opt-in parameters
apiUser, botUser and supportUser then require the admin role
(403 otherwise). Only the literal value true is privileged —
apiUser=false is the explicit negation of the default and never
returns 403. With the flag off the behavior is unchanged (technical
users listed as before, no admin gate). The technical flags themselves
are not part of the response payload.
Index selection matrix (status × disabled × cannotStartConversation —
residual conditions are filtered in memory, recursive pagination refills
short pages):
| status | disabled | cannotStartConversation | Index | In-memory residual |
|---|---|---|---|---|
| ✓ | ✓ | — | user-status-index (composite key) | — |
| ✓ | ✓ | ✓ | user-status-index | cannotStartConversation |
| ✓ | — | any | query-retailer-index | status (+ template) |
| — | ✓ | ✓ | user-disabled-template-index | — |
| — | ✓ | — | user-disabled-index | — |
| — | — | ✓ | user-template-index | — |
| — | — | — | query-retailer-index | — |
teams is always filtered in memory (intersection with the denormalized
teams[].id array).
Sparse GSI note: user-status-index only contains items that already
received a presence event (or were written after the presence pipeline).
Until the base converges, a server-side status=LOGGEDOUT query may miss
users who never generated an event — reads default those items to
LOGGEDOUT, and the in-memory residual path applies the same default.
Request examples
GET /v1/users?status=LOGGEDIN&disabled=false&limit=20
GET /v1/users?teams=team_a&teams=team_b&role=service
GET /v1/users?status=AWAY&teams=team_a&tokenPagination=eyJwayI6...
GET /v1/users?botUser=true # admin only when the exclusion flag is on
GET /v1/users?status=ONLINE # 400 — outside the enum| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||