🔒 ILYGO Privacy LLM — API v1

Stateless API pour intégration M2M. Anonymise du texte via détection NER (LLM + regex), exécute via Claude CLI, et désanonymise — le tout côté serveur.

Authentification
(aucune auth requise — API_TOKEN non défini côté serveur)
Routes ouvertes (mode dev). Configurez API_TOKEN en production.

CORS

Cross-origin autorisé (Access-Control-Allow-Origin: *). Méthodes : GET, POST, OPTIONS.

Types d'entités supportés

PERSON · EMAIL · PHONE · ADDRESS · IBAN · ORG · DATE · URL · ID_NUMBER · IP_ADDRESS · MAC_ADDRESS · API_KEY · TAX_ID · CREDIT_CARD · DATE_OF_BIRTH · MEDICAL_CONDITION · JOB_TITLE

Les placeholders PERSON intègrent le genre : [PERSON_H_N] (homme), [PERSON_F_N] (femme), [PERSON_N] (indéterminé).

POST/api/v1/anonymize

Détecte les entités, retourne le texte avec placeholders + mapping inverse.

Request body

{
  "text": "Marie Dupont (marie@acme.ch) chez Acme SA.",
  "entityTypes": ["PERSON", "EMAIL", "ORG"],   // optionnel, défaut: []
  "persist": false                              // optionnel, sauve en DB si true
}

Response 200

{
  "anonymizedText": "[PERSON_F_1] ([EMAIL_1]) chez [ORG_1].",
  "mapping": {
    "[PERSON_F_1]": "Marie Dupont",
    "[EMAIL_1]": "marie@acme.ch",
    "[ORG_1]": "Acme SA"
  },
  "entities": [ /* détail des entités détectées */ ],
  "sessionId": 42  // uniquement si persist=true
}

Errors

Exemple curl

curl -X POST http://localhost:3000/api/v1/anonymize \
  -H "Content-Type: application/json" \
  -d '{"text":"Marie Dupont","entityTypes":["PERSON"]}'

POST/api/v1/deanonymize

Restaure les valeurs réelles dans une réponse contenant des placeholders. Tolérant aux inversions de genre.

Request body (stateless)

{
  "cloudResponse": "Bonjour [PERSON_F_1], ...",
  "mapping": {
    "[PERSON_F_1]": "Marie Dupont"
  }
}

Request body (stateful, via session)

{
  "cloudResponse": "Bonjour [PERSON_F_1], ...",
  "sessionId": 42
}

Response 200

{
  "deanonymized": "Bonjour Marie Dupont, ...",
  "alerts": [
    {
      "severity": "warn",
      "kind": "gender_flip",
      "placeholder": "[PERSON_H_1]",
      "suggestion": "[PERSON_F_1]",
      "message": "..."
    }
  ]
}

Les types d'alertes : orphan (placeholder absent du mapping), gender_flip (genre inversé), unknown_type (type inconnu), unresolved (placeholder resté en clair).

POST/api/v1/validate

Valide structurellement une réponse cloud sans la désanonymiser ni rien persister. Utile pour CI/CD ou lint.

Request body

{
  "cloudResponse": "Bonjour [PERSON_F_1], ...",
  "mapping": { "[PERSON_F_1]": "Marie Dupont" }
}

Response 200

{ "alerts": [ /* idem deanonymize */ ] }

POST/api/v1/process

Pipeline complet en 1 appel synchrone : anonymise → Claude CLI (compte abonné) → désanonymise → valide.

Request body

{
  "text": "Marie Dupont travaille chez Acme SA.",
  "entityTypes": ["PERSON", "ORG"],                  // optionnel
  "claudeInstruction": "Reformule ce texte en langage juridique.", // optionnel, prepended
  "guard": true,                                      // optionnel, défaut true
  "persist": false                                    // optionnel
}

Response 200

{
  "anonymizedText": "[PERSON_F_1] travaille chez [ORG_1].",
  "mapping": { "[PERSON_F_1]": "Marie Dupont", "[ORG_1]": "Acme SA" },
  "cloudResponse": "[PERSON_F_1], salariée de [ORG_1], ...",
  "deanonymized": "Marie Dupont, salariée de Acme SA, ...",
  "alerts": [],
  "timings": {
    "anonymizeMs": 1800,
    "claudeMs": 11500,
    "deanonymizeMs": 2,
    "totalMs": 13302
  },
  "sessionId": 43  // uniquement si persist=true
}

Errors

⚠ Le timeout serveur Claude est de 5 minutes (configurable via CLAUDE_TIMEOUT_MS). Côté client, prévoyez un timeout d'au moins 60s pour des prompts moyens.