Filtering and sorting
Filter and sort Hoursmith API list endpoints with search, field filters, date and number ranges, and the sort parameter.
Core resource list endpoints support filtering and sorting through query parameters. Different filter dimensions combine with AND; repeated values within a documented exact/enum dimension combine with OR, with duplicates ignored and a maximum of 25 values. Payout endpoints have their own documented filter sets; consult each operation's reference.
Sorting
Use sort with a field name. Prefix with - for descending (Stripe-style):
GET /api/v1/invoices?sort=-issueDate
GET /api/v1/clients?sort=name- The default sort is
-createdAt(newest first). - Each resource allows a specific set of sort fields (e.g. invoices allow
number,status,issueDate,dueDate,total,amountPaid,createdAt, and more). idis always allowed as a tiebreaker. Nullable columns sort nulls last (descending) or first (ascending).
Search
Core collection search uses normalized, token-AND matching across documented text and safe related
fields (up to 200 characters). Terms of three or more characters include typo-tolerant candidates;
one/two-character input uses a primary-field prefix. Use sort=relevance with a non-empty search
for best-first results; ordinary sorts are still supported:
GET /api/v1/clients?search=globex
GET /api/v1/clients?search=globex&sort=relevanceField filters
Exact-match filters use the field name:
GET /api/v1/projects?clientId=...&status=ACTIVE
GET /api/v1/tasks?projectId=...&priority=HIGH
GET /api/v1/time-entries?userId=...&billable=true
GET /api/v1/invoices?status=PAID&status=SENTBooleans accept true/false, 1/0, or yes/no. Some resources also support relation
filters like clientName.
Use the exact enum spelling shown in the reference. Nullable relations use documented parameters
such as taskState=set|unset or invoiceState=set|unset, not invented empty IDs. Unknown enum
values, impossible calendar dates, and inverted ranges return validation errors.
Date ranges
Append From / To to a date column. Use YYYY-MM-DD (interpreted as UTC) or a full ISO
timestamp:
GET /api/v1/time-entries?entryDateFrom=2026-06-01&entryDateTo=2026-06-30
GET /api/v1/invoices?paidAtFrom=2026-01-01Time entries have two different date ranges — pick the right one. entryDate is the calendar day
the entry is filed under; startedAt is when the work actually began. Use startedAtFrom /
startedAtTo for questions like "what did I work on between 9am and noon?". Entries logged as a
plain duration have no start time, so they fall outside any startedAt range. startedAt is also a
sort field: ?sort=startedAt.
Number ranges
Append Min / Max to a numeric column:
GET /api/v1/time-entries?durationSecondsMin=3600
GET /api/v1/invoices?totalMax=1000Putting it together
GET /api/v1/time-entries?projectId=...&billable=true&entryDateFrom=2026-06-01&sort=-entryDate&limit=200Combine filters with pagination to export large datasets efficiently —
filter to exactly what you need, then page with limit=200.
The exact filterable and sortable fields for each resource are documented per endpoint in the API reference.