AI Integration Quick Reference
AI Integration Quick Reference
The two-phase contract
Pass a fetch listener as the optional argument and each read fires up to two callbacks, always in this order:1
Cached phase
The SDK delivers a page from the local cache first. It normally fires even when the page is empty — an empty cached page is indistinguishable from a cache miss, by design. Render it right away. Some reads skip this phase entirely, such as a blocked-users read with a search keyword; see When the cached page is empty.
2
Server phase
After a successful server response, the SDK delivers the server’s copy for the same slice and writes it through to the cache before the callback. Reconcile your displayed list against it. (Blocked users are the exception: their server page is delivered but not written to the cache. The cached blocked-users list is kept current by the SDK itself.)
- Offline, the read ends with an error. After the cached page, a read whose request gets no answer settles with
onErrorcarrying codeFAILED_TO_FETCH. A real server error reachesonErrorunchanged. The call always settles. Start the next fetch on a request object only after the previous one has returned: a second fetch started while one is running gets no cached page, and for messages, threads, reactions and the notification feed it ends withonErrorwith codeREQUEST_IN_PROGRESS. - The server phase never fires offline. It fires only on a genuine server response. Never treat a cached page as “end of history”; an empty cached page only means the end of the cached window.
- The Promise still settles too. Passing a listener does not replace the returned Promise: it settles on the server outcome, so it also rejects offline. If you use only the listener, add a
.catch()to avoid an unhandled rejection. Consume the result from one channel, not both.
With offline support off, these listeners behave like the classic Promise: the cached phase never fires, and the server result arrives in
onServer…. Nothing changes until you enable offline (see Enable Offline Support). Requires SDK 4.3.0 or later.Read messages
MessagesRequest supports both directions. fetchPrevious pages toward older messages; fetchNext pages toward newer ones. Both take a MessageFetchListener.
- TypeScript
- JavaScript
Read conversations
ConversationsRequest pages with fetchNext, taking a ConversationFetchListener.
- TypeScript
- JavaScript
Read the other lists
Every remaining list read accepts the same two-phase listener. Each listener is constructed from an object with cached/server callbacks of the matching type plusonError.
The call shape is identical to the conversations example above — swap the request, the listener, and the callback names.
- TypeScript
- JavaScript
For
ReactionsRequest, use one request object per direction: an object caches only the first direction it fetches, and its cached phase stays empty in the other direction. Users, groups, members, banned members, reactions, and the notification feed are served from a recorded copy of each request (up to maxSnapshotQueries distinct requests, each kept for snapshotTtlDays), so a list you never opened online is empty offline. See the Configuration & API Reference.Read a single item
getConversation and getMessageDetails each accept a two-phase listener as a final argument. Unlike the list reads, the cached callback fires only when the item is cached — never with an empty or null object. A cache miss goes straight to the server phase online, or straight to onError offline.
- TypeScript
- JavaScript
Merge the two phases
The server phase replaces the same slice — it is a reconcile, not a second batch. Render the cached page straight away, then on the server phase diff it into your displayed list keyed by the item’s stable id (message id, conversation id, uid, guid). Do not append the server page to the cached one.When the cached page is empty
The cache answers a read only if every filter on it can be computed locally. A single server-only filter makes the whole cached phase come back empty (or not fire at all), with no error and no warning, while the server phase still answers in full. The guiding rule is better empty than wrong. The most common server-only filter issetSearchKeyword, which blanks the cached phase on any request that carries a search keyword (threads, reactions and the notification feed never carry one). Other examples are hasLinks, updatesOnly and setInteractionGoalCompletedOnly on MessagesRequest, setting a UID and a GUID together (one sender’s messages in a group), and the status filters (UsersRequest.setStatus, GroupMembersRequest.setStatus) on the entity lists. setUpdatedAfter is a paging input, not a filter.