Grofomo API
Browse the docs

Responses and errors

The response envelope, the error shape, and how to tell them apart.

Examples use a fictional festival, summer-fest. Sign in at events.grofomo.com and they switch to your own events.

Every endpoint — success or failure — returns the same envelope.

Success

{
  "apiVersion": 1,
  "data": { }
}

Failure

{
  "apiVersion": 1,
  "error": {
    "code": "not_found",
    "message": "Event not found"
  }
}

code is a stable, machine-readable string — branch on it. message is written for a developer reading a log, and its wording may change; never parse it.

Handling both

Because the shape is uniform, one helper covers the whole API:

async function grofomo(path) {
  const res = await fetch(`https://api.grofomo.com${path}`, {
    headers: { 'X-Grofomo-Key': process.env.GROFOMO_SECRET_KEY },
  });

  const body = await res.json();
  if (!res.ok) {
    throw new Error(`${body.error.code}: ${body.error.message}`);
  }
  return body.data;
}

Read the body once. res.json() consumes the stream, so calling it in both branches throws on the second call.

Status codes

StatusCodeWhat it means
200Fine.
400bad_requestThe request body or a parameter did not validate.
400turnstile_failedThe bot-check token was missing or invalid.
401unauthorizedNo key, or a key that is invalid, revoked, or out of scope.
403origin_not_allowedThe browser's domain is not on the organiser's allowlist.
404not_foundNo such event on this surface. Check ?surface=web.
429Rate limited. Honour Retry-After.
500fetch_failedOur fault. Safe to retry.

Retry 429 and 5xx. Never retry 401, 403 or 404 — they mean something is configured wrong, and a retry loop just turns one problem into a traffic problem.

Versioning

apiVersion is 1 and will stay 1 while changes are additive. New fields can appear at any time, so ignore fields you do not recognise rather than validating strictly against a fixed shape.

A breaking change would arrive as a new version, announced in the changelog before it lands.