Skip to main content

Sort and Paging

Sort​

sort_token = [ sort_term , { "," , sort_term } ] ;
sort_term = [ "+" ] , attribute_name
| "-" , attribute_name ;
PrefixDirection
+Ascending — the default
-Descending
noneAscending

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
note
+ and - mean something different in where

In 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 ;
Size comes first

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">
AttributeMeaning
totalHow many assets satisfied the query in total, ignoring paging — omitted when the server did not compute it
pageSizeThe requested page size
pageStartThe 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.

danger
A missing 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 page the 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 -1 or null on 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.