Skip to content
Coritan Docs

Pagination and filtering

How list endpoints page their results with limit and offset or with page numbers, and how to read the total.

View as Markdown

List endpoints answer one page of results at a time. Each list takes one of four sets of paging parameters, and many take filters as well. The API reference gives the parameters of every route. This page lists the conventions, the page sizes of the main lists, and how to read a total.

Parameters First page Next page Used by
limit and offset offset=0 Add limit to offset. GET /services/ and GET /payments/disputes in the Client API, and most lists in the Organization API, the Commerce API and the Store API
page and limit page=1 Add 1 to page. Invoices, transactions, a service's events and support conversations in the Client API
page and per_page page=1 Add 1 to page. DNS zones and records, proxy routes, SSL certificates and products in the Client API, and services in the customer portal
before_id and limit Leave out before_id. Send the last answer's next_before_id as before_id. Events, promotions, gift cards and fulfilment provider logs in the Commerce API

page starts at 1, and page n skips the first (n - 1) × limit results (or (n - 1) × per_page). A page past the last one answers an empty list.

Lists come newest first unless the tables below say otherwise. Invoices, transactions, customers and Commerce orders break a tie on the ID, so while nothing changes, every row appears on exactly one page. On a list sorted newest first, a row added while you page pushes the others down by one, and the next page then starts with the last row of the page before. Skip IDs you already hold.

Leave out limit or per_page to get the default. On most lists, a value above the largest size, or below 1, answers 422, and the entry in detail names the parameter and the largest size:

JSON
{
  "detail": [
    {
      "type": "less_than_equal",
      "loc": ["query", "limit"],
      "msg": "Input should be less than or equal to 200",
      "input": "500",
      "ctx": {"le": 200}
    }
  ]
}
List Route Paging Default Largest
Services GET /services/ limit, offset 100 500
A service's events GET /services/{service_ref}/events page, limit 50 200
Invoices GET /billing/invoices page, limit 50 200
Transactions GET /billing/transactions page, limit 50 200
Disputes GET /payments/disputes limit, offset 50 100
DNS zones, in order of domain GET /dns/zones page, per_page 25 100
A zone's records, in order of name, then type GET /dns/zones/{zone_id}/records page, per_page 100 1,000
Proxy routes GET /proxy/routes page, per_page 50 200
SSL certificates GET /ssl/certificates page, per_page 25 100
Products, in the order the catalogue shows them GET /products/ page, per_page 100 200
Support conversations, latest activity first GET /chat/conversations page, limit 20 100
Messages in a conversation, oldest first GET /chat/conversations/{conversation_id}/messages before_id, after_id, limit 50 100

GET /billing/crypto/deposits takes limit alone (50 by default, at most 200) and answers the newest deposits, with no way to ask for older ones.

Organization API and customer portal

Section titled Organization API and customer portal
List Route Paging Default Largest
Customers GET /orgs/{org_slug}/customers limit, offset 50 200
Invoices GET /orgs/{org_slug}/invoices limit, offset 50 500, cut down
Audit log GET /orgs/{org_slug}/audit-log limit, offset 50 200
A customer's services GET /orgs/{org_slug}/portal/services page, per_page 50 200
A customer's invoices GET /orgs/{org_slug}/portal/invoices limit, offset 50 500, cut down
A customer's transactions GET /orgs/{org_slug}/portal/transactions limit, offset 50 500, cut down

Where the table says cut down, a larger limit does not fail: the list answers 500 results instead.

List Route Paging Default Largest
Orders GET /orgs/{org_slug}/commerce/orders limit, offset 50 200
Products, most recently changed first GET /orgs/{org_slug}/commerce/products limit, offset 50 200
Events GET /orgs/{org_slug}/commerce/events before_id, limit 50 200
Promotions GET /orgs/{org_slug}/commerce/promotions before_id, limit 50 200
Gift cards GET /orgs/{org_slug}/commerce/gift-cards before_id, limit 50 200
Store products GET /orgs/{org_slug}/store/products limit, offset 20 100
Store collections, in the store's order GET /orgs/{org_slug}/store/collections limit, offset 50 100

Store products come newest first by default. order changes that: -created_at, created_at, -title or title.

Most lists answer a bare JSON array with no total. Those below say how many results match.

Lists How to get the total Answer
Invoices and transactions in the Client API Add with_total=true. {"items": [...], "total": 12, "page": 1, "limit": 50, "counts": {...}}
Customers and invoices in the Organization API, and invoices and transactions in the customer portal Add with_total=true. {"items": [...], "total": 12, "limit": 50, "offset": 0, "counts": {...}}
Proxy routes Always there. {"routes": [...], "total": 12, "page": 1, "per_page": 50}
SSL certificates Always there. {"certificates": [...], "total": 12}
Lists in the Commerce API and the Store API that take offset Always there. The results under a name such as orders, with count, limit and offset

total and count are the number of results the filters match, across every page. counts gives the number for each status or type as if no status or type filter were set, with all for the whole list. Invoices add open, which is unpaid and overdue together, and Client API transactions add credit, which is credit added and credit used together. Organization invoices also carry outstanding: what the open invoices owe, for each currency.

A filter narrows the list before it is cut into pages, so total and every page reflect it. A filter the route does not know is ignored.

Filter Lists What it matches
status Services One status: pending, provisioning, active, suspended, pending_termination, terminated or failed.
resource_type Services vps (or cloud_compute), container, ip (or floating_ip), mail or smtp_relay. Another word answers 422 with "error": "invalid_resource_type" and the accepted words in allowed.
tag Services Services with that tag.
status_filter Invoices open, draft, unpaid, paid, cancelled, refunded or overdue.
type_filter Transactions payment, refund, credit, credit_add or credit_deduct. In the customer portal: payment, refund, chargeback, credit_add or credit_deduct.
record_type and name A zone's records One record type, in any case, and one exact record name.
status, priority and q Support conversations status takes open, awaiting_customer, awaiting_agent, in_progress, on_hold or closed, and open matches every conversation that is not closed. priority takes low, medium, high or critical. q searches the subject and the latest message, and # followed by a number finds that conversation.
q Organization customers, portal invoices and Commerce orders Search text: a customer's email, name, handle, company or number; an invoice number; or an order number such as #1001, an order ID or part of an email.
placed_from and placed_to Commerce orders A date and time range. placed_to itself is left out.

resource_type, type_filter, priority and the Client API's status_filter answer 422 for a word they do not list. The other filters match nothing when no result has the value you send. The reference for each route lists the rest of its filters.

Ask for pages until one holds fewer results than you asked for, or until you have total results. This reads every service, 100 at a time:

Shell
offset=0
while :; do
  page=$(curl -s "https://api.coritan.com/api/v1/services/?limit=100&offset=$offset" \
    -H "Authorization: Bearer $CORITAN_TOKEN")
  echo "$page" | jq -c '.[]'
  [ "$(echo "$page" | jq length)" -lt 100 ] && break
  offset=$((offset + 100))
done

On a list that uses before_id, stop when next_before_id is null.

Messages in a support conversation page by ID rather than by position:

No parameters
The latest limit messages, oldest first.
before_id
The latest limit messages older than that message ID, oldest first. Send the ID of the first message you hold to read further back.
after_id
Up to limit messages newer than that message ID, oldest first. Send the ID of the last message you hold to fetch only what is new.

Internal notes from Coritan's team never appear in the list. Poll no more often than you need to: Rate limits applies to every request.

When you poll GET /orgs/{org_slug}/portal/services for changes, add consistency=eventual. The answer may miss a change made a moment ago, so leave it out on the first read after a change of your own.