Files
bible/rules/patterns/go-api/contract.md
Michael Chus d9204f2210 Rename kit/ to rules/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 16:57:06 +03:00

2.9 KiB

Contract: REST API Conventions (Go Web Applications)

URL Naming

  • Resources are plural nouns: /api/assets, /api/components, /api/pricelists.
  • Nested resources use parent path: /api/assets/:id/components.
  • Actions that are not CRUD use a verb suffix: /api/pricelists/:id/export-csv, /api/tasks/:id/cancel, /api/sync/push.
  • No verbs in resource paths: use /api/assets + DELETE, not /api/delete-asset.

HTTP Methods and Status Codes

Operation Method Success Notes
List GET 200
Get one GET 200 / 404
Create POST 201 Return created resource
Update PUT / PATCH 200 Return updated resource
Delete / Archive DELETE 200 or 204
Async action POST 202 Return {task_id}
Validation error POST/PUT 422 Return field errors
Server error any 500 Log full error server-side
Not found any 404
Unauthorized any 401
  • Never return 200 OK for validation errors — use 422 Unprocessable Entity.
  • Never return 200 OK with {"error": "..."} in the body — use the correct status code.

Error Response Format

All non-2xx responses return a consistent JSON body:

{
  "error": "human-readable message",
  "fields": {
    "serial_number": "Serial number is required",
    "price": "Must be greater than 0"
  }
}
  • error — always present, describes what went wrong.
  • fields — optional, present only for validation errors (422). Keys match form field names.
  • Never expose raw Go error strings, stack traces, or SQL errors to the client.

List Response Format

{
  "items": [...],
  "total_count": 342,
  "page": 2,
  "per_page": 50,
  "total_pages": 7
}
  • Always include pagination metadata even if the client did not request it.
  • items is always an array — never null, use [] for empty.

Request Conventions

  • Accept application/json for API endpoints.
  • HTML form submissions (htmx) use application/x-www-form-urlencoded or multipart/form-data.
  • File uploads use multipart/form-data.
  • Query parameters for filtering and pagination: ?page=1&per_page=50&search=abc&status=active.

Health and Utility Endpoints

Every application must expose:

GET /health       → 200 {"status": "ok"}
GET /api/db-status → 200 {"ok": true} or 500 {"ok": false, "error": "..."}
  • /health must respond even if DB is down (for load balancer probes).
  • /api/db-status checks the actual DB connection and returns its state.

Async Actions

For long-running operations return immediately with a task reference:

POST /api/pricelists/create → 202 {"task_id": "abc123"}
GET  /api/tasks/abc123      → 200 {"status": "running", "progress": 42, "message": "Processing..."}
GET  /api/tasks/abc123      → 200 {"status": "success", "result": {...}}

See go-background-tasks/contract.md for full task contract.