Data Access

Sorting & Pagination

Sort and paginate results from your collections.

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' } }],
});

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' } }],
});
The -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' } },
  ],
});
Sort specifiers apply in order — the second field only breaks ties in the first.

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,
});

Return the second page (items 11-20):

const articles = await client.Articles.readMany({
  fields: ['id', 'title'],
  limit: 10,
  offset: 10,
});

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);
The SDK strips the { 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:

response.json
{
  "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.

Total counts are not computed for federated queries — for example, a filter that follows a relation into a different data source. The 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,
});
The SDK unwraps the { data } envelope by default. See Client Setup.
Offset-based pagination can skip or duplicate items if data changes between requests. Sort by a stable, unique field like id for consistent results.
Page-based and cursor-based pagination are not currently supported. These are planned for future versions. For now, all pagination is done with 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,
    },
  }],
});

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
Copyright © 2026