Sorting & Pagination
Sort by a Single Field
Use the sort parameter to order results. Sort specifiers are objects with a field name key and a direction value of asc or desc.
Return articles sorted by newest first:
const articles = await client.Articles.readMany({
fields: ['id', 'title', 'created_at'],
sort: [{ created_at: { direction: 'desc' } }],
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title,created_at&sort[0][created_at][direction]=desc" \
-H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
'https://example.monospace.io/api/blog/items/articles?fields=id,title,created_at&sort[0][created_at][direction]=desc',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
Sort alphabetically by title (ascending is the default when direction is omitted):
const articles = await client.Articles.readMany({
fields: ['id', 'title'],
sort: [{ title: { direction: 'asc' } }],
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title&sort[0][title][direction]=asc" \
-H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch(
'https://example.monospace.io/api/blog/items/articles?fields=id,title&sort[0][title][direction]=asc',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
-field prefix syntax for descending sort (e.g., sort=-created_at) is not supported and will be rejected by the engine. Use the object syntax sort[0][field][direction]=desc instead.Sort by Multiple Fields
Pass multiple sort specifiers to break ties. The second field only applies when values in the first field are equal.
Sort articles by status ascending, then by creation date descending within each status:
const articles = await client.Articles.readMany({
fields: ['id', 'title', 'status', 'created_at'],
sort: [
{ status: { direction: 'asc' } },
{ created_at: { direction: 'desc' } },
],
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title,status,created_at&sort[0][status][direction]=asc&sort[1][created_at][direction]=desc" \
-H "Authorization: Bearer YOUR_API_KEY"
const params = new URLSearchParams();
params.set('fields', 'id,title,status,created_at');
params.set('sort[0][status][direction]', 'asc');
params.set('sort[1][created_at][direction]', 'desc');
const response = await fetch(
`https://example.monospace.io/api/blog/items/articles?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
Paginate with Limit and Offset
Use limit to control how many items are returned and offset to skip items. The default limit is 100, configurable via MONOSPACE_QUERY_LIMIT_DEFAULT. The maximum allowed limit is set by MONOSPACE_QUERY_LIMIT_MAX. Set limit=0 or limit=-1 to request unlimited results (subject to the configured maximum).
Return the first 10 articles:
const articles = await client.Articles.readMany({
fields: ['id', 'title'],
limit: 10,
offset: 0,
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title&limit=10&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
const params = new URLSearchParams({
fields: 'id,title',
limit: '10',
offset: '0',
});
const response = await fetch(
`https://example.monospace.io/api/blog/items/articles?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
Return the second page (items 11-20):
const articles = await client.Articles.readMany({
fields: ['id', 'title'],
limit: 10,
offset: 10,
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title&limit=10&offset=10" \
-H "Authorization: Bearer YOUR_API_KEY"
const params = new URLSearchParams({
fields: 'id,title',
limit: '10',
offset: '10',
});
const response = await fetch(
`https://example.monospace.io/api/blog/items/articles?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
Get the Total Count
Add meta=totalCount to a list request to count every item matching the query. The count respects filters and permissions but ignores limit and offset — it answers "how many in total", not "how many on this page".
Return one page of published articles plus the total number of published articles:
const { data, meta } = await client.Articles.readMany(
{
fields: ['id', 'title'],
filter: { status: { _eq: 'published' } },
limit: 2,
meta: { totalCount: true },
},
{ unwrapEnvelope: false },
);
console.log(meta.totalCount);
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title&filter[status][_eq]=published&limit=2&meta=totalCount" \
-H "Authorization: Bearer YOUR_API_KEY"
const params = new URLSearchParams({
fields: 'id,title',
'filter[status][_eq]': 'published',
limit: '2',
meta: 'totalCount',
});
const response = await fetch(
`https://example.monospace.io/api/blog/items/articles?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data, meta } = await response.json();
console.log(meta.totalCount);
{ data } envelope by default, discarding meta with it — pass { unwrapEnvelope: false } as the second argument to keep both. With meta: { totalCount: true } in the arguments, the result is typed as { data, meta: { totalCount: number } }.The response carries the count in a meta object next to data:
{
"data": [
{ "id": 1, "title": "Getting Started with Monospace" },
{ "id": 2, "title": "Data Modeling Best Practices" }
],
"meta": {
"totalCount": 42
}
}
meta[totalCount]=true and meta[]=totalCount are equivalent spellings. Requesting any other meta field is a validation error. Without meta, the response contains no meta object.
meta=totalCount request is silently ignored and the response contains no meta object, so don't assume it is always present.Implement Page-Based Navigation
Calculate the offset from a page number using offset = (page - 1) * pageSize. There is no page query parameter — pagination is strictly limit/offset-based. Derive the page count from the total count: Math.ceil(totalCount / pageSize).
Fetch page 3 with 25 items per page:
const page = 3;
const pageSize = 25;
const offset = (page - 1) * pageSize;
const articles = await client.Articles.readMany({
fields: ['id', 'title', 'status'],
limit: pageSize,
offset,
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title,status&limit=25&offset=50" \
-H "Authorization: Bearer YOUR_API_KEY"
const page = 3;
const pageSize = 25;
const offset = (page - 1) * pageSize;
const params = new URLSearchParams({
fields: 'id,title,status',
limit: String(pageSize),
offset: String(offset),
});
const response = await fetch(
`https://example.monospace.io/api/blog/items/articles?${params}`,
{
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
},
);
const { data } = await response.json();
{ data } envelope by default. See Client Setup.id for consistent results.limit and offset.Sort and Paginate Within Nested Relations
Apply sorting and pagination to related collections using expanded field selection. In REST, use deep with underscore-prefixed keys. In the SDK, use sort, limit, and offset inside the expanded relation object.
Return each article with its 5 most recent comments:
const articles = await client.Articles.readMany({
fields: ['id', 'title', {
comments: {
fields: ['id', 'body', 'created_at'],
sort: [{ created_at: { direction: 'desc' } }],
limit: 5,
},
}],
});
curl -g "https://example.monospace.io/api/blog/items/articles?fields=id,title,comments.id,comments.body,comments.created_at&deep[comments][_sort][0][created_at][direction]=desc&deep[comments][_limit]=5" \
-H "Authorization: Bearer YOUR_API_KEY"
const url = new URL('https://example.monospace.io/api/blog/items/articles');
url.searchParams.set('fields', 'id,title,comments.id,comments.body,comments.created_at');
url.searchParams.set('deep[comments][_sort][0][created_at][direction]', 'desc');
url.searchParams.set('deep[comments][_limit]', '5');
const response = await fetch(url, {
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
});
const { data } = await response.json();
For more on selecting nested fields and the expanded field selection syntax, see Field Selection.
See Also
- Reading Data — fetch items, field selection, and sorting
- Filtering — narrow results with filter operators
- Field Selection — wildcards, nested fields, and expanded relation syntax