WakaStart
Utilisation de l'API

Utilisation de l'API — Conventions REST

Authentifier les requêtes, pagination, filtres, multi-tenant automatique et format d'erreur unifié.

Version v1.05 min de lecture

Utilisation de l'API — Conventions REST

Toutes les requêtes post-auth passent par la Public API (ws-back-api :3005). Ce chapitre couvre les conventions REST, l'authentification des requêtes, la pagination et le multi-tenant.

Concepts clés

  • Bearer + enriched : double authentification obligatoire pour les appels frontend.
  • API Key : alternative pour les backends serveur-à-serveur.
  • WID : identifiant court préféré dans les URLs et les paramètres.
  • Filtrage automatique : le backend filtre selon le scope du token — vous ne filtrez jamais manuellement.
  • Pagination : page-based (page + limit), pas cursor-based.

Authentification des requêtes

Méthode 1 — Bearer JWT + enriched token (frontend)

Une requête vers les services downstream doit porter deux tokens :

http
Authorization: Bearer <keycloak_access_token> (RS256, émis par Keycloak) x-enriched-token: <wakastart_token> (HS256, émis par ws-serv-token)

Sans x-enriched-token, la réponse est 401 Token enrichi manquant ou invalide.

Implémentation recommandée — proxy serveur Next.js :

typescript
// app/api/proxy/[...path]/route.ts import { cookies } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; export async function GET( req: NextRequest, { params }: { params: { path: string[] } } ) { const cookieStore = await cookies(); const accessToken = cookieStore.get("keycloak_token")?.value; const enrichedToken = cookieStore.get("wakastart_token")?.value; if (!accessToken || !enrichedToken) { return NextResponse.json({ error: "Not authenticated" }, { status: 401 }); } const apiUrl = `${process.env.WAKASTART_API_URL}/api/${params.path.join("/")}`; const url = new URL(apiUrl); req.nextUrl.searchParams.forEach((value, key) => { url.searchParams.set(key, value); }); const response = await fetch(url.toString(), { method: req.method, headers: { "Authorization": `Bearer ${accessToken}`, "x-enriched-token": enrichedToken, "Content-Type": "application/json", }, }); const data = await response.json(); return NextResponse.json(data, { status: response.status }); }

Depuis votre frontend React :

typescript
// lib/api.ts — utilise le proxy qui gère l'auth async function apiGet<T>(path: string, params?: Record<string, string>): Promise<T> { const url = new URL(`/api/proxy/${path}`, window.location.origin); if (params) { Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v)); } const res = await fetch(url.toString()); if (!res.ok) throw new ApiError(res.status, await res.json()); return res.json(); } // Usage : const users = await apiGet<UserList>("config/users", { page: "1", limit: "20" });

Méthode 2 — API Key (backend serveur-à-serveur)

Les API Keys remplacent entièrement la paire Bearer+enriched. Elles sont scopées à un Customer.

typescript
const response = await fetch(`${WAKASTART_API_URL}/api/config/users`, { headers: { "x-api-key": "sk_live_...", "Content-Type": "application/json", }, });

Les API Keys sont des secrets — ne les exposez jamais côté frontend, ne les committez jamais.


Conventions REST

ConventionDétail
Verbes HTTPGET (lecture), POST (création), PATCH (mise à jour partielle), PUT (remplacement), DELETE (suppression)
Format dateISO 8601 avec timezone : 2026-05-19T10:30:00.000Z
Identifiants dans les URLsPréférer les WIDs (/config/users/WKST05) aux UUIDs
Content-Typeapplication/json sur tous les POST/PATCH/PUT
EncodageUTF-8 obligatoire
NullabilitéLes champs absents ne sont pas retournés (pas de null explicite sauf si documenté)

Format d'erreur unifié

json
{ "statusCode": 403, "message": "Niveau d'administration insuffisant. Requis: CustomerAdmin, Actuel: User", "error": "Forbidden" }

Pour les erreurs de validation (400) :

json
{ "statusCode": 400, "message": [ "email must be an email", "firstName should not be empty" ], "error": "Bad Request" }

Pagination

Tous les endpoints de liste supportent la pagination par page :

http
GET /api/config/users?page=1&limit=20
json
{ "data": [ { "id": "uuid", "wid": "WKST05", "email": "john@acme.com" } ], "meta": { "total": 142, "page": 1, "limit": 20, "totalPages": 8 } }

Paramètres :

ParamDéfautMaxDescription
page1Numéro de page (1-indexed)
limit20100Nombre d'éléments par page

Pattern avec TanStack Query :

typescript
import { useQuery } from "@tanstack/react-query"; function useUsers(page: number) { return useQuery({ queryKey: ["users", page], queryFn: () => apiGet<UserList>("config/users", { page: String(page), limit: "20" }), placeholderData: (prev) => prev, }); }

Filtres communs

http
GET /api/config/users?search=john&isActive=true&page=1&limit=20 GET /api/config/customers?networkId=NET001&page=1 GET /api/invitations/sent?status=PENDING&page=1&limit=10

Multi-tenant automatique

Les données sont automatiquement filtrées selon le scope du token :

adminLevelPortée des données retournées
WakaAdminToute la plateforme
OwnerAdminSon Partner entier
NetworkAdminSon Network + tous ses Customers
CustomerAdminSon Customer uniquement
UserSon propre profil

Vous n'avez pas besoin de filtrer manuellement. Si un CustomerAdmin appelle GET /api/config/users, il ne voit que les utilisateurs de son Customer.


Runtime config

Pour charger le thème, les langues et le branding de votre app en un seul appel :

http
GET /api/apps/{appWid}/runtime-config Authorization: Bearer <token> x-enriched-token: <wakaToken>
json
{ "theme": { "id": "uuid", "name": "Default", "cssUrl": "https://storage.wakastart.app/themes/default.css" }, "languages": [ { "code": "fr", "name": "Français", "isDefault": true, "i18nUrl": "https://storage.wakastart.app/i18n/fr.json" } ], "branding": { "logoLightUrl": "https://storage.wakastart.app/logos/acme-light.png", "logoDarkUrl": "https://storage.wakastart.app/logos/acme-dark.png", "faviconUrl": "https://storage.wakastart.app/favicons/acme.ico" } }

Bonnes pratiques

  • Proxy serveur : ne laissez jamais le browser manipuler les cookies ou les tokens directement.
  • Gestion des 401 : tenter un refresh token, puis redirect vers login. Jamais de boucle infinie.
  • Préférer les WIDs : dans vos routes et vos paramètres, les WIDs (WKST05) sont plus lisibles que les UUIDs.
  • Limit max 100 : ne dépassez pas limit=100 par page.
  • TanStack Query : utilisez staleTime pour éviter les re-fetches inutiles (5-30s selon la criticité).

Pièges classiques

  • Header x-enriched-token absent : toutes les requêtes frontend retournent 401.
  • Filtrage manuel inutile : ajouter customerId=xxx manuellement alors que le backend filtre déjà.
  • limit=1000 : timeout garanti sur les gros tenants. Paginez proprement.
  • CORS sur les appels directs : si votre frontend appelle directement l'API sans proxy, vous aurez des erreurs CORS.

Aller plus loin