Response envelope
Successful responses wrap the payload indata:
meta.timestamp is always present. meta.requestId appears when the request carried an id, and
correlates the response with our server logs — quote it when reporting a problem.
Errors
Every4xx and 5xx uses the error envelope:
error.code, not error.message — code is the stable field. details is populated for
validation failures and null otherwise; entries for enum fields also carry allowedValues.
A malformed identifier returns 422, not 400. Anything that is not a 24-character hexadecimal
id is rejected before it reaches the database, with
error.details[0].field naming the offending
parameter.Pagination
List endpoints acceptpage and limit and return:
limitdefaults to 20 and is capped at 100. Above the cap is a422, not a silent clamp.pageorlimitof0, a negative number, or a non-numeric string is a422. These were previously ignored and replaced with defaults.- Page through with
hasNextPageandnextPagerather than requesting an oversized page.
Sorting
sort takes field names separated by commas or spaces, each optionally prefixed with - for
descending. Both ?sort=name,-createdAt and ?sort=name -createdAt are accepted and mean the same
thing. The default is -createdAt.
A malformed value such as ?sort=- is a 422 naming sort.
Unknown parameters
Query keys an endpoint does not declare are stripped before the handler runs, not rejected. A request carrying one still returns200; the parameter simply has no effect.

