PlutocracyMercury developer docs

Errors and status codes

The error envelope every route uses, what each status means on the storefront routes, and the zone answers that carry no body.

The error envelope

Every error, from every route, has the same JSON body:

{
  "code": 401,
  "error": "UNAUTHORIZED",
  "message": "Unauthorized",
  "method": "GET",
  "path": "/search/query/linen",
  "timestamp": "2026-11-09T01:02:03.456Z"
}

code repeats the HTTP status, error is its name (BAD_REQUEST, NOT_FOUND...), and message says what went wrong when the server knows. Anything unexpected is a 500 in the same envelope. Branch on the status code, not on message: messages are for people and can change.

Status codes on the storefront routes

StatusWhen
200Success. Also some deliberate empty answers, below.
201Success for a zone POST (the cart zone route).
400A bad request: a negative pageNumber, an empty collection handle, or a search term of the string undefined.
401No credential, or an unknown bypass token or origin. See authentication.
404An unknown collection (Collection not found), or a path that isn't a route. (An unknown product handle is a null in the products array, not a 404.)
406The search engine rejected the query, usually because of a malformed filter.
500A server fault. Retry once with backoff, then give up gracefully.

Successful responses with no body

A zone whose matching rule group shows nothing answers 2xx with an empty body instead of JSON, so read the text before parsing:

const res = await fetch(url);
if (!res.ok) {
  const error = await res.json().catch(() => null); // the envelope, when there is one
  throw new Error(`Mercury ${res.status}: ${error?.message ?? res.statusText}`);
}
const text = await res.text();
const data = text ? JSON.parse(text) : null;

Resilience

A failing Mercury call should never break a storefront page. Render the theme's own content (or nothing) when a collection, zone or search call fails, and set a timeout: the storefront routes normally answer well under a second.