Read users in bulk mode
POST/user-ext-srv/bulkread/users
The Bulk Read API allows you to retrieve large volumes of user data efficiently. It supports advanced filtering, cursor-based pagination via searchAfter, and consistent data snapshots using Point-In-Time (pit) queries.
Key Concepts
- Cursor-Based Pagination (
searchAfter):- Requires a
sortfieldto be specified in the request (e.g.,updatedTimeorsub). - Every user record in the response contains a
sortarray. - To fetch the next page, pass the complete, unmodified
sortarray of the last user in the current response assearchAfterin the subsequent request.
- Requires a
- Data Type & Formatting Requirement:
searchAfterMUST be passed as a native JSON array (e.g.,[1629375844777, "b8c4d2e1-8f3a-4e2b-9a1c-5d6e7f8a9b0c"]).- Never pass
searchAfteras a stringified array (e.g.,"searchAfter": "[1629375844777, \"b8c4d2e1-8f3a-4e2b-9a1c-5d6e7f8a9b0c\"]"). Passing a stringified array string will result in API request parsing failures.
- Mixed-Array Cursor Structure &
sortfield=subException:- The
sortcursor is a mixed-type JSON array containing values for the primary sort field and tie-breakers (e.g.,[timestamp, sub]). - When sorting by fields like
updatedTime, cidaas automatically appendssubas a second element in thesortarray to guarantee deterministic ordering across identical timestamps (e.g.,[1629375844777, "b8c4d2e1-8f3a-4e2b-9a1c-5d6e7f8a9b0c"]). - Exception (
sortfield=sub): Whensortfieldis set directly tosub("sortfield": "sub"), thesortarray contains only a single string element (e.g.,["b8c4d2e1-8f3a-4e2b-9a1c-5d6e7f8a9b0c"]) becausesubis already unique. - Always pass the complete
sortarray unchanged insearchAfter(do not omit or truncate tie-breaker elements).
- The
- Point-In-Time (PIT): Enabling a PIT session creates a consistent data snapshot. This ensures all pagination requests see the exact same data state as it existed when the session was initiated, preventing duplicate or missing records caused by concurrent data updates during export.
End-to-End Pagination Flow Example
1. Initial Request (First Page)
POST /user-ext-srv/bulkread/users
{
"sortfield": "updatedTime",
"descending": true,
"size": 2
}
2. API Response (First Page)
{
"success": true,
"status": 200,
"data": [
{
"sub": "user-001",
"updatedTime": 1700000000000,
"sort": [1700000000000, "user-001"]
},
{
"sub": "user-002",
"updatedTime": 1699999900000,
"sort": [1699999900000, "user-002"]
}
]
}
3. Subsequent Request (Next Page)
Extract the complete sort array from the last user ([1699999900000, "user-002"]) and pass it as searchAfter:
POST /user-ext-srv/bulkread/users
{
"sortfield": "updatedTime",
"descending": true,
"size": 2,
"searchAfter": [1699999900000, "user-002"]
}
Format Note:
- Correct (JSON Array):
"searchAfter": [1699999900000, "user-002"]- Incorrect (Stringified):
"searchAfter": "[1699999900000, \"user-002\"]"
4. Completion
Repeat until the API returns an HTTP 204 No Content status.
Usage with Point-In-Time (PIT)
- Initial Request: Include
sortfieldand apitobject with akeepAliveduration (in minutes).\{"sortfield": "updatedTime","pit": \{"keepAlive": "5"\}\} - Extract PIT ID: The response will include a
pitId.\{"users": [...],"pitId": "gcSHBAM2Y2lkYWFz..."\} - Subsequent Requests: Provide the last user's complete
sortarray assearchAfterand thepitIdasidinside thepitobject.\{"sortfield": "updatedTime","pit": \{"keepAlive": "5","id": "gcSHBAM2Y2lkYWFz..."\},"searchAfter": [1629375844777, "8589940405"]\} - Completion: Continue the loop until the API returns an HTTP 204 No Content status.
Request
Responses
- 200
- 204
- 400
- 401
OK
No Content
Bad Request
Unauthorized