Lists and filters
Every collection answers the same grammar.
GET /gigs?limit=50&offset=0&sort=-gig_date,label&fields=id,label,gig_date&filter[gig_status_id]=<status id>&filter[gig_date][on_or_after]=2026-10-01
| Parameter | Meaning |
|---|---|
limit |
Page size. Default 50, maximum 200. |
offset |
Records to skip. meta.total is the full count, so offset + limit < total means there is more. |
sort |
Comma-separated fields. Prefix with - for descending. Each resource lists its sortable fields in the reference. |
fields |
Comma-separated subset to return. id is always included. |
filter[field]=value |
Shorthand for equals. |
filter[field][operator]=value |
Any operator the field's type supports. Several fields are ANDed. |
Operators by field type
| Field type | Operators |
|---|---|
| text (labels, notes, names, emails, phones, urls) | equals, does_not_equal, contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty |
| number, currency | equals, does_not_equal, greater_than, less_than, greater_than_or_equal_to, less_than_or_equal_to, is_empty, is_not_empty |
| date, time, timestamps | equals, before, after, on_or_before, on_or_after, is_empty, is_not_empty |
| select, status, relation (ids) | equals, does_not_equal, is_empty, is_not_empty |
| multi-select | contains, does_not_contain, is_empty, is_not_empty |
| checkbox | equals, does_not_equal |
Text matching is case-insensitive. is_empty and is_not_empty take true. The reference documents the exact operators of every field, and an unsupported operator answers 400 with the list of supported ones.
Examples
Band leader slots nobody has filled yet:
GET /gig-roles?filter[role_id]=<band leader role id>&filter[staff_member_id][is_empty]=true
Staff who can play a role, in call order:
GET /staff-member-roles?filter[role_id]=<role id>&filter[status]=active&sort=call_order
Everyone blocked out over a weekend:
GET /staff-member-blockouts?filter[start_date][on_or_before]=2026-12-13&filter[end_date][on_or_after]=2026-12-12
Nested collections
GET /gigs/{id}/products is the same query as GET /gig-products?filter[gig_id]=…, with a 404 if the gig does not exist. Every nested route accepts the full grammar on top of the pinned parent, and POST to it creates a child with the parent's id already filled in.