Skip to content

Listing & pagination

Every list endpoint in the Pagr API — templates, template versions, and documents — shares one contract: the same query parameters in, the same envelope out. Learn it once and it applies everywhere.

Parameter Type Default Description
skip integer 0 Records to skip. Offset-based, not cursor-based.
take integer 25 Page size. Clamped server-side to 1–200.
sortBy string (per-endpoint default) Field to sort on, using the wire’s camelCase name. An unrecognised value silently falls back to the endpoint’s default sort.
sortDirection asc | desc asc Sort direction.
search string Free-text; contains-matches across the endpoint’s text fields.
filters[i].field string Field to filter on.
filters[i].op string eq Comparison operator. Supported operators vary by field — see Filterable fields.
filters[i].value string Value to compare against.

Filters use an indexed query form and combine with AND:

?filters[0].field=environment&filters[0].op=eq&filters[0].value=production
&filters[1].field=renderedAt&filters[1].op=gte&filters[1].value=2026-01-01T00:00:00Z

Every list response is wrapped the same way:

{
"items": [ /* … */ ],
"total": 42, // full count matching your filters, independent of skip/take
"skip": 0, // the paging the server actually applied
"take": 25
}

total is the count across all pages, so use it to know when to stop paging. skip and take echo what the server applied after clamping — if you asked for take=5000 you’ll get take=200 back.

Operator sets used below:

Set Operators
Id eq
Text eq, contains
Ordered (numbers, dates) eq, gt, gte, lt, lte
Enum eq, neq

GET /v1/templates and GET /v1/projects/{projectId}/templates.

Field Type Operators
name string Text
project.guid UUID Id
createdAt ISO 8601 datetime Ordered
updatedAt ISO 8601 datetime Ordered

Sortable: name, createdAt, updatedAt (default). search matches name.

GET /v1/templates/{templateId}/versions.

Field Type Operators
versionNumber number Ordered
publishedAt ISO 8601 datetime Ordered
createdAt ISO 8601 datetime Ordered
updatedAt ISO 8601 datetime Ordered

Sortable: versionNumber (default), publishedAt, createdAt, updatedAt.

GET /v1/documents.

Field Type Operators
documentName string Text
template.guid UUID Id
versionNumber number Ordered
fileSizeBytes number Ordered
pageCount number Ordered
renderedAt ISO 8601 datetime Ordered
createdAt ISO 8601 datetime Ordered
updatedAt ISO 8601 datetime Ordered
environment test | production Enum
language string Enum

Sortable: documentName, versionNumber, fileSizeBytes, pageCount, renderedAt (default), renderDuration, environment, createdAt, updatedAt. search matches documentName.

Page through every production document rendered this year, newest first.

Terminal window
curl -G "https://pagr-prd-api-public.azurewebsites.net/v1/documents" \
-H "Authorization: Bearer pagr_prod_xxxxxxxx" \
--data-urlencode "skip=0" \
--data-urlencode "take=100" \
--data-urlencode "sortBy=renderedAt" \
--data-urlencode "sortDirection=desc" \
--data-urlencode "filters[0].field=environment" \
--data-urlencode "filters[0].op=eq" \
--data-urlencode "filters[0].value=production" \
--data-urlencode "filters[1].field=renderedAt" \
--data-urlencode "filters[1].op=gte" \
--data-urlencode "filters[1].value=2026-01-01T00:00:00Z"

Increment skip by take until skip + items.length >= total.

Every SDK’s paged result exposes the same three things, so the loop above looks the same in each language:

SDK Items Total More pages?
Python .items (also iterable / indexable) .total .has_more
TypeScript .items (also iterable) .total .hasMore
Java .getItems() (also Iterable) .getTotal() .hasMore()
C# .Items (also IReadOnlyList<T>) .Total .HasMore
Ruby .items (also Enumerable) .total .more?
C++ .items .total .has_more()

The “more pages?” flag is computed client-side as skip + items.length < total — no extra request needed. Note Ruby names it more? rather than has_more?, following Ruby’s predicate convention.

  • Offset paging drifts. New renders arrive while you page. If exactness matters, filter on a fixed upper bound (renderedAt lte a timestamp you captured before starting) so the result set can’t grow underneath you.
  • take is clamped, not rejected. Asking for 5000 gives you 200 and no warning. Read take off the response if you depend on the page size.
  • Datetime values are ISO 8601 strings on the wire. The Python SDK accepts a datetime and the C# SDK has Filter.Gte(field, DateTimeOffset) helpers that format for you; elsewhere, format to ISO 8601 yourself.
  • UUID filter fields are the nested wire namesproject.guid and template.guid, not projectId / templateId. The names differ from the fields in the response body on purpose; use the table above.
  • List endpoints are reads, so the SDKs retry them on transient server failures. Paging loops are safe to leave running. See Handle errors and retries.