Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

07 — API Conventions (Shared)

Exact wire contract of the StudyLyon API, derived from source (ResponseEnvelopeInterceptor, HttpExceptionFilter, PaginationQueryDto, rate-limit guards, WsModule). Module docs 12_API_Mapping.md map screens to endpoints using only these shapes.


1. Base

  • Base URL: https://api.<domain>/api/v1 (version prefix v1; see version.constants.ts).
  • Content-Type: application/json; multipart for file uploads.
  • Auth: Authorization: Bearer <accessToken>; refresh via POST /auth/refresh.
  • Request ID: server echoes x-request-id; client sends its own UUID when absent.
  • API keys (X-API-Key) for M2M — not used by the client app.

2. Success envelope (exact)

{
  "success": true,
  "message": "OK",
  "data": { },
  "meta": { },
  "timestamp": "2026-08-02T10:00:00.000Z",
  "requestId": "..."
}
  • Paginated endpoints return data = array, meta = { page, limit, totalItems, totalPages, hasNext, hasPrevious }.
  • Non-paginated endpoints omit meta.

3. Error envelope (exact)

{
  "success": false,
  "message": "Validation failed.",
  "error": { "code": "VALIDATION_ERROR", "details": [{ "field": "email", "message": "..." }] },
  "timestamp": "...",
  "requestId": "..."
}
HTTPCodeMeaning
400VALIDATION_ERRORInvalid input (details = per-field)
401UNAUTHENTICATEDMissing/expired/invalid token
403PERMISSION_DENIEDAuthed but not allowed
404RESOURCE_NOT_FOUNDMissing resource (also for cross-tenant IDs — do not leak existence)
409DUPLICATE_RESOURCEUnique constraint hit
422BUSINESS_RULE_VIOLATIONBusiness rule refused
429RATE_LIMITEDRate limit exceeded
5xxINTERNAL_SERVER_ERRORGeneric; never expose internals

4. Rate limits (client-relevant)

TierLimitNotes
auth10/minlogin, register, reset — client shows countdown, no auto-retry
api100/minnormal app usage; client backoff on 429
admin500/minadmin endpoints

5. Pagination & filtering conventions

  • Query: page (1-based), limit (1–100, default 20), sort (field or -field), q (global search term where the controller supports it).
  • Filters are controller-specific query params (documented per module).

6. Multi-tenancy & auth

  • Every request carries JWT with tenantId claim; server derives tenant from token — client never sends tenantId in the body.
  • Guard: Public() decorator exempts auth endpoints only.
  • Cross-tenant access → 403/404; client treats as permission/not-found.

7. Caching (client + server)

  • Server: Redis cache sl:{tenantId}:{key}, TTL per module; dashboard KPIs cached.
  • Client: last-good cache + stale-while-revalidate (06_State_Management.md §3.3).
  • No Cache-Control guarantees from API — client caching is advisory.

8. Realtime (WebSocket)

  • Gateway: WS upgrade with Authorization: Bearer <token> (or first-message auth).
  • Channels: per-user room user:{userId}; topics notification.new, message.new, announcement.published, attendance.changed, invoice.updated, results.published.
  • Message shape: { type: topic, tenantId, data, timestamp }.
  • Disconnect → buffered in-app notifications delivered via REST on next fetch.

9. Optimistic UI & idempotency (client contract)

  • Safe mutations: PATCH read, status toggles → optimistic + rollback.
  • Write-once ops (payment, publish, submit) → show server result, no local write.
  • Client sends Idempotency-Key header (UUID) on critical POSTs where the module API supports dedup; retry-safe by design otherwise.

10. Offline strategy

  • Reads: last-good cache, offline banner, Retry on every failure.
  • Writes: only module-defined queues (attendance bulk, homework draft) with local persistence + flush on reconnect + idempotency keys.
  • Files: uploads resume-capable (chunked) only where backend supports it — otherwise queue with retry + DLQ visibility.

11. Security (client obligations)

  • Tokens in secure storage (Keychain/Keystore), never logs.
  • Biometric gate for sensitive screens (payments, admin settings) — forward-looking (backend 2FA exists; client-side gate is app-level).
  • TLS only; pinning per org policy.
  • All error UI derived from server codes — never render raw server messages that may contain internals (use i18n keys, fall back to message for 4xx business text only).

12. Versioning

  • v1 current; breaking changes → new version prefix; client negotiates via Accept: application/vnd.studylyon.v1+json if backend adds it (flag: not in code yet).