Le contrôle de sécurité
POST https://api.kennmarq.com/v1/check
À partir du 2 décembre 2026, l’AI Act interdit les systèmes d’IA qui produisent des images sexuelles de toute personne paraissant être un enfant, ou d’une personne réelle sans son consentement (art. 5, par. 1, points b bis et b ter). Le contrôle de sécurité analyse une image sous ces deux angles et répond par un blocage, un signalement ou une autorisation. C’est un signal de risque aux taux d’erreur publiés, pas une garantie : c’est vous qui décidez, et vous restez responsable.
Requête
Une clé avec la portée check, et du multipart/form-data avec l’image dans file (PNG, JPEG ou WebP ; la requête fait au plus 4 Mo, et une image plus lourde, jusqu’à 25 Mo, passe par un envoi indiqué dans upload) et, en option, policy : ai-act (par défaut) ou safe-only. Chaque contrôle compte deux marquages. Pour contrôler pendant le marquage, envoyez plutôt check à POST /v1/mark.
Une vidéo (MP4, jusqu’à 25 Mo ici ; contrôlez une vidéo plus lourde pendant son marquage) est analysée sur 12 images réparties sur toute sa durée, à deux marquages chacune : la réponse est celle de sa pire image (un blocage l’emporte sur un signalement, qui l’emporte sur une autorisation), avec la position de cette image dans frame (index et seconds) et, dans frames, le nombre d’images analysées.
curl https://api.kennmarq.com/v1/check \
-H "Authorization: Bearer $KENNMARQ_API_KEY" \
-F file=@render.png -F policy=ai-act{
"object": "safety_check",
"checked_at": "2026-11-12T10:00:00Z",
"checker": { "name": "Kennmarq.com", "version": "0.5.0" },
"file": { "type": "image/png", "bytes": 1482113, "width": 1024, "height": 1024, "sha256": "…" },
"policy": "ai-act",
"verdict": "flag",
"reason": "sexual_realistic_face",
"nudity": { "label": "explicit", "score": 0.991 },
"apparent_minor": false,
"realistic_face": true
}verdict:allow,flagoublock. Un blocage reste un200: le contrôle a fonctionné, et sa réponse est le blocage.reason:sexual_apparent_minor,sexual_realistic_face,explicit, ounullpour une autorisation.nudity:none,suggestiveouexplicit, et le score du classifieur, de 0 à 1.apparent_minoretrealistic_face: évalués uniquement pour une image comportant de la nudité, etnullsinon. Le contrôle n’estime jamais l’âge isolément, et ne renvoie jamais un âge ni une identité.
Politiques
| Politique | Bloque | Signale |
|---|---|---|
ai-act | Contenu sexuel ou suggestif impliquant un mineur apparent (art. 5, par. 1, point b ter) | Contenu explicite montrant un visage réaliste : obtenez le consentement de la personne avant de le publier (art. 5, par. 1, point b bis) |
safe-only | Idem, et tout contenu explicite | Rien |
| notre socle | Contenu explicite impliquant un mineur apparent, sur chaque POST /v1/mark, quel que soit son check. Impossible à désactiver | Rien |
Comment une image est analysée
Par étapes, chacune seulement si la précédente l’exige : une image sans nudité ne demande donc qu’une analyse. D’abord la nudité : explicit quand le classifieur est sûr, ou assez sûr et que le détecteur trouve une partie dénudée ; suggestive à partir d’un score de 0,3. Ensuite, pour une image comportant de la nudité : est-ce une photo ? Sur une photo, chaque visage assez grand pour être analysé (32 px ou plus) est évalué pour son âge apparent, avec des seuils plus stricts sur une image explicite que sur une image suggestive. Un dessin passe plutôt par le tagger, dont les tags indiquent quand un personnage dessiné est un enfant.
| Analyse | Modèle | Licence |
|---|---|---|
| Nudité | Le classifieur NSFW de Falconsai (ViT-B/16), avec le détecteur 320n de NudeNet comme second avis sur les images limites | Apache-2.0; MIT |
| Photo ou dessin | SigLIP de Google (base, 224 px), en zero-shot face à des descriptions de photos et de dessins | Apache-2.0 |
| Visages | YuNet, d’OpenCV Zoo | MIT |
| Âge apparent, photos | Deux modèles sur six recadrages de chaque visage : SigLIP 2 affiné sur des tranches d’âge, et age-vit de Civitai | Apache-2.0 |
| Âge apparent, dessins | wd-vit-tagger-v3 de SmilingWolf (ses tags désignant un enfant) | Apache-2.0 |
Uniquement des modèles ouverts, exécutés sur nos serveurs de Zurich et figés sur les fichiers exacts que nous avons testés.
Taux d’erreur
Part des photos réelles dont le visage a été lu comme celui d’un mineur, mesurée en octobre 2026 avec ces modèles et ces seuils sur les photos de validation de FairFace (5 980 visages) :
| Âge | Image explicite | Image suggestive |
|---|---|---|
| 0–2 | 98,5 % | 97 % |
| 3–9 | 92 % | 85 % |
| 10–19 | 47 % | 34 % |
| 20–29 | 5,9 % | 2,3 % |
| 30 ans et plus | 0,9 % | 0,6 % |
Les adultes lus comme mineurs sur des images explicites ne se répartissent pas uniformément : entre 20 et 29 ans, 8,0 % des femmes et 3,2 % des hommes ; environ 12,5 % des visages noirs et d’Asie du Sud-Est, 1,7 % des visages blancs. FairFace est le jeu d’entraînement de l’un des modèles : sur des images réelles, les résultats seront donc moins bons. Sur 78 images courantes sans nudité, le contrôle n’a déclenché aucune fausse alerte, avec l’une comme avec l’autre politique (le rapport de robustesse). Limites connues :
- un visage qu’il ne trouve pas (détourné, caché ou de moins de 32 px de haut) n’est pas évalué pour son âge : une telle photo passe donc ;
- l’âge apparent est une estimation incertaine autour de 18 ans, dans les deux sens : la plupart des adolescents plus âgés passent ;
- un rendu 3D quasi photoréaliste compte comme une photo ;
- le tagger lit mieux les dessins de style anime ; d’autres styles peuvent masquer un enfant dessiné.
Confidentialité
L’image est analysée en mémoire et jamais conservée : ni copie, ni score, ni empreinte. La réponse ne va qu’à vous, jamais dans les marquages d’un fichier.
Erreurs
| Statut | Code | Quand |
|---|---|---|
| 400 | invalid_request | Aucun fichier, un champ envoyé deux fois, une politique autre que ai-act ou safe-only, ou une image illisible. |
| 400 | unknown_field | Un champ autre que file (ou upload) et policy. |
| 400 | option_not_available | url, categorize ou describe : pas encore disponibles. |
| 401 | missing_api_key, invalid_api_key, api_key_revoked | Voir Authentification. |
| 402 | quota_exceeded | Il reste moins de deux marquages ce mois-ci (24 pour une vidéo). |
| 403 | insufficient_scope, ip_not_allowed | La clé n’a pas la portée check, ou l’adresse ne figure pas sur la liste d’IP autorisées. |
| 404 | upload_not_found | L’envoi indiqué n’est pas utilisable par cette clé : inconnu, déjà utilisé, expiré ou appartenant à une autre clé. |
| 413 | payload_too_large | La requête dépasse 4 Mo (envoyez les fichiers plus lourds via un envoi), ou une vidéo dépasse 25 Mo ou nos limites. |
| 415 | unsupported_media_type | Pas une image PNG, JPEG ou WebP ni une vidéo MP4, ou pas envoyé en multipart/form-data. |
| 429 | rate_limited | Trop d’appels cette minute ; réessayez après le nombre de secondes indiqué dans Retry-After. |
| 503 | marker_unavailable, storage_unavailable | Le contrôle (ou les envois) ne peut pas s’exécuter pour le moment. Il n’est jamais ignoré : rien n’est décompté ; réessayez. |
Les corps d’erreur suivent le format commun.