Files
datacat/documentation/api-reference.md
z3n 0976c33059 feat(api-detail): isCurrent + setCurrent + màj doc et seeder
- Shared types : ajout isCurrent sur ApiEntry et ApiEntryListItem
- Backend entity : colonne is_current (boolean, default true)
- Backend service : isCurrent calculé à la création, setCurrent()
  marque une version comme courante (siblings → false)
- Backend controller : POST /api/apis/:id/set-current
- Frontend ApiService : méthode setCurrent()
- Browse/upload : affichage badge "Courante" via isCurrent
- Seeder : données de démo mises à jour
- Documentation : api-reference, architecture, local-setup, CLAUDE.md

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-06-19 14:23:31 +00:00

11 KiB

Référence API — Datacat

Base URL en développement : http://localhost:3010

Toutes les routes JSON retournent Content-Type: application/json.


Health

GET /health

Vérifie que le serveur est opérationnel.

Réponse 200

{ "status": "ok" }

APIs (/api/apis)

GET /api/apis

Liste les entrées avec filtres optionnels et pagination.

Query parameters

Paramètre Type Défaut Description
search string Recherche dans name, provider, description, contacts (case-insensitive)
type ASYNCAPI | OPENAPI Filtre par type
categoryId UUID Filtre par catégorie
page number 1 Page (min 1)
limit number 20 Taille de page (min 1, max 100)

Réponse 200

{
  "items": [
    {
      "id": "uuid",
      "title": "Consulter Petstore",
      "name": "Petstore",
      "convention": "CONSULTER",
      "version": "1.0.0",
      "description": "...",
      "type": "OPENAPI",
      "provider": "Équipe Produit",
      "status": "GENERATED",
      "categoryId": "uuid-or-null",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "total": 42,
  "page": 1,
  "limit": 20
}

items contient des ApiEntryListItem (sans yamlContent, htmlPath, contacts ni versionMajor/Minor/Patch).


GET /api/apis/:id

Retourne le détail complet d'une entrée.

Réponse 200

{
  "id": "uuid",
  "title": "Consulter Petstore",
  "name": "Petstore",
  "convention": "CONSULTER",
  "version": "1.0.0",
  "versionMajor": 1,
  "versionMinor": 0,
  "versionPatch": 0,
  "description": "...",
  "type": "OPENAPI",
  "provider": "Équipe Produit",
  "yamlContent": "openapi: '3.0.0'\n...",
  "htmlPath": "/app/docs-output/uuid/index.html",
  "status": "GENERATED",
  "errorMessage": null,
  "categoryId": "uuid-or-null",
  "contactFunctionalName": "Alice Martin",
  "contactFunctionalEntity": "DSI",
  "contactFunctionalEmail": "alice@example.com",
  "contactTechnicalName": "Bob Dupont",
  "contactTechnicalEntity": "Équipe Backend",
  "contactTechnicalEmail": "bob@example.com",
  "createdAt": "2025-01-01T00:00:00.000Z",
  "updatedAt": "2025-01-01T00:00:00.000Z"
}

Réponse 404 — entrée introuvable


PATCH /api/apis/:id

Met à jour les métadonnées d'une entrée (champs éditables par l'utilisateur).

Body JSON (tous les champs sont optionnels)

{
  "convention": "CONSULTER",
  "name": "Nouveau nom",
  "provider": "Équipe X",
  "versionMajor": 2,
  "versionMinor": 0,
  "versionPatch": 0,
  "description": "Description mise à jour",
  "categoryId": "uuid-or-null",
  "contactFunctionalName": "...",
  "contactFunctionalEntity": "...",
  "contactFunctionalEmail": "...",
  "contactTechnicalName": "...",
  "contactTechnicalEntity": "...",
  "contactTechnicalEmail": "..."
}

Réponse 200ApiEntry complet mis à jour

Réponse 404 — entrée introuvable


DELETE /api/apis/:id

Supprime une entrée.

Réponse 204 — succès (pas de corps)

Réponse 404 — entrée introuvable


POST /api/apis/:id/regenerate

Relance la génération de documentation pour une entrée existante. Remet le statut à PENDING et déclenche DocsGenerationService.generate() en arrière-plan.

Réponse 200ApiEntry avec status: "PENDING"

Réponse 404 — entrée introuvable


GET /api/apis/:id/docs

Retourne le fichier HTML de documentation généré.

Réponse 200text/html (fichier statique servi via res.sendFile)

Réponse 404

  • Entrée introuvable
  • Documentation pas encore générée (htmlPath est null)

GET /api/apis/:id/yaml

Télécharge le fichier YAML source.

Réponse 200

  • Content-Type: application/x-yaml
  • Content-Disposition: attachment; filename="<name>.yaml"
  • Corps : contenu YAML brut

Réponse 404 — entrée introuvable


Upload (/api/uploads)

POST /api/uploads/validate

Valide 1 à 20 fichiers YAML sans créer d'entrée en base. Utilisé pour la validation en temps réel lors de l'upload.

Content-Type : multipart/form-data

Champs du formulaire

Champ Type Requis Description
files file (1 à 20) Oui Fichiers YAML (.yaml ou .yml)

Réponse 200

{
  "valid": true,
  "type": "OPENAPI",
  "mainFile": "petstore.yaml",
  "name": "Petstore",
  "versionMajor": 1,
  "versionMinor": 0,
  "versionPatch": 0,
  "description": "A sample API",
  "errors": []
}

En cas d'erreur :

{
  "valid": false,
  "type": null,
  "mainFile": null,
  "name": null,
  "versionMajor": null,
  "versionMinor": null,
  "versionPatch": null,
  "description": null,
  "errors": [
    { "file": "api.yaml", "message": "erreur de syntaxe YAML — unexpected token" }
  ]
}

POST /api/uploads

Crée une nouvelle entrée à partir d'un ou plusieurs fichiers YAML. Lance la génération de documentation en arrière-plan (fire-and-forget).

Content-Type : multipart/form-data

Champs du formulaire

Champ Type Requis Description
files file (1 à 20) Oui Fichiers YAML (.yaml ou .yml)
convention CONSULTER | ENREGISTRER | ETRE_NOTIFIE Oui Convention d'échange
name string Oui Nom de l'API
provider string Oui Fournisseur / équipe responsable
versionMajor string (number) Non Version majeure (défaut: 0)
versionMinor string (number) Non Version mineure (défaut: 0)
versionPatch string (number) Non Version patch (défaut: 0)
description string Non Description libre
type ASYNCAPI | OPENAPI Non Type (détecté automatiquement si absent)
categoryId UUID Non Catégorie parente
contactFunctionalName string Non Contact métier — nom
contactFunctionalEntity string Non Contact métier — entité
contactFunctionalEmail string Non Contact métier — email
contactTechnicalName string Non Contact technique — nom
contactTechnicalEntity string Non Contact technique — entité
contactTechnicalEmail string Non Contact technique — email

Détection automatique du type

Le type est détecté à partir du contenu YAML :

  • Présence de openapi: en début de ligne → OPENAPI
  • Présence de asyncapi: en début de ligne → ASYNCAPI

Si plusieurs fichiers sont fournis, le fichier contenant la clé racine est considéré comme le fichier principal. Les autres sont bundlés via redocly bundle (OpenAPI) ou @asyncapi/bundler (AsyncAPI).

Réponse 201ApiEntry créé avec status: "PENDING"

Réponse 400

  • Aucun fichier fourni
  • name ou convention manquant
  • Fichier non YAML
  • Type non détectable et non fourni
  • Aucun fichier principal trouvé dans un upload multi-fichiers

Catégories (/api/categories)

GET /api/categories

Retourne toutes les catégories, triées par order_index puis name.

Réponse 200

{
  "items": [
    {
      "id": "uuid",
      "name": "Infrastructure",
      "description": "...",
      "parentId": null,
      "orderIndex": 0,
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ]
}

GET /api/categories/browse

Navigation à la racine : retourne les catégories de premier niveau et les APIs sans catégorie.

Réponse 200CategoryBrowseResponse

{
  "category": null,
  "breadcrumb": [],
  "subcategories": [
    {
      "id": "uuid",
      "name": "Infrastructure",
      "description": "...",
      "parentId": null,
      "orderIndex": 0,
      "subcategoryCount": 2,
      "apiCount": 5,
      "createdAt": "...",
      "updatedAt": "..."
    }
  ],
  "apis": [
    {
      "id": "uuid",
      "title": "Consulter API sans catégorie",
      "name": "API sans catégorie",
      "convention": "CONSULTER",
      "version": "1.0.0",
      "provider": "...",
      "status": "GENERATED",
      "categoryId": null,
      "..."
    }
  ]
}

GET /api/categories/browse/:id

Navigation dans une catégorie : retourne ses sous-catégories et ses APIs directes.

Réponse 200CategoryBrowseResponse

{
  "category": { "id": "uuid", "name": "Infrastructure", ... },
  "breadcrumb": [
    { "id": "parent-uuid", "name": "Catégorie parente", ... },
    { "id": "uuid", "name": "Infrastructure", ... }
  ],
  "subcategories": [ ... ],
  "apis": [ ... ]
}

Réponse 404 — catégorie introuvable


GET /api/categories/:id

Retourne le détail d'une catégorie.

Réponse 200Category

Réponse 404 — catégorie introuvable


POST /api/categories

Crée une nouvelle catégorie.

Body JSON

{
  "name": "Infrastructure",
  "description": "APIs d'infrastructure",
  "parentId": "uuid-or-null",
  "orderIndex": 0
}
Champ Type Requis
name string Oui
description string Non
parentId UUID Non
orderIndex number Non (défaut: 0)

Réponse 201Category créée


PATCH /api/categories/:id

Met à jour une catégorie.

Body JSON (tous les champs sont optionnels)

{
  "name": "Nouveau nom",
  "description": "...",
  "parentId": "uuid-or-null",
  "orderIndex": 1
}

Réponse 200Category mise à jour

Réponse 404 — catégorie introuvable


DELETE /api/categories/:id

Supprime une catégorie.

Réponse 204 — succès (pas de corps)

Réponse 400 — le dossier contient des APIs ou des sous-dossiers (vérification applicative avant suppression)

Réponse 404 — catégorie introuvable


Codes d'erreur communs

Code Description
400 Requête invalide (champ manquant, format incorrect, suppression non vide)
404 Ressource introuvable
500 Erreur interne serveur

Format d'erreur

{
  "statusCode": 404,
  "message": "API entry <uuid> not found",
  "error": "Not Found"
}

Statuts d'une entrée API

Statut Description
PENDING Entrée créée, génération de doc en cours
GENERATED Documentation HTML disponible
ERROR La génération a échoué (voir errorMessage)

Conventions d'échange

Convention Label affiché
CONSULTER Consulter
ENREGISTRER Enregistrer
ETRE_NOTIFIE Être notifié