La photo d'un passeport est le fichier le plus sensible que la plupart des applications recevront jamais. Elle porte un visage, un nom complet, une date de naissance et un numéro de document, et elle suffit à ouvrir un compte ailleurs. Pourtant, dans bien des flux d'envoi, l'image est copiée cinq ou six fois avant que quiconque se demande si elle doit seulement exister.

Cet article aborde la question du côté de l'ingénierie. Il cite ce que dit le RGPD sur la conservation des données, passe en revue les endroits où une image de passeport s'accumule sans bruit, et décrit un schéma que nous appelons lire, renvoyer, oublier : l'image est lue, le résultat est renvoyé, et rien de l'image n'est gardé. Il se termine par la partie qui reste votre travail, car certaines entreprises sont tenues de garder une copie, et à partir de juillet 2027 l'UE l'écrit noir sur blanc dans une nouvelle loi.

Ceci est le blog de doc.cheap, une API OCR pour passeports et pièces d'identité qui lit les documents d'identité et renvoie le résultat en JSON. Lisez les passages sur le produit en gardant cela à l'esprit.

Ce que le RGPD demande vraiment

Le RGPD ne dit pas « ne stockez jamais une image de passeport ». Il dit quelque chose de plus utile : gardez ce dont vous avez besoin, aussi longtemps que vous en avez besoin, et pas plus. L'art. 5(1) du règlement (UE) 2016/679 pose les principes. Deux d'entre eux décident de l'essentiel de la conception.

Principe Texte de l'art. 5(1) (version anglaise) Ce que cela signifie pour une image
Minimisation des données, point c) "adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed" Si votre processus a besoin du nom, de la date de naissance et du numéro de document, l'image elle-même n'est peut-être plus nécessaire une fois ces données lues.
Limitation de la conservation, point e) "kept in a form which permits identification of data subjects for no longer than is necessary for the purposes for which the personal data are processed" Chaque copie a besoin d'une date de fin, et « nous n'avons jamais pris le temps de la supprimer » n'en est pas une.

L'art. 5(2) ajoute la responsabilité : vous devez être en mesure de démontrer que vous respectez ces principes. Et l'art. 25(1), la protection des données dès la conception, demande "appropriate technical and organisational measures, such as pseudonymisation, which are designed to implement data-protection principles, such as data minimisation, in an effective manner", c'est-à-dire des mesures techniques et organisationnelles adaptées, comme la pseudonymisation, pensées pour appliquer efficacement des principes tels que la minimisation des données.

Lus ensemble, ces textes transforment une question juridique en question d'ingénierie. Moins il existe de copies d'une image, moins il y a d'endroits à décrire, sécuriser, sauvegarder et finalement vider. Une copie qui n'a jamais été écrite est la seule qui n'exige aucun de ces efforts.

Où finissent les images de passeport

La plupart des équipes stockent l'image volontairement à un seul endroit. Le problème, ce sont les endroits que personne n'a choisis. Voici une liste à confronter à votre propre flux.

Endroit Comment l'image y arrive
Bucket d'envoi Le client envoie d'abord le fichier vers un stockage objet, et le backend le lit depuis là. L'objet survit à la requête.
Journaux de requêtes Un middleware de journalisation écrit les corps de requête, et une image en base64 est un corps de requête.
Rapports d'erreurs Un outil de suivi des exceptions joint la charge utile de la requête qui a échoué.
Files d'attente et nouvelles tentatives Un message de tâche transporte l'image, et une file de lettres mortes garde les échecs pendant des semaines.
Sauvegardes et instantanés Un instantané de base de données ou de disque pris ce jour-là contient toutes les images écrites avant lui, bien après la suppression de la ligne.
Tickets de support Un utilisateur renvoie la photo par e-mail « parce que l'envoi n'a pas marché ».
Analytique et replay de session Un outil enregistre la page, y compris l'aperçu du fichier sélectionné.
Le fournisseur d'OCR Le service qui lit le document garde sa propre copie, selon ses propres règles de conservation.

La dernière ligne est celle que vous contrôlez le moins. Vos propres journaux, vous pouvez les corriger. Une copie détenue par un fournisseur dépend des réglages de ce fournisseur, et il faut lui demander lesquels.

Le schéma : lire, renvoyer, oublier

Le schéma se formule simplement. L'image n'existe qu'en mémoire, le temps d'une requête. Ce qui sort de la requête, c'est la lecture : les valeurs extraites. L'image, elle, ne sort pas du tout.

  1. Envoyez l'image directement à la reconnaissance. Pas de bucket d'envoi entre les deux. Si un bucket est inévitable pour les gros fichiers, donnez à l'objet une durée de vie de quelques minutes et supprimez-le quand l'appel revient.
  2. Utilisez tout de suite ce dont vous avez besoin dans la réponse. Les recadrages, comme la photo du titulaire, n'existent que dans cette réponse. Si votre flux compare un selfie au portrait, faites-le maintenant.
  3. Gardez la lecture, pas l'image. Stockez les champs dont votre processus a besoin, selon votre propre règle de conservation. Une date de naissance et un numéro de document restent des données personnelles : ils ont donc eux aussi besoin d'une date de fin.
  4. Tenez l'image à l'écart des journaux et des rapports d'erreurs. Retirez les corps de requête à la frontière, en un seul endroit, plutôt que de compter sur chaque appelant pour y penser.
  5. Consignez le résultat. Pour chaque endroit du tableau ci-dessus, notez si l'image peut l'atteindre et pourquoi elle ne le peut pas. Cette note est la responsabilité que demande l'art. 5(2).

Ce que fait notre API avec l'image

Voici comment doc.cheap traite la même question, telle que la décrit sa page conservation des données et confidentialité.

  • L'image n'est jamais stockée. Elle vit en mémoire pendant la requête, est transmise au moteur de reconnaissance et disparaît une fois la réponse écrite. Aucun disque, aucun stockage objet, aucun journal ne la reçoit.
  • Les recadrages ne sont pas stockés non plus. Le recadrage du document, la photo du titulaire et la signature reviennent dans la réponse de l'appel qui les a produits. Un scan relu plus tard via GET /v1/scans/{id} a tous ses emplacements d'image à null.
  • Ce qui peut être gardé, c'est la lecture, et seulement pendant la durée que vous demandez. L'option retain_hours la fixe par requête, de 0 à 8760 heures (un an). Une valeur explicite l'emporte toujours sur le réglage du compte.
  • retain_hours: 0 n'écrit rien. Pas une ligne qui expire aussitôt : aucune ligne du tout. Il n'y a rien à purger, rien dans une sauvegarde et rien à exporter. Le scan compte quand même comme un scan.
  • Le réglage par défaut du compte couvre le reste. Quand une requête ne précise aucune durée, le réglage d'historique du compte s'applique : 24 heures, 7 jours, 1 mois ou 1 an. Les nouveaux comptes démarrent sur 1 an, pour que le tableau de bord affiche un historique. Raccourcir ce réglage s'applique aux lignes déjà stockées, chacune mesurée depuis sa propre date de création.
  • Une ligne conservée garde une petite image : une miniature d'au plus 96 px sur son plus grand côté et d'au plus 16 KiB, affichée dans le journal des opérations du tableau de bord pour qu'on puisse reconnaître une ligne. Elle n'est pas lisible via l'API. La miniature part avec la ligne.
  • Un scan peut être supprimé plus tôt. Une clé live envoie DELETE /v1/scans/{id}, ce qui supprime le résultat, la ligne d'historique et la miniature. C'est définitif.

Le guide contrôler la conservation de l'historique présente les réglages pas à pas, et notre page sur la façon dont nous traitons les données en donne le résumé.

Voici un appel sans conservation en Python avec requests. La clé sandbox publique sk_sandbox_public est imprimée dans la documentation et ne demande aucune inscription : elle donne 10 documents reconnus gratuits par adresse au total, et au plus 10 requêtes par heure. La conservation zéro est un réglage de votre propre compte, elle demande donc votre clé live. Le sandbox public n'est pas un compte : il garde une trace de chaque scan, avec sa petite image, dans le journal propre du service ; envoyez-lui donc une image de test, jamais un vrai document.

import base64
import uuid

import requests

API = "https://api.doc.cheap/v1/scans"
KEY = "sk_sandbox_public"  # votre propre clé live en production


def read_and_forget(path):
    with open(path, "rb") as f:
        image = base64.b64encode(f.read()).decode("ascii")
    response = requests.post(
        API,
        headers={
            "Authorization": f"Bearer {KEY}",
            "Idempotency-Key": str(uuid.uuid4()),
        },
        json={
            "image": image,
            # 0 : avec une clé live, rien de ce scan n'est consigné côté API.
            # False : pas de recadrage du portrait, ce flux n'en utilise pas.
            "options": {"retain_hours": 0, "return_portrait": False},
        },
        timeout=30,
    )
    response.raise_for_status()
    scan = response.json()
    del image  # la copie locale disparaît dès le retour de l'appel
    if scan["meta"]["status"] != "recognized":
        return None
    # Gardez la lecture dont votre processus a besoin, selon votre propre règle de conservation.
    return {
        "scan_id": scan["meta"]["id"],
        "document_number": scan["document"]["number"],
        "expiry_date": scan["document"]["expiry_date"],
        "birth_date": scan["holder"]["birth_date"],
        "mrz_status": scan["mrz"]["status"],
    }

La conservation nulle a un coût qu'il vaut mieux connaître avant qu'il ne vous surprenne. Une Idempotency-Key permet normalement à une nouvelle tentative de renvoyer le premier résultat. Avec retain_hours: 0, il n'y a aucun résultat stocké à renvoyer : pendant 24 heures, une nouvelle tentative sous la même clé est donc refusée avec un HTTP 409 et le code idempotency_replay_unavailable, au lieu de recevoir une seconde réponse. Traitez cette réponse comme « le premier appel est passé » et utilisez le résultat que vous avez déjà.

Relire le scan montre l'autre face de la conception. Une clé sandbox ne relit rien du tout, quel que soit l'identifiant. Nous avons envoyé cette requête avec sk_sandbox_public le 5 octobre 2026 :

curl https://api.doc.cheap/v1/scans/<SCAN_ID> \
  -H "Authorization: Bearer sk_sandbox_public"

Elle est revenue avec un HTTP 404 (le message est raccourci) :

{
  "error": {
    "code": "not_found",
    "message": "No scan with id …",
    "docs_url": "https://doc.cheap/docs/errors/not_found"
  }
}

Une clé live reçoit le même 404 pour un scan fait avec retain_hours: 0, et pour tout scan dont la durée de conservation est écoulée. Si vous comparez des services sur ce point, la comparaison des API OCR de passeport est un bon point de départ ; demandez à chacun où va l'image, et pas seulement ce qu'il renvoie.

Ce qui reste votre travail

Lire, renvoyer, oublier supprime les copies côté API. Ce schéma ne décide pas de ce que votre entreprise doit garder. Pour certaines entreprises, la réponse est « une copie », et la loi le dit.

La nouvelle loi de l'UE contre le blanchiment de capitaux, le règlement (UE) 2024/1624, s'applique à partir du 10 juillet 2027. Son art. 90 dispose : "It shall apply from 10 July 2027, except in relation to obliged entities referred to in Article 3, points (3)(n) and (o), to which it shall apply from 10 July 2029." Autrement dit, il s'applique à partir du 10 juillet 2027, sauf pour les entités assujetties de l'art. 3, points (3)(n) et (o), pour lesquelles il s'applique à partir du 10 juillet 2029. Son art. 77, sur la conservation des documents, oblige les entités assujetties, comme les banques et les autres établissements financiers, à conserver :

"a copy of the documents and information obtained in the performance of customer due diligence pursuant to Chapter III, including information obtained through electronic identification means;"

En d'autres termes, une copie des documents et des informations obtenus lors de la vigilance à l'égard de la clientèle, y compris ceux obtenus par des moyens d'identification électronique.

L'art. 77(3) fixe la durée : les documents sont "retained for a period of 5 years commencing on the date of the termination of the business relationship", c'est-à-dire conservés cinq ans à compter de la fin de la relation d'affaires, puis "obliged entities shall delete personal data upon expiry of the five-year period", autrement dit, au bout de ces cinq ans, les données personnelles doivent être effacées. L'art. 77(2) permet, sous conditions, "a retention of the references to such information" à la place des copies, c'est-à-dire de ne garder que les références à ces informations.

Donc, si vous êtes une entité assujettie, la conservation nulle côté API ne supprime pas votre obligation de garder une trace. Elle change l'endroit où cette trace vit. Votre propre stockage devient l'unique copie, et le principe de limitation de la conservation vu plus haut s'y applique toujours : cinq ans après la fin de la relation, elle disparaît. Le travail de conception consiste à rendre ce stockage délibéré, avec un seul endroit, un seul responsable, du chiffrement, un contrôle d'accès et une tâche de suppression, plutôt que le tas accidentel du tableau ci-dessus.

Si vous n'êtes pas une entité assujettie, posez d'abord la question simple : quelque chose dans votre processus a-t-il besoin de l'image une fois les champs lus ? Souvent, la réponse honnête est non.

Une liste de contrôle

  • Chaque endroit du tableau « où finissent les images » est vérifié par rapport à votre flux.
  • L'image va directement à la reconnaissance, ou passe par un bucket dont la durée de vie se compte en minutes.
  • Les recadrages sont utilisés dans le gestionnaire de réponse et ne sont écrits nulle part.
  • L'appel OCR fixe sa conservation de façon délibérée, retain_hours: 0 quand rien n'a besoin d'être relu.
  • Les nouvelles tentatives gèrent la réponse 409 idempotency_replay_unavailable.
  • Les journaux et les rapports d'erreurs retirent les corps de requête à une seule frontière.
  • Les champs que vous gardez ont une date de fin, et quelque chose les supprime.
  • Si une loi exige une copie, elle vit dans un seul stockage délibéré avec sa propre date de suppression.

Ceci est un résumé d'ingénierie, pas un avis juridique. Si vous trouvez un endroit où une image peut fuir et que cet article oublie, écrivez à admin@doc.cheap.

Une question pour vous : où avez-vous trouvé pour la dernière fois une copie d'un document d'identité que personne n'avait l'intention de garder ? Dites-le-nous dans les commentaires ci-dessous.