Sort and Paging
Sort
sort_token = [ sort_term , { "," , sort_term } ] ;
sort_term = [ "+" ] , attribute_name
| "-" , attribute_name ;
| Prefix | Direction |
|---|---|
+ | Ascending — the default |
- | Descending |
| none | Ascending |
Terms are comma-separated and applied in order, so the first term is the major sort:
GET /rest-1.v1/Data/Story?sel=Name,Estimate&sort=Estimate
GET /rest-1.v1/Data/Story?sort=-Estimate,+Name
The second sorts by Estimate descending, then by Name ascending within each Estimate.
Each term is a full attribute path, so you can sort by a value reached through a relation:
?sort=Scope.Name,-ChangeDate
+ and - mean something different in whereIn a filter expression
the same two characters are the unary existence operators: -Estimate there
means "has no estimate", not "descending". The characters are shared; the
meaning comes from which parameter they appear in.
A + in a URL query string is decoded as a space by many servers and clients.
Since ascending is the default, the safest habit is to omit + entirely and
write only the - prefixes you need. If you do send +, encode it as %2B.
Default Ordering
No ordering is guaranteed when sort is absent from a /Data request — do not
depend on the order of an unsorted list request.
There is one exception. On a history request with no sort, the server adds
an implicit ascending sort on Moment. Supplying your own sort replaces it
rather than adding to it, so a sorted history response is no longer
chronological.
Errors
A sort value that does not parse, or that names a non-existent attribute,
produces 400 Bad Request with the message Invalid SORT parameter.
sort is ignored without complaint on single-asset /Data/{Type}/{id} requests.
Note that deleted and needTotal are applied on those same URLs; see
which parameters apply to which request shape.
Paging
paging_token = page_size , [ "," , page_start ] ;
page_size = INT ;
page_start = INT ;
page=<size>,<start> — the first number is how many assets to return, the
second is how many to skip. This is the opposite of the (start, size)
ordering most pagination APIs use, and getting it backwards is silent: you get a
valid response containing the wrong window.
Note also that query.v1 uses a named mapping — page: { start: 0, size: 50 }
— so a query ported between the two surfaces cannot carry the ordering across.
start counts assets to skip, so it advances by size per page, not by one:
GET /rest-1.v1/Data/Story?sel=Name&page=5,0 # assets 1–5
GET /rest-1.v1/Data/Story?sel=Name&page=5,5 # assets 6–10
GET /rest-1.v1/Data/Story?sel=Name&page=5,10 # assets 11–15
start is optional; page=5 is page=5,0. Both values are plain non-negative
integers — no sign, no decimal point.
Because paging is applied after sorting, a stable sort is a prerequisite for
correct paging. Paging an unsorted /Data list can repeat or skip assets
between pages.
Reading the Response
A list response carries three attributes on its root element:
<Assets total="10" pageSize="5" pageStart="0">
| Attribute | Meaning |
|---|---|
total | How many assets satisfied the query in total, ignoring paging — omitted when the server did not compute it |
pageSize | The requested page size |
pageStart | The requested page start |
When page is omitted, pageSize comes back as 2147483647 — Int32.MaxValue
— meaning the response is unpaged. Treat that value as "no limit", not as a real
page size.
"No limit" means no limit. An unpaged list request attempts to return every
matching asset, so page is effectively mandatory on any query that could match
more than a handful. See Query size and performance.
total means "not computed", not "no results"total follows two rules:
- Unpaged responses always carry it, and it is always a real count — with
no
pagethe server counts what it returns. - Paged responses carry it only when the server was asked to compute it.
Otherwise the attribute is omitted entirely (XML and JSON alike; it is never
written as
-1ornullon this endpoint).
On a paged query, whether the count is computed is controlled by the
needTotal parameter, and its default
is per-instance: it comes from the ApiDefaultNeedTotal server setting. That
is the trap — a client that drives a pager off total can work correctly
against one Agility instance and break against another with no code change,
because the default flipped underneath it.
Always send needTotal=true explicitly when you need the count, and treat a
missing total as "unknown" rather than as zero. needTotal is applied on both
list and single-asset requests, unlike page and sort.
Errors
A page value that is not an integer produces 400 Bad Request with the
message Invalid PAGE parameter. Extra comma-separated values beyond the second
are ignored rather than rejected.
page is ignored without complaint on single-asset /Data/{Type}/{id}
requests, for the same reason sort is.
Putting It Together
GET /rest-1.v1/Data/Story
?sel=Name,Estimate,ToDo
&where=Estimate='5'
&sort=ToDo
&page=3,0
&find=Ticket
&findin=Name
The first 3 of the Story assets sorted by their To Do, with their Name, Estimate and To Do attributes, that have an Estimate of 5 and a Name containing the word Ticket.
Related Topics
- Attribute paths
- Filter expressions
- Grammar reference
- Query size and performance — why an unpaged request is a problem, and the request shape that avoids it
- Performance