Skip to content

The safety check

POSThttps://api.kennmarq.com/v1/check

From 2 December 2026 the AI Act bans AI systems that make sexual pictures of anyone appearing to be a child, or of a real person without their consent (Art. 5(1)(ba) and (bb)). The safety check screens a picture for both, as a block, flag or allow. It's a risk signal with published error rates, not a guarantee: you decide, and you stay responsible.

Request

A key with the check scope, and multipart/form-data with the picture in file (PNG, JPEG or WebP; the request is at most 4 MB, and a larger picture, up to 25 MB, goes through an upload named in upload) and, optionally, policy: ai-act (the default) or safe-only. Each check counts two marks. To check while marking, send check to POST /v1/mark instead.

A clip (MP4, up to 25 MB here; check a larger one while marking it) is read on 12 frames spread over it, two marks each: the answer is its worst frame's (a block over a flag over an allow), with that frame's place in frame (index and seconds) and frames, how many were read.

curl
curl https://api.kennmarq.com/v1/check \
  -H "Authorization: Bearer $KENNMARQ_API_KEY" \
  -F file=@render.png -F policy=ai-act
200 application/json
{
  "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, flag or block. A block is still a 200: the check worked, and its answer is the block.
  • reason: sexual_apparent_minor, sexual_realistic_face, explicit, or null for an allow.
  • nudity: none, suggestive or explicit, and the classifier's score, 0 to 1.
  • apparent_minor and realistic_face: read only for a picture with nudity, and null otherwise. The check never estimates ages on their own, and never returns an age or an identity.

Policies

What each policy blocks and flags
PolicyBlocksFlags
ai-actSexual or suggestive content with an apparent minor (Art. 5(1)(bb))Explicit content with a realistic face: get the person's consent before you publish it (Art. 5(1)(ba))
safe-onlyThe same, and anything explicitNothing
our floorExplicit content with an apparent minor, on every POST /v1/mark whatever its check. You can't turn it offNothing

How a picture is read

In steps, each only when the one before calls for it, so a picture without nudity costs one read. Nudity first: explicit when the classifier is sure, or fairly sure and the detector finds an exposed part; suggestive from a score of 0.3. Then, for a picture with nudity: is it a photo? For a photo, each face large enough to read (32 px or more) is read for apparent age, at stricter lines on an explicit picture than on a suggestive one. A drawing goes to the tagger instead, whose tags say when a drawn character is a child.

The models the check runs
ReadModelLicence
NudityFalconsai's NSFW classifier (ViT-B/16), with NudeNet's 320n detector as a second opinion on borderline picturesApache-2.0; MIT
Photo or drawingGoogle's SigLIP (base, 224 px), zero-shot against photo and drawing descriptionsApache-2.0
FacesOpenCV Zoo's YuNetMIT
Apparent age, photosTwo models on six cuts of each face: SigLIP 2 fine-tuned on age bands, and Civitai's age-vitApache-2.0
Apparent age, drawingsSmilingWolf's wd-vit-tagger-v3 (its child tags)Apache-2.0

All open models, run on our servers in Zurich, pinned to the exact files we tested.

Error rates

Share of real photos whose face was read as a minor, measured in October 2026 with these models and lines on FairFace's validation photos (5,980 faces):

Faces read as a minor, by age
AgeExplicit pictureSuggestive picture
0–298.5%97%
3–992%85%
10–1947%34%
20–295.9%2.3%
30 and over0.9%0.6%

Adults read as minors in explicit pictures are not spread evenly: in their twenties, women 8.0% and men 3.2%; Black and Southeast Asian faces about 12.5%, White faces 1.7%. FairFace is one model's own training set, so real pictures will do worse. On everyday pictures without nudity, the check raised no false alarm in 78 under either policy (the robustness report). Known limits:

  • a face it can't find (turned away, hidden, or under 32 px tall) gets no age read, so such a photo passes;
  • apparent age is a guess near 18, both ways: most older teens pass;
  • a near-photoreal 3D render counts as a photo;
  • the tagger reads anime-style drawings best; other styles may hide a drawn child.
Say the check helps you meet the Art. 5 safeguards, never that it prevents abuse or detects abuse material. Keep your own review for flags, and for what a filter like this misses.

Privacy

The picture is read in memory and never kept: no copy, no score, no hash. The answer goes only to you, never into a file's marks.

Errors

Errors of POST /v1/check
StatusCodeWhen
400invalid_requestNo file, a field sent twice, a policy other than ai-act or safe-only, or a picture that can't be read.
400unknown_fieldA field other than file (or upload) and policy.
400option_not_availableurl, categorize or describe: not available yet.
401missing_api_key, invalid_api_key, api_key_revokedSee authentication.
402quota_exceededFewer than two marks left this month (24 for a clip).
403insufficient_scope, ip_not_allowedThe key lacks the check scope, or the address isn't allowlisted.
404upload_not_foundThe upload named isn't one this key can use: unknown, used, expired, or another key's.
413payload_too_largeThe request is over 4 MB (send larger files through an upload), or a clip over 25 MB or our limits.
415unsupported_media_typeNot a PNG, JPEG or WebP picture or an MP4 clip, or not sent as multipart/form-data.
429rate_limitedToo many calls this minute; retry after Retry-After seconds.
503marker_unavailable, storage_unavailableThe check (or uploads) can't run right now. It never skips: nothing is charged; retry.

Error bodies follow the common format.