The API response envelope

{ data, message } / { data, meta } / { error } — and HTTP status codes.

6 mineasy

Every Grit API endpoint returns one of three shapes. Memorise these and you can read any response without looking up the schema.

Shape 1 — Single item

{
"data": { "id": "...", "email": "alex@example.com" },
"message": "User created successfully"
}

Used for GET /api/users/123, POST /api/users,PUT /api/users/123. message is human-readable; the UI shows it as a toast.

Shape 2 — Paginated list

{
"data": [ { "id": "..." }, { "id": "..." } ],
"meta": {
"total": 100,
"page": 1,
"page_size": 20,
"pages": 5
}
}

Used for GET /api/users and any list endpoint. meta drives pagination UI.

Shape 3 — Error

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email is required",
"details": {
"email": "This field is required"
}
}
}

Any 4xx or 5xx response. code is machine-readable (used for branching in the UI); message is human-readable; details is per-field for form validation errors.

HTTP status codes Grit uses

200 OK Successful read or update
201 Created Successful create
400 Bad Request Malformed JSON, missing required fields
401 Unauthorized No / invalid auth token
403 Forbidden Authenticated, but not allowed
404 Not Found Resource doesn't exist
422 Validation Form validation failure (details has per-field errors)
500 Server Error Something blew up server-side
Pro tip: 404 is also used for IDOR defence — Grit's authz.MustOwn returns 404 (not 403) when the authenticated user tries to access someone else's resource. That way the attacker can't distinguish "exists, you can't see it" from "doesn't exist".

Quick check

Your form submits 'name' but forgets 'email'. What status code + envelope do you expect?

Try it

With the API running, hit three endpoints from your browser or curl and paste the JSON in notes.md:

  1. GET /api/health — see Shape 1
  2. GET /api/users with a fresh JWT (admin) — see Shape 2 (paginated list)
  3. GET /api/users/nonexistent-id — see Shape 3 (404 error)

What's next

You know what success and failure look like. Next — how Grit handles errors internally: explicit on the Go side, error boundary + toast on the React side.

Spot a typo? Have an idea?

Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled — suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.

Suggest an improvement on GitHub