Listing, Sorting and Fields
The *_list tools use the same pagination as the REST API: by page number.
| Argument | Default | Max |
|---|---|---|
page | 1 | — |
per_page | 20 | 100 |
{ "name": "dashboards_portal_users_list", "arguments": { "status": "active", "page": 2, "per_page": 50 } }
The result carries the usual envelope:
{
"data": [ /* ... */ ],
"meta": { "total": 142, "page": 2, "per_page": 50, "total_pages": 3 }
}
When page > total_pages, data comes back empty — that is not an error.
:::note Collections that do not paginate
Some collections are small configuration lists. Those answer with the whole set and do not accept page — and the matching tool does not offer the argument either. That is intentional: a tool advertising page on a route that ignores it would make the model page forever through a list that never moves.
:::
Sorting
| Argument | Values | Default |
|---|---|---|
sort_by | A column name in snake_case (created_at, name) | varies per resource |
sort_order | asc or desc, in any case | varies per resource |
{ "name": "dashboards_portal_users_list", "arguments": { "sort_by": "created_at", "sort_order": "asc" } }
Two rules worth knowing, different from each other on purpose:
- A column the resource does not sort by falls back to the default. Sorting by a field that does not exist is a request the server cannot honour, but it is not a reason to fail the whole call;
dashboards_schemas_getlists the accepted ones undersortable_fields. - A direction that is not a direction is a
400.sort_order: "descending"is an error, not a silentdesc— returning the right order by accident would hide the bug until the day the accident landed the other way.
Fields (fields)
Every read tool accepts fields, an array of column names. Omitted, the whole resource comes back; given, only that:
{ "name": "dashboards_portal_users_list",
"arguments": { "status": "active", "fields": ["email", "status", "created_at"] } }
| Rule | Why |
|---|---|
id always comes back | A projection you cannot follow is useless, and dropping id silently would break the next call, not this one. |
| Top level only | fields: ["person"] returns the whole nested object; there is no person.name syntax. |
| Reads only | A create answers with an envelope the caller did not choose; projecting it would hide half the receipt for an operation that already happened. |
An unknown name is a 400 | With the list of what exists. Ignoring it would return fewer fields than asked for and look like the resource does not have them — a wrong answer wearing a right one's face. |
fields is the cheapest way to cut the context an agent spends: a list of 300 portal users with three columns fits where the same list in full would not.
dashboards_schemas_get — the field catalogue
fields only helps if you know what to ask for, and a model left guessing will try portal_user.mail_address when the contract says email. dashboards_schemas_get answers that directly:
{ "name": "dashboards_schemas_get", "arguments": {} }
{ "name": "dashboards_schemas_get", "arguments": { "resource": "portal_user" } }
With no argument it returns the resource catalogue. With resource, it returns every field of that resource — name, type, enum, nullability, description — and, separately, its sortable_fields.
It comes from the same schemas that generate the published OpenAPI, so the list the tool reports and the one this documentation publishes cannot diverge.
Data contract
What holds for the v1 API holds here, because it is the same code:
- snake_case everywhere, arguments and responses.
- Dates in ISO 8601, processed in UTC.
- Writes accept
idempotency_key— see Idempotency.