# API conventions (read before writing or consuming any contract) These hold for **every** Balinyaar endpoint. Per-domain contract docs assume them and don't restate them. ## Base & versioning - Base URL from `NEXT_PUBLIC_API_URL` (client) / `https://localhost:5002` (server default). - Versioned routes: `api/v{version}/...` (Asp.Versioning). Default `v1`. - **All URL segments are `snake_case`** (server `SnakeCaseParameterTransformer`). Controllers use `[controller]`/`[action]` tokens, so `GetNurseProfile` → `.../get_nurse_profile`. ## Response envelope (`OperationResult` → `ApiResult`) Every response is the server's standard envelope, not a bare body. Success and failure share the shape; the frontend's `clientFetch`/`serverFetch` already unwrap it and throw `ApiError` on failure. Document each endpoint's **payload** (the `data`/result) and its failure cases. The envelope carries at least: a success flag, an HTTP-aligned status, a user-safe message, and the typed `data` (or validation errors). The canonical shape is defined by `Baya.Application/Models/ApiResult` + `OperationResult` on the server — mirror that, don't invent a new envelope. ## Status codes - `200` success (payload in `data`). - `400` validation/business-rule failure (field-level errors included). - `401` unauthenticated (missing/expired token) · `403` unauthorized (lacks permission). - `404` not found. - `409` conflict (idempotency / duplicate / state-machine violation) where applicable. - `5xx` unexpected (generic safe message; details only in server logs). ## Auth - Bearer JWE in `Authorization: Bearer ` (access token, ~15 min). Refresh via the refresh endpoint; rotation + reuse-detection apply. The client attaches the header automatically in `clientFetch`. State which policy/role each endpoint needs. ## Localisation - The client sends the active locale (`Accept-Language` / `x-app-locale`, `fa` default). Server-produced user-facing messages should honour it. Reference data that has `name_fa`/`name_en` returns both; the client picks by locale. ## Pagination (mandatory on lists) - Query params: `page` (1-based) + `page_size` (cap it server-side, e.g. ≤100). Response payload carries `items` + `total` (+ `page`/`page_size`). Document the default and max `page_size` per endpoint. ## Idempotency (money & side-effecting POSTs) - Where stated, the client sends an idempotency key (header or body field) and the server dedups. Webhook endpoints dedup on the provider's `external_event_id`. Document which endpoints require a key. ## Naming - JSON properties are the server's serialized casing (follow what NSwag/Swagger emits — typically `snake_case` to match routing, or the project's configured policy; **derive the exact casing from the published `swagger.json`, don't assume**). The frontend types match the wire exactly. > When in doubt about an envelope/casing detail, the published `openapi/swagger.json` is authoritative.