curl --request POST \
--url https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query \
--header 'Content-Type: application/json' \
--header 'X-DOMO-Developer-Token: <api-key>' \
--data '
{
"content.region": {
"$eq": "West"
}
}
'import requests
url = "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query"
payload = { "content.region": { "$eq": "West" } }
headers = {
"X-DOMO-Developer-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-DOMO-Developer-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({'content.region': {$eq: 'West'}})
};
fetch('https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'content.region' => [
'$eq' => 'West'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-DOMO-Developer-Token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query"
payload := strings.NewReader("{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-DOMO-Developer-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query")
.header("X-DOMO-Developer-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-DOMO-Developer-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}"
response = http.request(request)
puts response.read_body[
{
"id": "a8428d64-a01d-49b2-9144-ddeec001acf8",
"datastoreId": "39b88a97-8247-4c0d-ba1d-8ed78d1a6680",
"collectionId": "232e6d6c-46e9-49b6-a137-8933f0f05999",
"syncRequired": true,
"owner": "870010733",
"createdBy": "870010733",
"createdOn": "2026-06-23T20:58:06.567Z",
"updatedOn": "2026-06-23T23:36:13.177Z",
"updatedBy": "870010733",
"content": {
"campaignName": "Q2 Campaign",
"region": "West",
"status": "Active"
}
},
{
"id": "fc28d0cb-92a5-40fd-8a7c-84547d63953a",
"datastoreId": "39b88a97-8247-4c0d-ba1d-8ed78d1a6680",
"collectionId": "232e6d6c-46e9-49b6-a137-8933f0f05999",
"syncRequired": true,
"owner": "870010733",
"createdBy": "870010733",
"createdOn": "2026-06-23T20:58:35.097Z",
"updatedOn": "2026-06-23T21:03:40.861Z",
"updatedBy": "870010733",
"content": {
"campaignName": "Red Campaign",
"region": "West",
"status": "Inactive"
}
}
]{
"message": "Cannot find permission from source [USER:870010733] to target [MAGNUM_COLLECTION:a3f7d891-bc24-4e56-9a12-c7e3b0f845d2]. Permission Service reports that one or both does not exist",
"status": 404,
"statusReason": "Not Found",
"toe": "RG3808D5LS-DHKE4-TG5EB"
}Query Documents
Retrieve documents from a collection via MongoDB query (v2 endpoint).
AppDB supports the full range of MongoDB query predicates. The following operators are not supported:
$where— JavaScript expression evaluation is disabled server-side.$nearand$nearSphere— proximity searches require a geospatial index, which AppDB collections do not have.
All other operators in the official MongoDB query predicate documentation are supported, including comparison, logical, array, data type, bitwise, $expr, $jsonSchema, and $regex operators. The geospatial shape operators $geoWithin and $geoIntersects are also supported when your documents contain GeoJSON data.
Querying by date
AppDB has two categories of date fields that require different query approaches. Using the wrong approach for a field type fails silently — no error, just incorrect results.
System date fields (createdOn, updatedOn) are stored as BSON DateTime by AppDB. Query them using MongoDB Extended JSON v2 $date syntax:
{"createdOn": {"$gt": {"$date": "2026-01-01"}}}
Content date fields are stored as whatever JSON primitive you write. An ISO 8601 string like "2026-09-01T18:30:00Z" is stored as a BSON String. Two approaches work:
String comparison — ISO 8601 strings sort lexicographically in date order, so standard comparison operators work directly for both date-only (YYYY-MM-DD) and datetime (YYYY-MM-DDTHH:MM:SSZ) strings:
{"content.startDate": {"$gt": "2026-01-01"}}
$expr + $toDate — converts the string to a date at query time, enabling $date comparisons and handling mixed-precision strings correctly:
{
"$expr": {
"$gt": [
{"$toDate": "$content.startDate"},
{"$date": "2026-01-01"}
]
}
}
Mixing up these approaches produces wrong results without an error.
Using $date against a content string field always returns empty — BSON DateTime never matches BSON String. Using plain string comparison against a system field like createdOn also always returns empty — BSON String never compares against BSON DateTime regardless of the operator used.
To confirm the stored type of any field, use the $type operator. If {"someField": {"$type": "date"}} returns documents, use $date syntax. If {"someField": {"$type": "string"}} returns documents, use string comparison or $expr + $toDate.
Aggregation examples
The following examples use this sample movie collection:
[
{
"content": {
"title": "Inception", "genre": "sci-fi",
"year": 2010, "rating": 8.8,
"tags": ["mind-bending", "action"]
}
},
{
"content": {
"title": "Interstellar", "genre": "sci-fi",
"year": 2014, "rating": 8.6,
"tags": ["mind-bending", "emotional"]
}
},
{
"content": {
"title": "The Notebook", "genre": "romance",
"year": 2004, "rating": 7.9,
"tags": ["romantic", "drama"]
}
},
{
"content": {
"title": "Titanic", "genre": "romance",
"year": 1997, "rating": 7.8,
"tags": ["romantic", "drama", "action"]
}
},
{
"content": {
"title": "The Avengers", "genre": "action",
"year": 2012, "rating": 8.0,
"tags": ["action", "superhero"]
}
}
]
Average rating per genre for movies released since 2010
?groupby=content.genre&avg=content.rating avgRating&orderby=avgRating descending
Body:
{"content.year": {"$gte": 2010}}
Response:
[
{"_id": "sci-fi", "avgRating": 8.7},
{"_id": "action", "avgRating": 8.0}
]
Movie count per genre
?groupby=content.genre&count=count
Body: {}
[
{"_id": "sci-fi", "count": 2},
{"_id": "romance", "count": 2},
{"_id": "action", "count": 1}
]
Tag frequency across all movies
unwind produces one document per tag value before grouping, so a movie with ["action", "romantic"] counts once toward each group.
?unwind=content.tags&groupby=content.tags&count=count&orderby=count descending
Body: {}
[
{"_id": "action", "count": 3},
{"_id": "romantic", "count": 2},
{"_id": "drama", "count": 2},
{"_id": "mind-bending", "count": 2},
{"_id": "superhero", "count": 1},
{"_id": "emotional", "count": 1}
]
curl --request POST \
--url https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query \
--header 'Content-Type: application/json' \
--header 'X-DOMO-Developer-Token: <api-key>' \
--data '
{
"content.region": {
"$eq": "West"
}
}
'import requests
url = "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query"
payload = { "content.region": { "$eq": "West" } }
headers = {
"X-DOMO-Developer-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-DOMO-Developer-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({'content.region': {$eq: 'West'}})
};
fetch('https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'content.region' => [
'$eq' => 'West'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-DOMO-Developer-Token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query"
payload := strings.NewReader("{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-DOMO-Developer-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query")
.header("X-DOMO-Developer-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{instance}.domo.com/api/datastores/v2/collections/{collectionId}/documents/query")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-DOMO-Developer-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"content.region\": {\n \"$eq\": \"West\"\n }\n}"
response = http.request(request)
puts response.read_body[
{
"id": "a8428d64-a01d-49b2-9144-ddeec001acf8",
"datastoreId": "39b88a97-8247-4c0d-ba1d-8ed78d1a6680",
"collectionId": "232e6d6c-46e9-49b6-a137-8933f0f05999",
"syncRequired": true,
"owner": "870010733",
"createdBy": "870010733",
"createdOn": "2026-06-23T20:58:06.567Z",
"updatedOn": "2026-06-23T23:36:13.177Z",
"updatedBy": "870010733",
"content": {
"campaignName": "Q2 Campaign",
"region": "West",
"status": "Active"
}
},
{
"id": "fc28d0cb-92a5-40fd-8a7c-84547d63953a",
"datastoreId": "39b88a97-8247-4c0d-ba1d-8ed78d1a6680",
"collectionId": "232e6d6c-46e9-49b6-a137-8933f0f05999",
"syncRequired": true,
"owner": "870010733",
"createdBy": "870010733",
"createdOn": "2026-06-23T20:58:35.097Z",
"updatedOn": "2026-06-23T21:03:40.861Z",
"updatedBy": "870010733",
"content": {
"campaignName": "Red Campaign",
"region": "West",
"status": "Inactive"
}
}
]{
"message": "Cannot find permission from source [USER:870010733] to target [MAGNUM_COLLECTION:a3f7d891-bc24-4e56-9a12-c7e3b0f845d2]. Permission Service reports that one or both does not exist",
"status": 404,
"statusReason": "Not Found",
"toe": "RG3808D5LS-DHKE4-TG5EB"
}Authorizations
Domo Developer Token for authentication.
Path Parameters
The ID of the collection.
Query Parameters
Comma-separated list of properties to group by. Use dot notation for nested fields (e.g., content.campaignName). Top-level fields can be referenced directly.
Alias for a count aggregation.
Comma-separated list of properties with aliases to average (e.g., content.clicks myAlias). Use dot notation for nested fields.
Comma-separated list of properties with aliases to find the minimum. Use dot notation for nested fields.
Comma-separated list of properties with aliases to find the maximum. Use dot notation for nested fields.
Comma-separated list of properties with aliases to sum. Use dot notation for nested fields.
Comma-separated list of array properties to unwind (deconstructs an array field, producing one document per element). Use dot notation for nested fields. Must be combined with at least one of count, groupby, avg, min, max, or sum.
Field or alias to order by, followed by ascending or descending (e.g., totalClicks descending). Accepts either an aggregation alias or a field name using dot notation.
Maximum number of results to return. Default is 10,000.
Number of results to skip before returning. Default is 0.
Body
A MongoDB-style query object.
Response
OK
Unique identifier for the document.
ID of the datastore the document belongs to.
ID of the collection the document belongs to.
Whether the document is pending a sync to the underlying dataset.
User ID of the document owner. v2 endpoints return this as a string; v1 endpoints (List, Get, Query, Update) return it as a numeric integer. This differs from Collection and Datastore owner fields, which are always integers.
User ID of the user who created the document. v2 endpoints always return this field. v1 endpoints return it only from Create Document; all other v1 endpoints (List, Get, Query, Update) omit it.
ISO 8601 timestamp when the document was created.
ISO 8601 timestamp when the document was last updated.
User ID of the user who last updated the document. v2 endpoints return this as a string; v1 endpoints return it as a numeric integer.
Arbitrary JSON content of the document.

