Filtering
Collection endpoints support Ransack filters passed as flat parameters — append a predicate suffix to any filterable attribute. The SDK wraps filter keys inq[…] automatically:
_eq, _not_eq, _cont (contains), _start, _end, _gteq / _lteq, _gt / _lt, _in (array), _null. The filterable attributes per resource are listed in the Admin API reference; each model declares an explicit allowlist, so unknown filter keys are ignored rather than executed.
Foreign-key predicates accept prefixed IDs (
user_id_eq: 'cus_xxx', variant_id_in: ['variant_a', 'variant_b']) — the API translates them; you never handle raw database IDs.Sorting
Passsort with an attribute name; prefix with - for descending. Comma-separate multiple fields:
Pagination
List responses return{ data, meta }. Drive pagination with page and limit:
Expanding associations
Passexpand to embed related records in the response, instead of making follow-up requests. Dot notation reaches nested associations (up to 4 levels):
fields does the opposite — trims the response to just the attributes you name (id is always included):
Error handling
Every non-2xx response throws aSpreeError with a stable machine-readable code, the HTTP status, and optional structured details:
Validation errors
On422 responses, details maps attribute names to arrays of messages — ready to project onto form fields:
Scope errors
When a request fails because the secret API key lacks the required scope, the error hascode: 'access_denied' and details.required_scope names the missing scope:
Expired JWT sessions
For cookie-authenticated apps, register anonUnauthorized handler to transparently refresh and retry on 401 — see Authentication.

