Aller au contenu

API HTTP

Base : https://api.prod.aim.dyneco.io

Authentification

Toutes les routes sauf /healthz exigent un en-tête Authorization: Bearer …, avec l'un des deux types d'identifiant :

TOKEN=$(az account get-access-token \
  --resource api://de32b68a-b2c5-4ad0-8e8c-dab234a90901 \
  --query accessToken -o tsv)
curl -H "Authorization: Bearer $TOKEN" "$API/v1/me"

Validé contre les clés publiques du tenant : signature, émetteur, audience, expiration. Durée de vie une heure.

curl -H "Authorization: Bearer aimk_…" "$API/v1/me"

Créée par aim key create. Porte le principal de son créateur. Sans expiration, révocable à tout moment.

Codes de réponse

Code Sens
200 / 201 / 204 Succès
401 En-tête absent, jeton invalide ou expiré, clé inconnue ou révoquée
403 Authentifié mais rôle insuffisant pour l'action
404 Ressource absente ou client auquel tu n'as pas accès
409 Conflit : slug déjà pris, retrait du dernier propriétaire
422 Corps ou paramètre invalide

404 plutôt que 403 sur un client

Un client auquel tu n'as pas accès est indiscernable d'un client inexistant. Répondre 403 révélerait son existence.

Identité

GET /v1/me

{ "oid": "0bb5f169-…", "name": "Augustin Poelmans", "email": "augustin.poelmans@dyneco.io" }

Clients

GET /v1/clients

Les clients dont l'appelant est membre, avec son rôle et les compteurs.

POST /v1/clients

{ "slug": "acme", "name": "ACME Corp", "description": "…", "mission": "…", "max_lines": 500 }

Le créateur devient propriétaire. 409 si le slug existe, 422 si le slug est invalide (3 à 40 caractères, minuscules, chiffres et tirets, sans tiret aux extrémités).

GET /v1/clients/{slug}

PATCH /v1/clients/{slug}

Rôle contributor. Champs modifiables : name, description, mission, max_lines, include_candidates.

DELETE /v1/clients/{slug}

Rôle owner. Supprime en cascade documents, faits et appartenances.

Ingestion

POST /v1/clients/{slug}/files

Rôle contributor. multipart/form-data, champ files répétable. 25 Mio par fichier. Conversion côté serveur.

{
  "accepted": [{ "id": "…", "title": "guide-dev-backend", "changed": true }],
  "skipped":  [{ "name": "photo.png", "reason": "format non pris en charge" }]
}

POST /v1/clients/{slug}/documents

Rôle contributor. Documents déjà normalisés — c'est la voie des dépôts, dont les signaux sont calculés sur le poste de l'utilisateur.

{ "documents": [{ "id": "…", "kind": "repo", "authority": "observed",
                  "title": "…", "body": "…", "origin": "…", "tags": [] }],
  "repo_name": "payment-service" }

GET /v1/clients/{slug}/documents

DELETE /v1/clients/{slug}/documents/{doc_id}

Rôle contributor. Supprime aussi les faits dont toute la provenance venait de ce document ; un fait corroboré ailleurs survit.

Extraction

POST /v1/clients/{slug}/extract?force=false

Rôle contributor. Réponse en flux NDJSON, une ligne par événement :

{"event": "progress",  "message": "✓ guide-dev-backend — 15 faits"}
{"event": "heartbeat"}
{"event": "done", "documents_extracted": 4, "facts_created": 35, "errors": []}
{"event": "error", "message": "…"}

Battements de cœur

Un heartbeat est émis toutes les 20 secondes. L'ingress Azure coupe une connexion restée silencieuse au bout de 240 secondes, et un document volumineux peut occuper le modèle plus longtemps sans rien produire. Un client doit ignorer ces lignes, sous peine de les prendre pour une fin de flux.

POST /v1/clients/{slug}/consolidate

Même format de flux. Renvoie {"event": "done", "merged": N, "conflicts": N}.

Faits

GET /v1/clients/{slug}/facts?type=&status=

GET /v1/clients/{slug}/facts/{fact_id}

PATCH /v1/clients/{slug}/facts/{fact_id}

Rôle contributor. Champs : statement, detail, scope, status, confidence. Passer un fait en approved sans préciser de confiance la porte au moins à 0,9.

DELETE /v1/clients/{slug}/facts/{fact_id}

GET /v1/clients/{slug}/search?q=&limit=20

Recherche plein texte. Retombe sur une correspondance par préfixe si la recherche exacte ne donne rien — voir Limites connues.

Compilation

GET /v1/clients/{slug}/pack

Le pack sélectionné et hiérarchisé. Le serveur n'écrit aucun fichier : c'est le CLI qui matérialise le pack, parce que lui seul sait où se trouve le dépôt.

{ "client": {  }, "included": [  ], "skills": [  ],
  "overflow_count": 12, "overflow": [  ] }

GET /v1/clients/{slug}/conventions?path=internal/api/handler.go

Les faits applicables à un chemin, les plus spécifiques d'abord.

Accès

GET /v1/clients/{slug}/members

POST /v1/clients/{slug}/members

Rôle owner. { "principal_oid": "…", "principal_label": "…", "role": "reader" }

DELETE /v1/clients/{slug}/members/{oid}

Rôle owner. 409 si c'est le dernier propriétaire.

Clés d'API

POST /v1/keys

{ "name": "claude-code-macbook" }{ "id": "…", "name": "…", "key": "aimk_…" }

La clé en clair n'est renvoyée qu'ici.

GET /v1/keys · DELETE /v1/keys/{key_id}

Une clé n'est visible et révocable que par son créateur.

Santé

GET /healthz

Sans authentification. Utilisé par la sonde de disponibilité.