Skip to main content

Pagination, Filtering & Sorting

Every list endpoint in the Oho REST API — /workers, /credentials, /applicants, /screening-packages, /fetch-requests, and the rest — shares the same query parameters for free-text search, paging, and ordering. The entity lists that carry a record-recency index (/workers, /credentials, /applicants, /exemptions) add an updatedAfter / updatedBefore window on top. Learn them once here and they behave the same wherever they appear.

Before you start

Read API Basics first — it covers base URLs, the Authorization header, the list response envelope, and soft deletes that this page builds on. The examples assume $OHO_BASE and $OHO_TOKEN are set.

The shared parameters

These apply to every list endpoint:

ParameterTypeDefaultPurpose
querystring*Free-text search across the entity's indexed fields.
pageinteger11-based page number to return.
pageSizeinteger25Results per page. Clamped to the range 1100.
sortstringOrder results as field:asc or field:desc.
includeDeletedbooleanfalseInclude soft-deleted records in the results.

Two more parameters — updatedAfter and updatedBefore — are available on the entity lists that index a last-modified time (/workers, /credentials, /applicants, /exemptions); see Filtering by update time below.

All of these are optional, and they compose: a single request can search, page, sort, and (where supported) filter by update window at the same time. Endpoints layer their own entity-specific filters on top — for example /credentials adds status and jurisdiction — but the parameters above behave identically across every list.

Searching with query

query runs a free-text search over the entity's indexed fields. Omit it (or pass the default *) to match everything:

curl -sS "$OHO_BASE/workers?query=jordan" \
-H "Authorization: Bearer $OHO_TOKEN"

To look a resource up by your own upstream identifier instead of searching, use the entity-specific exact-match filters (such as externalId) documented on each endpoint rather than query.

Paging through results

Results come back one page at a time. Use page to walk forward and pageSize to control how many rows each page holds:

curl -sS "$OHO_BASE/workers?page=2&pageSize=50" \
-H "Authorization: Bearer $OHO_TOKEN"

The meta block echoes the paging state and the total, so you can tell when you've reached the end:

{
"data": [{ "id": "wkr_V1StGXR8Z5jdHi6B", "type": "worker", "...": "..." }],
"meta": { "page": 2, "pageSize": 50, "total": 137, "requestId": "..." }
}

You've fetched the last page when page * pageSize >= total. With the values above, page 3 returns the final 37 records.

pageSize is clamped, not rejected

pageSize is clamped into the range 1100. Requesting pageSize=500 does not error — the server silently caps it at 100; values below 1 are raised to 1. Always read the pageSize returned in meta rather than assuming the value you sent was honored. To pull a large set, page through it instead of trying to raise the cap.

Sorting with sort

Pass a field name and a direction separated by a colon:

# Most recently updated workers first
curl -sS "$OHO_BASE/workers?sort=lastUpdated:desc" \
-H "Authorization: Bearer $OHO_TOKEN"

Direction is desc for descending; any other value — including an omitted or unrecognized direction — is treated as ascending, so sort=lastUpdated and sort=lastUpdated:asc are equivalent. The direction is not validated, so a typo silently sorts ascending rather than returning an error.

Which fields are sortable depends on the entity — lastUpdated (the record's last-modified time) is available on the lists that index it, and each endpoint documents the rest. Some endpoints (such as /compliance-checks) enforce an allow-list and reject an unknown field with 400; others pass the field through to the search layer. Check the per-endpoint API Reference for the sortable fields and the default ordering, which varies by entity (for example, workers default to display name ascending).

Filtering by update time

On /workers, /credentials, /applicants, and /exemptions, updatedAfter and updatedBefore bound results by each record's last-modified time (the indexed lastUpdated field). Each accepts either an ISO 8601 instant (2026-01-01T00:00:00Z) or a bare date (2026-01-01, interpreted as UTC midnight); an unparseable value returns 400. The boundaries are deliberately asymmetric:

  • updatedAfter is inclusive (>=) — a record updated exactly at the supplied instant is kept.
  • updatedBefore is exclusive (<) — a record updated exactly at the supplied instant is dropped.

This pairing makes it safe to page through changes in contiguous windows without seeing the same record twice at a boundary. Combine both to select a half-open [from, to) range:

# Credentials changed during June 2026
curl -sS "$OHO_BASE/credentials?updatedAfter=2026-06-01T00:00:00Z&updatedBefore=2026-07-01T00:00:00Z" \
-H "Authorization: Bearer $OHO_TOKEN"

A common sync pattern is to store the high-water mark from your last poll and pass it as updatedAfter on the next one, ordering by sort=lastUpdated:asc so you process changes oldest-first.

Including soft-deleted records

DELETE is a soft delete (see API Basics), and soft-deleted records are hidden from lists by default. Pass includeDeleted=true to bring them back — deleted rows carry deleted: true so you can tell them apart:

curl -sS "$OHO_BASE/credentials?includeDeleted=true" \
-H "Authorization: Bearer $OHO_TOKEN"

Putting it together

A single request can use every convention at once. The example below searches credentials, restricts to those changed since a given instant, sorts newest-first, and takes the first page of 50 — deleted records excluded:

curl -sS "$OHO_BASE/credentials?query=nurse&updatedAfter=2026-06-28T00:00:00Z&sort=lastUpdated:desc&page=1&pageSize=50" \
-H "Authorization: Bearer $OHO_TOKEN"

For the entity-specific filters that layer on top of these, see the per-endpoint API Reference.