logo
Queries a collection. Send it with no options to page through everything, or add a filter to match on document contents.
💡 Results are paginated. Keep requesting the next page_number until the response comes back with "eop": true.

Request

method is "listDocuments".
Field
Type
Required
Description
collection
String
Yes
The collection to query.
filter
Object
Optional
Conditions a document must match. Omit to return everything.
sort
Object
Optional
Field-to-direction map. -1 descending, 1 ascending.
page_size
Number
Optional
Documents per page. Defaults to 50, capped at 200.
page_number
Number
Optional
Page to retrieve, starting at 0.
app_id
String
Optional
The app the collection belongs to. Defaults to the bot's own app.
reference
String
Optional
Your id for this request. Echoed back in the response.

Filters

A filter is an object of field conditions, all of which must hold. A bare value means equality:
json
"filter": { "status": "shipped", "total": { "$gte": 100 }, "region": { "$in": ["EG", "AE"] }, "coupon": { "$exists": false } }

Operators

Operator
Matches when the field
Example
bare value
equals the value
{"status": "shipped"}
$eq
equals the value
{"status": {"$eq": "shipped"}}
$ne
does not equal the value
{"status": {"$ne": "cancelled"}}
$gt $gte
is greater than / at least
{"total": {"$gte": 100}}
$lt $lte
is less than / at most
{"total": {"$lt": 50}}
$in
is one of the listed values
{"region": {"$in": ["EG", "AE"]}}
$nin
is none of the listed values
{"region": {"$nin": ["US"]}}
$exists
is present (true) or absent (false)
{"coupon": {"$exists": false}}
$contains
is an array containing the value
{"items": {"$contains": "sku-1"}}
$like
is a string containing the substring
{"name": {"$like": "ali"}}
Nested fields use dots: {"address.city": "Cairo"}.

Notes on matching

Comparisons are typed from the value you send. {"total": {"$gte": 100}} compares numerically; {"name": {"$gte": "m"}} compares as text. Send 100, not "100", when you mean a number — quoting it gives you a string comparison where "9" sorts after "100".
$like matches substrings literally. % and _ in your value are treated as characters, not wildcards.
⚠️ Filtering scans the collection — the document body is not indexed. It stays fast on collections of hundreds to low thousands. If a collection grows large and you query it often, promote the hot field into document_id so you can fetch by id instead.
Not supported in this version: $or / $and nesting, and regular expressions. Every condition in a filter is AND-ed.

Response

listDocumentsResponse

Field
Type
Returned
Description
method
String
Yes
"listDocumentsResponse"
documents
Array
Yes
This page of results. Each entry has document_id and document.
collection
String
Yes
Echoed from the request.
page_number
Number
Yes
The page this result represents.
eop
Boolean
Yes
End of pages. true when there is nothing more to fetch.
app_id
String
Yes
Echoed from the request.
reference
String
Optional
Echoed from the request.

SDKs

SDK
Call
Callback
Java
store.listDocuments(api, collection, filter, sort, pageSize, pageNumber, reference);
onDocumentResponse(DocumentResponse response)
JavaScript
store.listDocuments(api, collection, reference, { filter, sort, pageSize, pageNumber });
onDocumentResponse(response)
Python
store.list_documents(api, collection, reference, filter=…, sort=…, page_size=…, page_number=…)
on_document_response(self, response)
Java also has a short form for an unfiltered first page: store.listDocuments(api, collection, reference).

Example

Request

json
{ "method": "listDocuments", "collection": "orders", "app_id": "90090684293000559", "reference": "123456789", "filter": { "status": "shipped", "total": { "$gte": 100 }, "region": { "$in": ["EG", "AE"] } }, "sort": { "created_at": -1 }, "page_size": 50, "page_number": 0 }
java
JSONObject total = new JSONObject(); total.put("$gte", 100); JSONObject filter = new JSONObject(); filter.put("status", "shipped"); filter.put("total", total); JSONObject sort = new JSONObject(); sort.put("created_at", -1); DocumentStore.getInstance() .listDocuments(api, "orders", filter, sort, 50, 0, "123456789"); // in the callback @Override public void onDocumentResponse(DocumentResponse response) { for (DocumentResponse.Entry entry : response.getDocuments()) { System.out.println(entry.getDocumentId() + " -> " + entry.getDocument()); } if (!Boolean.TRUE.equals(response.isEndOfPages())) { // request response.getPageNumber() + 1 } }
javascript
const store = require('nandbox-bot-api/src/util/DocumentStore') store.listDocuments(api, 'orders', '123456789', { filter: { status: 'shipped', total: { $gte: 100 } }, sort: { created_at: -1 }, pageSize: 50, pageNumber: 0 }) // in the callback nCallBack.onDocumentResponse = response => { response.documents.forEach(e => console.log(e.document_id, e.document)) if (!response.eop) { // request response.page_number + 1 } }
python
from nandboxbots.util.DocumentStore import DocumentStore DocumentStore.get_instance().list_documents( api, "orders", "123456789", filter={"status": "shipped", "total": {"$gte": 100}}, sort={"created_at": -1}, page_size=50, page_number=0, ) # in the callback def on_document_response(self, response): for entry in response.documents: print(entry.document_id, entry.document) if not response.eop: pass # request response.page_number + 1

Response

json
{ "method": "listDocumentsResponse", "collection": "orders", "app_id": "90090684293000559", "reference": "123456789", "page_number": 0, "eop": true, "documents": [ { "document_id": "42", "document": { "status": "shipped", "total": 149.5, "region": "EG", "created_at": "2026-07-27T10:00:00Z" } }, { "document_id": "43", "document": { "status": "shipped", "total": 100, "region": "AE", "created_at": "2026-07-26T18:30:00Z" } } ] }