Documentation

API REST — Intégrez MasqID
dans vos workflows.

Anonymisation et pseudonymisation par appel HTTP, à intégrer dans vos workflows automatisés (n8n, Make, Zapier, scripts Python ou Node). Hébergé en France, sans cloud tiers, sans LLM.

Sommaire
  1. Vue d'ensemble
  2. Authentification
  3. Rate limiting & sécurité
  4. Identifiants de jobs
  5. Endpoints
  6. Workflow simple
  7. Workflow avec review
  8. Dépseudonymisation
  9. Erreurs
  10. SDK & exemples

Vue d'ensemble

L'API MasqID expose 3 endpoints webhook pour l'anonymisation et 1 endpoint statique pour récupérer les résultats. Deux flows :

Base URL : https://n8n.fsiavocat.com

Base URL statique (résultats) : https://anonymize.fsiavocat.com/status/

Authentification

L'API est actuellement publique (pas de clé requise) pendant la phase de validation 2026. Une authentification par clé sera ajoutée à la mise en commercialisation. Contact : contact@fsi-avocats.fr

Usage à volume. Si vous prévoyez plus de 100 documents / jour ou une intégration en production, contactez-nous pour obtenir une clé API dédiée (limites augmentées, SLA).

Rate limiting & sécurité

Protection au niveau Nginx (anti-flood, anti-bruteforce) :

Filtres applicatifs côté webhook :

Identifiants de jobs

Chaque scan génère un jobId au format UUID v4 cryptographique (128 bits d'entropie, CSPRNG via crypto.randomUUID()), encodé en 32 hex sans tirets. Aucune information temporelle ni séquentielle n'est récupérable depuis le jobId.

// Exemple de jobId valide
"24d0b6bde16145feb8ec481718d4d16a"
// Validation regex backend
/^[a-f0-9]{32}$/

Endpoints

POST /webhook/anonymize

Anonymise un document en une seule étape (scan + application). Retourne immédiatement un jobId — le traitement est asynchrone.

Request (multipart/form-data)

ChampTypeDescription
filebinaryDocument à traiter (PDF, DOCX, XLSX, MD, TXT)
modestringpseudo (réversible) ou redact (irréversible)
levelstringmaximum (défaut) — niveau de détection
extra_termsstring (opt)Termes supplémentaires à détecter, un par ligne
whitelist_termsstring (opt)Termes à ignorer, un par ligne

Response — 202 Accepted

{
  "status": "accepted",
  "jobId": "a1b2c3d4e5f6...",
  "message": "Document en cours de traitement."
}
POST /webhook/anonymize-scan

Étape 1/2 du workflow review. Lance le scan PII seul et retourne la liste des entités détectées. Le document source est conservé 30 min pour l'étape d'application.

Request (multipart/form-data)

ChampTypeDescription
filebinaryDocument à scanner

Response — 200 OK

{
  "jobId": "a1b2c3d4...",
  "fileName": "contrat.pdf",
  "fileSizeMB": "0.12",
  "pii": {
    "terms": [
      { "text": "Jean DUPONT", "type": "REGEX_IDENTITE" },
      { "text": "MonSaaS SAS", "type": "REGEX_SOCIETE" }
    ],
    "summary": { "total_pii": 23 }
  },
  "status": "scan_completed"
}
POST /webhook/anonymize-apply

Étape 2/2 du workflow review. Applique le traitement sur le document avec la liste de PII filtrée par l'utilisateur.

Request (application/json)

{
  "jobId": "a1b2c3d4...",
  "mode": "pseudo",
  "fileName": "contrat.pdf",
  "pii": [
    { "text": "Jean DUPONT", "type": "PII" },
    { "text": "MonSaaS SAS", "type": "PII" }
  ]
}

Response — 202 Accepted

{ "status": "accepted", "jobId": "a1b2c3d4..." }
GET https://anonymize.fsiavocat.com/status/{jobId}.json

Polling du statut d'un job. Intervalle recommandé : 4 secondes.

Response — en cours

{
  "status": "processing",
  "pct": 75,
  "message": "Génération du document anonymisé...",
  "mode": "pseudo",
  "fileName": "contrat.pdf"
}

Response — terminé

{
  "status": "completed",
  "pct": 100,
  "mode": "pseudo",
  "fileName": "contrat.pdf",
  "entityCount": 23,
  "wordCount": 2145,
  "hasMapping": true,
  "hasPreview": true,
  "hasDoc": true,
  "docExt": "pdf",
  "hasSignature": false,
  "hasEncrypted": false,
  "completedTime": "2026-04-20T14:32:18Z"
}

Fichiers associés (après completed)

Génération côté client

Les artefacts suivants sont produits dans votre navigateur à partir des fichiers ci-dessus (aucun endpoint serveur, aucune exposition de données originales) :

Rétention : 30 minutes. Tous les fichiers sont supprimés automatiquement du serveur 30 min après la fin du traitement (purge cron toutes les 5 min). Téléchargez les résultats avant ce délai.

Workflow simple (1 étape)

Exécution entièrement automatique. Pas d'intervention humaine.

# 1. Upload
curl -X POST https://n8n.fsiavocat.com/webhook/anonymize \
  -F "file=@contrat.pdf" \
  -F "mode=pseudo" \
  -F "level=maximum"

# Response : { "jobId": "a1b2c3d4...", "status": "accepted" }

# 2. Polling
JOB_ID="a1b2c3d4..."
while true; do
  STATUS=$(curl -s "https://anonymize.fsiavocat.com/status/${JOB_ID}.json")
  STATE=$(echo "$STATUS" | jq -r .status)
  echo "$STATE"
  [ "$STATE" = "completed" ] && break
  sleep 4
done

# 3. Téléchargement
curl -O "https://anonymize.fsiavocat.com/status/${JOB_ID}_doc.pdf"
curl -O "https://anonymize.fsiavocat.com/status/${JOB_ID}_mapping.json"

Workflow avec review (2 étapes)

Valider manuellement la liste des PII avant le traitement. Idéal pour les documents complexes où les faux positifs doivent être écartés.

# 1. Scan
curl -X POST https://n8n.fsiavocat.com/webhook/anonymize-scan \
  -F "file=@contrat.pdf"

# Response : { "jobId": "...", "pii": { "terms": [...] } }

# 2. Filtrer les PII côté client (exemple : retirer les faux positifs,
#    ajouter des termes manuels) ... traitement custom

# 3. Apply avec la liste filtrée
curl -X POST https://n8n.fsiavocat.com/webhook/anonymize-apply \
  -H "Content-Type: application/json" \
  -d '{
    "jobId": "a1b2c3d4...",
    "mode": "pseudo",
    "fileName": "contrat.pdf",
    "pii": [
      { "text": "Jean DUPONT", "type": "PII" },
      { "text": "MonSaaS SAS", "type": "PII" }
    ]
  }'

# 4. Polling + téléchargement (idem workflow simple)

Dépseudonymisation

Aucun endpoint serveur n'est exposé pour la dépseudonymisation : la restauration s'effectue 100 % côté navigateur via /depseudo.html (interface drag & drop) ou directement en local en croisant mapping.json avec le document pseudonymisé.

Logique de restauration (pseudo-code) :

// 1. Charger mapping.json (clair ou .enc.json déchiffré localement)
const mapping = JSON.parse(text);

// 2. Pour chaque placeholder dans le document, remplacer par sa version canonique
for (const [placeholder, info] of Object.entries(mapping.reverse)) {
  text = text.replaceAll(`<${placeholder.replace(/^<|>$/g, '')}>`, info.canonical);
}

// 3. Le mapping reverse contient également les variantes capturées
//    (ex: "DUPONT" / "M. DUPONT" / "Jean DUPONT") — utile pour les
//    documents partiellement pseudonymisés.
Pourquoi pas d'endpoint serveur ? Aligné avec l'invariant produit MasqID : la table de correspondance ne quitte jamais le navigateur. Le serveur n'a aucun moyen de ré-identifier les documents. Cohérent avec RGPD art. 5.1.f (intégrité et confidentialité) et le secret professionnel des avocats.

Erreurs

CodeSignificationCauses typiques
200OKScan terminé (endpoint scan only)
202AcceptedJob créé, traitement asynchrone
400Bad RequestParamètres invalides, mode inconnu, jobId mal formé
413Payload Too LargeFichier > 256 Mo
429Too Many RequestsRate limit dépassé
500Server ErrorErreur du pipeline (scan, extraction, format non supporté)

SDK & exemples d'intégration

Node.js (node-fetch / axios)

const fs = require('fs');
const FormData = require('form-data');
const fetch = require('node-fetch');

async function anonymize(filePath, mode = 'pseudo') {
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  form.append('mode', mode);
  form.append('level', 'maximum');

  const res = await fetch('https://n8n.fsiavocat.com/webhook/anonymize', {
    method: 'POST',
    body: form
  });
  const { jobId } = await res.json();

  while (true) {
    const r = await fetch(`https://anonymize.fsiavocat.com/status/${jobId}.json`);
    const data = await r.json();
    if (data.status === 'completed') return data;
    await new Promise(rs => setTimeout(rs, 4000));
  }
}

Python (requests)

import time
import requests

def anonymize(file_path, mode='pseudo'):
    with open(file_path, 'rb') as f:
        r = requests.post(
            'https://n8n.fsiavocat.com/webhook/anonymize',
            files={'file': f},
            data={'mode': mode, 'level': 'maximum'},
        )
    job_id = r.json()['jobId']

    while True:
        status = requests.get(
            f'https://anonymize.fsiavocat.com/status/{job_id}.json'
        ).json()
        if status['status'] == 'completed':
            return job_id, status
        time.sleep(4)

n8n (workflow consommateur)

Utilisez un nœud HTTP Request avec POST, Content-Type multipart/form-data, et les champs file (binary) + mode. Le polling peut se faire avec un nœud Wait + HTTP Request en boucle.

Une intégration complète vous intéresse ?
Écrivez à contact@fsi-avocats.fr pour discuter de votre cas d'usage (volume, SLA, clé API dédiée).

Prêt à brancher MasqID dans votre workflow ?

L'API est ouverte. Testez sur 1 document, puis scalez.

Essayer gratuitement → Parler à l'équipe
© 2026 MasqID — édité par FSI Avocats · Montpellier
v3.6 · build 2026.05