Querying
The API supports pagination, filters, and sorting.
Pagination
page(default1)limit(default50, max200)
When records share the selected sort value, list queries use the record ID as a tie-breaker. Keep filters and sorting unchanged while paging. Concurrent changes to records can still affect page boundaries.
Common Filters
company: a 24-character hexadecimal MongoDB ID or a 10-character internal nanoid (letters, numbers,_or-). Comma-separated and repeated company filters are supported. Malformed identifiers return400 BAD_REQUEST; valid identifiers that do not exist or are outside the key’s company access return404 NOT_FOUND. This applies to company and agency keys on endpoints available to them.activefromandtomust be real calendar dates inYYYY-MM-DDformat. Impossible dates such as2026-02-30return400 BAD_REQUESTinstead of rolling into the next month. Leap days are accepted only in leap years. This validation applies to both company and agency keys on endpoints available to them, and to workerexpiringAfter/expiringBeforedate filters.- Valid broad date ranges retain their meaning even when creation-date filtering uses ObjectId timestamps: a lower bound before 1970 or an upper bound after the timestamp range does not exclude otherwise matching records. Ranges entirely outside the representable creation dates return no records.
query
Multi-value ID filters also accept a mix of repeated parameters and comma-separated values, such as project=id1,id2&project=id3, where the endpoint supports multiple IDs. Duplicate IDs are ignored. Structured values such as project[id]=id1 return 400 BAD_REQUEST; malformed company values are rejected before resolving access scope.
On the rates list, region, sector and agency accept a single ID each. Repeated parameters or structured values return 400 BAD_REQUEST; they are not treated as an omitted filter. This does not change the supported multi-value company filter.
The requisitions list accepts a single status. Repeated parameters, including duplicate valid statuses, or structured status values return 400 BAD_REQUEST. Existing status aliases and agency-key restrictions still apply.
Timesheet list date ranges intersect the list's existing current-week cutoff. Filtering by dateField=end does not include future timesheets beyond that cutoff, even with a later to date. Future timesheets remain accessible through permitted detail requests.
Timesheet summaries support createdAt, updatedAt, start, end, approvedDate and weekEnding as date fields. Compatibility aliases startDate, endDate and we are also accepted. The same selected date is used for month/week grouping and range filtering, and the current-week cutoff remains in force. Other date fields return 400 BAD_REQUEST.
For requisition summaries grouped by agency, assignedQuantity counts that agency's non-cancelled assignments. openQuantity is the requisition demand minus that agency's assigned count, floored at zero. Shared requisition demand may appear in multiple agency groups. Explicit agency filters and agency-key scope also restrict the returned agency groups; summaries without agency grouping retain requisition-level totals.
Assignment summary averageWorkerDistance excludes unknown distances. It is null when a group has no numeric distance observations; an actual zero-distance average remains 0.
Sorting
sortBysortOrder(ascordesc)
Field Selection
List endpoints accept fields as a comma-separated list of top-level response fields. Use it to reduce payload size when you only need a small set of columns.
For assignments, fields=id,values retains the same pay and charge totals as the full response. You can also request values.pay or values.charge individually. Field selection does not recalculate these totals.
Nested selections preserve array structure and element order. For example, fields=id,pieceRates.code,pieceRates.values.cis.pay returns a pieceRates array with the requested fields inside each piece-rate object; each pay value remains a number. Empty arrays and null values retain their types. Selecting an entire field includes it in full, even when a nested field is also requested.
For example, fields=id,status,value returns only those fields when they are present on each row.
Example
GET /api/open/v1/projects?from=2026-01-01&to=2026-01-31&active=true&page=1&limit=50&fields=id,name,active