{"openapi":"3.1.0","info":{"title":"Tano","version":"0.1.0"},"paths":{"/v1/journey-embedding":{"get":{"tags":["comptes"],"summary":"Get Journey Embedding","description":"Les origines autorisées à encadrer le parcours (`/embed`). Vide : aucune.","operationId":"get_journey_embedding_v1_journey_embedding_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Journey Embedding V1 Journey Embedding Get"}}}}}},"post":{"tags":["comptes"],"summary":"Put Journey Embedding","description":"Remplacer la liste des origines autorisées à encadrer le parcours. Journalisé.","operationId":"put_journey_embedding_v1_journey_embedding_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingSettings"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Put Journey Embedding V1 Journey Embedding Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/api-keys":{"post":{"tags":["comptes"],"summary":"Create Api Key","description":"Créer une clé. Le secret est rendu une seule fois.","operationId":"create_api_key_v1_api_keys_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewApiKey"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["comptes"],"summary":"Get Api Keys","description":"Lister les clés, par curseur. Aucun secret n'y figure.","operationId":"get_api_keys_v1_api_keys_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"starting_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starting After"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Api Keys V1 Api Keys Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/api-keys/{key_id}":{"delete":{"tags":["comptes"],"summary":"Delete Api Key","description":"Révoquer une clé. L'effet est immédiat sur toutes les instances.","operationId":"delete_api_key_v1_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"tags":["comptes"],"summary":"Get Usage","description":"La consommation d'un mois, par service, face au quota souscrit (M8 §10).\n\n`services` garde sa forme d'origine — un total par service — pour les intégrations qui la\nlisent ; `detail` y ajoute le quota, le comportement en dépassement et l'offre.","operationId":"get_usage_v1_usage_get","parameters":[{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},{"type":"null"}],"title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Usage V1 Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contract":{"get":{"tags":["comptes"],"summary":"Get Contract","description":"Le contrat du client : qui il est pour Tano, et ce qu'il a souscrit (M8 §10).\n\nLecture seule. Chaque souscription porte son état au jour de la lecture : en vigueur, à venir\nou terminée — une souscription terminée reste listée, c'est elle qui explique une facture\npassée.","operationId":"get_contract_v1_contract_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Contract V1 Contract Get"}}}}}}},"/v1/usage/export":{"get":{"tags":["comptes"],"summary":"Export Usage","description":"Chaque unité mesurée du mois, en CSV : l'export rapprochable de M8 §10.\n\nUne ligne par mesure, avec le dossier auquel elle se rapporte — l'identifiant que le client a\nreçu en l'ouvrant. Aucune donnée personnelle : des codes, des quantités, des instants.","operationId":"export_usage_v1_usage_export_get","parameters":[{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},{"type":"null"}],"title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints":{"get":{"tags":["comptes"],"summary":"Get Endpoints","operationId":"get_endpoints_v1_webhook_endpoints_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Endpoints V1 Webhook Endpoints Get"}}}}}},"post":{"tags":["comptes"],"summary":"Create Endpoint","description":"Déclarer une destination. Le secret de signature est rendu une seule fois.","operationId":"create_endpoint_v1_webhook_endpoints_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewEndpoint"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/deliveries":{"get":{"tags":["comptes"],"summary":"Get Deliveries","description":"L'état de livraison des dernières 24 heures, pour l'écran de notifications (M8 §10).\n\nLu pour cette destination seulement : les cinquante dernières livraisons du client, filtrées\nensuite, perdaient celles d'une destination calme derrière une destination bavarde.","operationId":"get_deliveries_v1_webhook_endpoints__endpoint_id__deliveries_get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Deliveries V1 Webhook Endpoints  Endpoint Id  Deliveries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/replay":{"post":{"tags":["comptes"],"summary":"Replay Delivery","description":"Rejouer une livraison échouée, à la demande du client.","operationId":"replay_delivery_v1_webhook_endpoints__endpoint_id__replay_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}},{"name":"delivery_id","in":"query","required":true,"schema":{"type":"string","title":"Delivery Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Replay Delivery V1 Webhook Endpoints  Endpoint Id  Replay Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/resume":{"post":{"tags":["comptes"],"summary":"Resume","description":"Réactiver une destination suspendue, après correction côté client.","operationId":"resume_v1_webhook_endpoints__endpoint_id__resume_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resume V1 Webhook Endpoints  Endpoint Id  Resume Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-deliveries":{"get":{"tags":["comptes"],"summary":"Get Webhook Log","description":"Le journal des webhooks : chaque livraison, toutes destinations, filtrable.","operationId":"get_webhook_log_v1_webhook_deliveries_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Event Type"}},{"name":"endpoint_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Endpoint Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":7,"title":"Days"}},{"name":"starting_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Starting After"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Webhook Log V1 Webhook Deliveries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-deliveries/{delivery_id}":{"get":{"tags":["comptes"],"summary":"Get Webhook Delivery","description":"Une livraison et le corps envoyé, tel que la destination l'a reçu.","operationId":"get_webhook_delivery_v1_webhook_deliveries__delivery_id__get","parameters":[{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","title":"Delivery Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Webhook Delivery V1 Webhook Deliveries  Delivery Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-deliveries/{delivery_id}/replay":{"post":{"tags":["comptes"],"summary":"Replay Webhook Delivery","description":"Rejouer une livraison depuis le journal.","operationId":"replay_webhook_delivery_v1_webhook_deliveries__delivery_id__replay_post","parameters":[{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","title":"Delivery Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Replay Webhook Delivery V1 Webhook Deliveries  Delivery Id  Replay Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/test":{"post":{"tags":["comptes"],"summary":"Test Webhook Endpoint","description":"Envoyer un essai signé à une destination. Il paraît au journal sous `webhook.test`.","operationId":"test_webhook_endpoint_v1_webhook_endpoints__endpoint_id__test_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Test Webhook Endpoint V1 Webhook Endpoints  Endpoint Id  Test Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-events":{"get":{"tags":["comptes"],"summary":"Get Webhook Events","description":"Les événements auxquels s'abonner : quand ils partent, et un exemple du corps reçu.","operationId":"get_webhook_events_v1_webhook_events_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Webhook Events V1 Webhook Events Get"}}}}}}},"/v1/api-usage":{"get":{"tags":["comptes"],"summary":"Get Api Usage","description":"Les appels de l'intégration, par jour et par code de réponse — ceux de la console exclus.","operationId":"get_api_usage_v1_api_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Api Usage V1 Api Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators/resolve":{"post":{"tags":["comptes"],"summary":"Resolve Operator","description":"Dire quel opérateur est ce sujet, et ce qu'il a le droit de voir. `adr/0009`.\n\n**Cet endpoint n'authentifie personne.** La console a vérifié un jeton d'identité signé par\nle fournisseur ; elle présente ici le sujet qu'il portait, sous la clé d'API du client. Le\nservice ne vérifie pas de mot de passe et n'émet aucun jeton — « il ne porte pas\nl'authentification des opérateurs elle-même, déléguée au fournisseur d'identité, mais il\nporte les habilitations » (M8 §1).\n\nC'est aussi pourquoi il exige la clé d'API : seul un serveur en détient une, et c'est ce qui\nempêche un navigateur de se déclarer opérateur en présentant un sujet de son choix.\n\nÀ la première connexion, l'invitation est consommée ici. L'ordre compte : on rattache puis on\nrésout, de sorte qu'un rattachement réussi et une résolution en échec soient impossibles.","operationId":"resolve_operator_v1_operators_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubjectPresented"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Resolve Operator V1 Operators Resolve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators/directory":{"get":{"tags":["comptes"],"summary":"Get Operator Directory","description":"Les noms des opérateurs du client, pour les afficher à leurs collègues.\n\nOuvert à tout opérateur actif : « Moussa Traoré tient ce dossier » se lit mieux qu'un\nidentifiant. Ni adresse, ni habilitation — seulement qui est qui.","operationId":"get_operator_directory_v1_operators_directory_get","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Operator Directory V1 Operators Directory Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators":{"get":{"tags":["comptes"],"summary":"Get Operators","description":"Les opérateurs du client, leur habilitation et leur dernière connexion. Administrateur.","operationId":"get_operators_v1_operators_get","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Operators V1 Operators Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["comptes"],"summary":"Invite","description":"Inviter un opérateur. Le jeton d'invitation est rendu **une seule fois**.\n\nLe service n'envoie pas de courriel : la console montre le lien à transmettre. Changer une\nhabilitation est une action privilégiée (M8 §9) — ré-authentification exigée.","operationId":"invite_v1_operators_post","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewOperator"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Invite V1 Operators Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators/{target_id}":{"patch":{"tags":["comptes"],"summary":"Change Clearance","description":"Changer le rôle, les pays ou la sensibilité d'un opérateur. Effet immédiat (M8 R8).","operationId":"change_clearance_v1_operators__target_id__patch","parameters":[{"name":"target_id","in":"path","required":true,"schema":{"type":"string","title":"Target Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorClearance"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Change Clearance V1 Operators  Target Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators/{target_id}/revoke":{"post":{"tags":["comptes"],"summary":"Revoke","description":"Retirer un accès. Effet immédiat : l'habilitation est relue à chaque appel (M8 R8).\n\nSans rejeu idempotent : une seconde révocation trouve l'opérateur déjà révoqué, et le dit.","operationId":"revoke_v1_operators__target_id__revoke_post","parameters":[{"name":"target_id","in":"path","required":true,"schema":{"type":"string","title":"Target Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews":{"get":{"tags":["revue"],"summary":"Get Queue","description":"La file de l'opérateur, triée par risque puis échéance.\n\nLe tri n'est pas paramétrable (R8) : il n'existe aucun paramètre de requête pour le\nchanger, et c'est la forme la plus claire de cette règle.","operationId":"get_queue_v1_reviews_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/TaskStatus"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cursor"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Queue V1 Reviews Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/metrics":{"get":{"tags":["revue"],"summary":"Get Review Metrics","description":"Les indicateurs et les alertes de la revue (M6 §11). Superviseur ou administrateur.\n\nPar défaut, les trente derniers jours. Déclaré avant `/reviews/{task_id}`.","operationId":"get_review_metrics_v1_reviews_metrics_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Review Metrics V1 Reviews Metrics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/summary":{"get":{"tags":["revue"],"summary":"Get Queue Summary","description":"Les compteurs de la file de l'opérateur : toute la file, et non la page chargée.\n\nDéclaré avant `/reviews/{task_id}`, qui prendrait sinon « summary » pour un identifiant.","operationId":"get_queue_summary_v1_reviews_summary_get","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Queue Summary V1 Reviews Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/support-access":{"get":{"tags":["revue"],"summary":"My Support Access","description":"Les accès en cours du compte de support agissant : les seuls dossiers qu'il peut lire.","operationId":"my_support_access_v1_reviews_support_access_get","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response My Support Access V1 Reviews Support Access Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/support-access":{"get":{"tags":["revue"],"summary":"List Support Access","description":"Les accès de support du client, du plus récent au plus ancien. Administrateur ou\nsuperviseur : ce sont eux qui les ouvrent, eux qui doivent pouvoir les relire.","operationId":"list_support_access_v1_support_access_get","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Support Access V1 Support Access Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["revue"],"summary":"Grant Support Access","description":"Ouvrir à un compte de support un dossier, pour quatre heures, avec motif (`adr/0012`).\n\nLe dossier doit être en revue : c'est la seule chose que la console sait montrer.","operationId":"grant_support_access_v1_support_access_post","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportAccessRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Grant Support Access V1 Support Access Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/support-access/{grant_id}/revoke":{"post":{"tags":["revue"],"summary":"Close Support Access","description":"Fermer un accès avant son terme. Pas de ré-authentification : fermer ne fait que retirer.","operationId":"close_support_access_v1_support_access__grant_id__revoke_post","parameters":[{"name":"grant_id","in":"path","required":true,"schema":{"type":"string","title":"Grant Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Close Support Access V1 Support Access  Grant Id  Revoke Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}":{"get":{"tags":["revue"],"summary":"Get Task","description":"Un dossier de la file, avec ce que cet opérateur a le droit d'en voir.\n\nLe critère 3 de M6 se joue ici : en double validation, tant que cet opérateur n'a pas rendu\nsa sortie, `decisions` est vide **dans la réponse du serveur**, et pas seulement caché à\nl'écran.","operationId":"get_task_v1_reviews__task_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Task V1 Reviews  Task Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/claim":{"post":{"tags":["revue"],"summary":"Claim","description":"Poser le verrou nominatif et ouvrir le dossier.","operationId":"claim_v1_reviews__task_id__claim_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Claim V1 Reviews  Task Id  Claim Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/lock":{"post":{"tags":["revue"],"summary":"Keep Lock","description":"Prolonger son verrou pendant l'examen — « trente minutes d'inactivité », pas d'examen.\n\nRend la nouvelle échéance. Un verrou déjà perdu ne se ranime pas : `409 lock_expired`, et la\nconsole propose de reprendre le dossier par une nouvelle prise en charge.","operationId":"keep_lock_v1_reviews__task_id__lock_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Keep Lock V1 Reviews  Task Id  Lock Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/case":{"get":{"tags":["revue"],"summary":"Get Workstation","description":"Tout ce que l'écran de dossier affiche, en un appel. M6 §10.\n\n**Un seul endpoint, et non cinq.** Ouvrir un dossier est **une** consultation du point de vue\ndu journal ; la découper produirait cinq entrées pour un seul geste, et le client qui relit\nson journal y verrait une activité qui n'a pas eu lieu.\n\nLa composition traverse trois schémas et passe par les **points d'entrée publics** des\nmodules, jamais par la table d'un autre. Ce n'est pas une politesse : chaque module a son\nrôle PostgreSQL, et un contexte est ouvert par module — la frontière est tenue par les\ndroits autant que par les imports.\n\n**Le sujet ressort masqué.** Rien n'est déchiffré ici : la réponse porte les chemins des\nchamps confrontés, pas leurs valeurs. Le masquage par défaut de M6 §9 est ainsi une\npropriété de ce que le serveur envoie, et pas un `display: none` dans un navigateur.","operationId":"get_workstation_v1_reviews__task_id__case_get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Workstation V1 Reviews  Task Id  Case Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/pieces/{piece_id}":{"get":{"tags":["revue"],"summary":"Get Piece","description":"La photo elle-même, descellée et servie par le service. M6 §10, colonne du centre.\n\n**Aucune URL signée**, et c'est le point de la conception. Une URL signée sort la lecture du\nchemin authentifié : elle échappe à la vérification d'habilitation, qui est relue en base à\nchaque appel, et elle échappe au journal des consultations — alors que M6 §9 exige qu'un\nexport porte l'identité de l'opérateur. Le coût est un octet qui traverse le service ; le\nbénéfice est que personne ne regarde une pièce sans que le client puisse le savoir.\n\nLe portrait relève du régime biométrique : il est descellé sous une clé distincte de celle\ndes données (M1 R8), et c'est la ligne qui choisit la finalité qui le garantit, pas une\nconsigne. Sa consultation est journalisée comme `downloaded` : l'octet est sorti du service,\net le dire autrement serait complaisant.","operationId":"get_piece_v1_reviews__task_id__pieces__piece_id__get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"piece_id","in":"path","required":true,"schema":{"type":"string","title":"Piece Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/unmask":{"post":{"tags":["revue"],"summary":"Reveal","description":"Révéler les données personnelles du dossier, et l'inscrire au journal.\n\nAu-delà de vingt dossiers démasqués dans l'heure, la preuve d'une ré-authentification récente\nest exigée (`X-Tano-Reauthenticated-At`, M6 §9) : sans elle, `403 reauth_required`.\n\n« Cette consultation sera enregistrée et visible par le client. » M6 §10.\n\n**L'endpoint rend maintenant ce qu'il révèle.** Il se contentait de journaliser et de rendre\nl'identifiant de la consultation : la révélation ne révélait rien, et la console n'avait rien\nà afficher après le geste de l'opérateur. C'était un endpoint inachevé, pas une prudence.\n\nL'ordre des opérations est la garantie : **le journal d'abord, la lecture ensuite**, et les\ndeux dans la même transaction. Une lecture qui échouerait après avoir été journalisée laisse\nun journal trop bavard, ce qu'un client peut vérifier et qui ne coûte rien à personne ;\nl'inverse laisse une donnée lue sans trace, ce qui vide la règle de son sens.\n\nL'écart entre déclaré et lu est calculé **ici**, par la confrontation de M1, et non laissé à\nla console : `KOUAME` et `KOUAMÉ` sont le même nom, et une comparaison naïve dans un\nnavigateur signalerait un écart là où la normalisation du domaine n'en voit pas.","operationId":"reveal_v1_reviews__task_id__unmask_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"field_path","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field Path"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reveal V1 Reviews  Task Id  Unmask Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/corrections":{"post":{"tags":["revue"],"summary":"Correct Field","description":"Saisir un champ à partir de l'image : une correction, donc une annotation (M6 §3, R9).\n\nSous le verrou de l'opérateur, comme la décision : corriger un dossier qu'un collègue tient\nserait écrire dans son examen. La valeur d'avant est lue **ici** — la dernière saisie, sinon la\nlecture du titre — et non reçue de la console, qui pourrait la présenter autrement.","operationId":"correct_field_v1_reviews__task_id__corrections_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldCorrection"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Correct Field V1 Reviews  Task Id  Corrections Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/decision":{"post":{"tags":["revue"],"summary":"Decide","description":"Enregistrer une sortie d'opérateur, puis relancer le parcours s'il y a lieu.\n\nL'ordre est celui de M6 R10 et il n'est pas négociable : la sortie est enregistrée par M6,\nla conclusion est tirée par M7. Si la transmission échoue, la sortie reste enregistrée et\nl'appel échoue — un opérateur informé que sa décision n'est pas passée peut réessayer, ce\nqui est le seul comportement honnête. L'idempotence de l'endpoint garantit que le second\nessai ne crée pas une seconde décision.","operationId":"decide_v1_reviews__task_id__decision_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorDecision"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecisionRecorded"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/revision":{"post":{"tags":["revue"],"summary":"Revise","description":"Réviser la décision d'un dossier décidé. Superviseur seul, sur ré-authentification récente.\n\nMême ordre que la décision : vérifier que le dossier se révise **avant** d'écrire, écrire la\nsortie révisée (M6), puis la décision de dossier révisée (M7, R10). Deux transactions, comme\npour la décision : si la seconde échoue, la révision de M6 reste et l'appel échoue — la\nreprise ne peut pas la réécrire (`revision_changes_nothing`), et se fait par l'exploitation.","operationId":"revise_v1_reviews__task_id__revision_post","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Revision"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevisionRecorded"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/access-log":{"get":{"tags":["revue"],"summary":"Get Access Log","description":"Qui a consulté ce dossier, restituable au client.\n\nAucun en-tête d'opérateur n'est exigé : c'est le **client** qui exerce ici un droit de\nregard sur ses propres dossiers, y compris sur les consultations faites par le personnel\nde Tano.","operationId":"get_access_log_v1_cases__case_id__access_log_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Access Log V1 Cases  Case Id  Access Log Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/record":{"get":{"tags":["revue"],"summary":"Case Record","description":"La fiche d'un dossier : état, décisions, revues, pièces, identité lue (masquée).\n\nUn dossier décidé reste consultable, parce qu'une banque doit pouvoir expliquer une décision\ndes mois plus tard. La consultation est inscrite au journal des consultations. Les contrôles\neux-mêmes (bande, visage, vivacité) se lisent au journal du dossier, où chaque étape laisse\nson compte rendu : la fiche ne les recopie pas.","operationId":"case_record_v1_cases__case_id__record_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Record V1 Cases  Case Id  Record Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/pieces/{piece_id}":{"get":{"tags":["revue"],"summary":"Case Piece","description":"Une pièce du dossier, servie par le service, jamais en cache — comme au poste de revue.\n\nConsignée comme `downloaded` : l'octet sort du service, et le portrait relève du régime\nbiométrique.","operationId":"case_piece_v1_cases__case_id__pieces__piece_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"piece_id","in":"path","required":true,"schema":{"type":"string","title":"Piece Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/unmask":{"post":{"tags":["revue"],"summary":"Case Unmask","description":"Révéler l'identité lue sur la pièce, et l'inscrire au journal des consultations.\n\nMême compteur que le poste de revue : au-delà de vingt dossiers démasqués dans l'heure, d'où\nqu'on démasque, la preuve d'une ré-authentification récente est exigée.","operationId":"case_unmask_v1_cases__case_id__unmask_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Unmask V1 Cases  Case Id  Unmask Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/questionnaires/unmask":{"post":{"tags":["revue"],"summary":"Case Questionnaires Unmask","description":"Révéler les réponses aux questionnaires du dossier, et l'inscrire au journal.\n\nLes points, le seuil et les drapeaux sont déjà au compte rendu de l'étape, sans rien révéler.\nLes réponses elles-mêmes sont des données personnelles : même geste, même journal et même\ncompteur que l'identité lue.","operationId":"case_questionnaires_unmask_v1_cases__case_id__questionnaires_unmask_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Questionnaires Unmask V1 Cases  Case Id  Questionnaires Unmask Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/applicant-data/unmask":{"post":{"tags":["revue"],"summary":"Case Applicant Unmask","description":"Révéler ce que la personne a saisi sur elle-même, à côté de ce que le client avait déclaré,\net l'inscrire au journal. Même geste, même compteur que l'identité lue.\n\nL'écart à la pièce, lui, est déjà au compte rendu du contrôle (`subject_mismatch`) : il se lit\nsans rien révéler.","operationId":"case_applicant_unmask_v1_cases__case_id__applicant_data_unmask_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Applicant Unmask V1 Cases  Case Id  Applicant Data Unmask Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/results":{"get":{"tags":["revue"],"summary":"Case Results","description":"Tout ce qui fonde la décision, sans aucune donnée personnelle : l'état en un mot, la\ndécision et son motif, la reprise demandée, le compte rendu de chaque contrôle (statut,\nmotifs, mesures), les doublons (des identifiants), les pièces reçues.","operationId":"case_results_v1_cases__case_id__results_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Results V1 Cases  Case Id  Results Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/data":{"get":{"tags":["revue"],"summary":"Case Data","description":"Les données personnelles du dossier : l'identité lue sur la pièce (et sa concordance avec\nla zone imprimée), ce que le client avait déclaré, ce que la personne a saisi, ses réponses\naux questionnaires. Permission `personal_data` ; lecture inscrite au journal du dossier.","operationId":"case_data_v1_cases__case_id__data_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Data V1 Cases  Case Id  Data Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/images/{piece_id}":{"get":{"tags":["revue"],"summary":"Case Image","description":"Une image du dossier (pièce, selfie, image du défi de vivacité). Permission\n`personal_data` ; téléchargement inscrit au journal du dossier. Jamais mise en cache.","operationId":"case_image_v1_cases__case_id__images__piece_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"piece_id","in":"path","required":true,"schema":{"type":"string","title":"Piece Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/decision":{"post":{"tags":["revue"],"summary":"Case Decision","description":"Trancher un dossier en revue depuis l'intégration : approuver, refuser, demander une reprise.\n\nPermission de clé `decisions`. Seulement quand le dossier attend une décision humaine — en\nrevue ; ailleurs, `case_not_in_review` dit où il en est. Le chemin est celui de la console :\nla sortie sur la tâche de revue (M6), puis la conclusion par le parcours (M7), qui publie\n`case.decided` ou `case.resubmission_requested`. La double validation ne s'applique pas : la\nclé tranche seule, et la preuve le dit.","operationId":"case_decision_v1_cases__case_id__decision_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationDecision"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Decision V1 Cases  Case Id  Decision Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/erasure":{"post":{"tags":["revue"],"summary":"Case Erasure","description":"Effacer les données personnelles d'un dossier clos, à la demande du client.\n\nPermission `personal_data`. Chaque module efface ce qu'il garde, sous son propre rôle, comme\nla purge programmée : images, identité lue, portraits et gabarits, déclaré, saisi, réponses,\nchamps lus sur la pièce et ses empreintes, commentaires et corrections de revue. Reste la\ntrace : le dossier, ses étapes, ses verdicts, ses décisions et le journal — la preuve qu'une\nvérification a eu lieu et comment, sans plus dire de qui.\n\nUn dossier en cours a encore sa finalité : `case_open` (409). Rejouer l'appel est sans\ndanger ; il rend des zéros. Le client reçoit `case.personal_data_erased`.","operationId":"case_erasure_v1_cases__case_id__erasure_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Erasure V1 Cases  Case Id  Erasure Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/journey-link":{"post":{"tags":["revue"],"summary":"Case Journey Link","description":"Un nouveau lien de parcours, à remettre à la personne : une reprise, un lien perdu.\n\nL'API le fait déjà (`POST /v1/sessions`) pour un client intégré ; la console le fait pour\nl'organisation qui n'a pas d'équipe technique, et pour la démonstration. Mêmes garde-fous : un\nopérateur habilité sur ce dossier, un dossier qui attend des photos — créé ou en collecte, pas\nen traitement, en revue ou clos. Le lien est rendu une seule fois ; son émission est journalisée\ncomme toute session.","operationId":"case_journey_link_v1_cases__case_id__journey_link_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Case Journey Link V1 Cases  Case Id  Journey Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/reviews/{task_id}/pieces/{piece_id}/portrait":{"get":{"tags":["revue"],"summary":"Get Piece Portrait","description":"Le portrait d'une pièce du poste de revue, isolé. Mêmes garanties que la pièce entière.","operationId":"get_piece_portrait_v1_reviews__task_id__pieces__piece_id__portrait_get","parameters":[{"name":"task_id","in":"path","required":true,"schema":{"type":"string","title":"Task Id"}},{"name":"piece_id","in":"path","required":true,"schema":{"type":"string","title":"Piece Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/pieces/{piece_id}/portrait":{"get":{"tags":["revue"],"summary":"Case Piece Portrait","description":"Le portrait d'une pièce de la fiche dossier, isolé. Mêmes garanties que la pièce entière.","operationId":"case_piece_portrait_v1_cases__case_id__pieces__piece_id__portrait_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"piece_id","in":"path","required":true,"schema":{"type":"string","title":"Piece Id"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases":{"post":{"tags":["dossiers"],"summary":"Create Case","description":"Ouvrir un dossier. La porte d'entrée du produit.\n\nDeux protections se superposent, et ce n'est pas une redondance. L'en-tête\n`Idempotency-Key` protège du rejeu d'une **requête identique** ; la référence client protège\ndu rejeu d'une **intention identique** exprimée par deux requêtes différentes — ce qui est le\ncas d'un client qui réessaie après un délai d'attente réseau avec une nouvelle clé.","operationId":"create_case_v1_cases_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewCase"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["dossiers"],"summary":"List Cases","description":"Chercher les dossiers du client, du plus récent au plus ancien.\n\n`q` : un identifiant de dossier, ou le début de la référence du client (sans distinction de\ncasse). `external_ref` : votre référence, exacte. `status` et `country` se répètent\n(`?country=CI&country=SN`). Aucune donnée personnelle n'est cherchée ni rendue.","operationId":"list_cases_v1_cases_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Q"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/CaseStatus"}},{"type":"null"}],"title":"Status"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":10},{"type":"null"}],"title":"Country"}},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created After"}},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Before"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cursor"}},{"name":"external_ref","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}],"title":"External Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Cases V1 Cases Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/export":{"get":{"tags":["dossiers"],"summary":"Export Cases","description":"Les dossiers d'une recherche, en CSV : mêmes filtres que la liste, 10 000 lignes au plus.\n\nDes références, des codes et des dates — aucune donnée personnelle, comme la liste.","operationId":"export_cases_v1_cases_export_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Q"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/CaseStatus"}},{"type":"null"}],"title":"Status"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"},"maxItems":10},{"type":"null"}],"title":"Country"}},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created After"}},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandbox/cases/{case_id}/submit":{"post":{"tags":["dossiers"],"summary":"Submit Sandbox","description":"Bac à sable : faire comme si la personne avait terminé son parcours, sans photo.\n\nRéservé à une clé de bac à sable, sur un dossier de bac à sable qui attend son parcours. Le\ntraitement démarre comme après un vrai parcours ; le nom de famille déclaré choisit le résultat\n(`TESTPASS`, `TESTREVIEW`, `TESTFAIL`, `TESTSANCTION`, `TESTSLOW`, `TESTDOWN`).","operationId":"submit_sandbox_v1_sandbox_cases__case_id__submit_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Submit Sandbox V1 Sandbox Cases  Case Id  Submit Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}":{"get":{"tags":["dossiers"],"summary":"Get Case","description":"L'état d'un dossier, ses étapes et sa décision, comme dans la liste. Aucune donnée\npersonnelle : des codes et des nombres.","operationId":"get_case_v1_cases__case_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Case V1 Cases  Case Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions":{"post":{"tags":["dossiers"],"summary":"Create Journey Session","description":"Créer une session de parcours et rendre son jeton, une seule fois.","operationId":"create_journey_session_v1_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewSession"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/captures":{"post":{"tags":["dossiers"],"summary":"Open Journey Capture","description":"Ouvrir une capture et rendre sa clé, une seule fois.\n\nLe parcours chiffre chaque bloc sous cette clé avant qu'il ne quitte l'appareil (M10 R4). Côté\nnavigateur elle ne quitte pas la mémoire — ni pour un stockage local, ni pour un journal : c'est\nce qui rend l'effacement de R7 réel plutôt que cosmétique.","operationId":"open_journey_capture_v1_sessions__session_id__captures_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewCapture"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptureOpened"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/captures/{capture_id}":{"get":{"tags":["dossiers"],"summary":"Capture Progress","description":"Ce qui est arrivé. La reprise se fonde là-dessus, et non sur ce que le parcours croit.","operationId":"capture_progress_v1_sessions__session_id__captures__capture_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"capture_id","in":"path","required":true,"schema":{"type":"string","title":"Capture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptureState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/captures/{capture_id}/chunks":{"post":{"tags":["dossiers"],"summary":"Send Chunk","description":"Recevoir un bloc chiffré. Idempotent : un réessai n'est pas une erreur.\n\n202 et non 201 : le bloc est accepté, la capture n'est pas pour autant complète. Le parcours lit\n`received` pour savoir ce qu'il lui reste à envoyer — c'est la reprise de M10 R5, et elle ne\nsuppose rien de ce qui s'est perdu dans la coupure.","operationId":"send_chunk_v1_sessions__session_id__captures__capture_id__chunks_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"capture_id","in":"path","required":true,"schema":{"type":"string","title":"Capture Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChunkBody"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChunkReceived"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/captures/{capture_id}/complete":{"post":{"tags":["dossiers"],"summary":"Complete Journey Capture","description":"Clore une capture, si et seulement si tous ses blocs sont là.\n\nLe compte annoncé est vérifié : une capture close avec des trous donnerait une image tronquée à\nla vérification, et un verdict rendu sur une image tronquée est pire qu'un envoi qui échoue.","operationId":"complete_journey_capture_v1_sessions__session_id__captures__capture_id__complete_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"capture_id","in":"path","required":true,"schema":{"type":"string","title":"Capture Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptureState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/applicant-data":{"post":{"tags":["dossiers"],"summary":"Submit Applicant Data","description":"Recevoir ce que la personne saisit sur elle-même, le vérifier, le garder chiffré.\n\nUne saisie à corriger n'est pas une erreur du protocole : la réponse dit `accepted: false` et,\nchamp par champ, pourquoi — le formulaire affiche tout d'un coup plutôt qu'une faute à la fois.\nDes codes, jamais les valeurs.","operationId":"submit_applicant_data_v1_sessions__session_id__applicant_data_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicantSubmission"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Submit Applicant Data V1 Sessions  Session Id  Applicant Data Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/questionnaires/{step}":{"post":{"tags":["dossiers"],"summary":"Submit Questionnaire","description":"Recevoir les réponses à un questionnaire du parcours, les vérifier, les garder chiffrées.\n\nComme pour les données du demandeur, une réponse à corriger n'est pas une erreur du protocole :\n`accepted: false` et, question par question, un code. Des codes, jamais les valeurs.","operationId":"submit_questionnaire_v1_sessions__session_id__questionnaires__step__post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"step","in":"path","required":true,"schema":{"type":"string","title":"Step"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuestionnaireSubmission"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Submit Questionnaire V1 Sessions  Session Id  Questionnaires  Step  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/captures/{capture_id}/face":{"post":{"tags":["dossiers"],"summary":"Check Journey Selfie","description":"Le selfie qui vient d'arriver montre-t-il un visage, au centre de l'ovale ?\n\nLe contrôle de la caméra ne mesure que la lumière et la netteté : il disait « c'est bon » sans\nvisage. Le service le vérifie ici, juste après l'envoi, pour que le sujet reprenne sa photo\ntant qu'il est devant l'écran — plutôt qu'un dossier en revue pour un selfie vide.","operationId":"check_journey_selfie_v1_sessions__session_id__captures__capture_id__face_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"capture_id","in":"path","required":true,"schema":{"type":"string","title":"Capture Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Journey Selfie V1 Sessions  Session Id  Captures  Capture Id  Face Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/copy":{"get":{"tags":["dossiers"],"summary":"Generic Copy","description":"Les textes des écrans sans flux. Aucun jeton, aucune donnée personnelle.\n\nSans cet endpoint, un lien expiré n'aurait aucun texte à afficher : le parcours ne rédige rien,\net l'ouverture de session — qui porte les textes du flux — est justement ce qui vient d'échouer.\nLe sujet resterait devant un écran muet.","operationId":"generic_copy_v1_copy_get","parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string","default":"fr","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericCopy"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/open":{"post":{"tags":["dossiers"],"summary":"Open Journey Session","description":"Ouvrir — ou reprendre — le parcours avec le jeton du sujet. Aucune clé d'API n'est présentée.\n\nM10 R1 : « aucun secret d'API dans une application distribuée. Le SDK n'utilise que des\njetons de session à durée courte ». Cet endpoint est donc le seul du contrat public qui\nn'exige pas d'authentification par clé — le jeton **est** l'authentification, et il ne donne\naccès qu'à un dossier, pour une heure au plus.\n\nLe contournement de contexte est ici, visible en deux lignes : la résolution du jeton sous\n`unscoped_session`, puis tout le reste sous `tenant_scope`.\n\n**Cet endpoint n'a pas de plafond applicatif, et c'est un choix documenté.** Nos plafonds\nsont comptés par client, or il n'y a pas encore de client connu au moment de l'appel : c'est\ntout l'objet de la résolution. Le corpus place la protection au bon endroit — « protection\napplicative et gestion des robots en périphérie, plafonnement par adresse IP et par client »\n(`cadre/05` §périmètre réseau). Le plafonnement par adresse relève donc de la périphérie, et\nil est **exigé** pour cet endpoint : sans lui, un attaquant peut essayer des jetons sans\nlimite. La force brute reste infaisable — trente-deux octets d'aléa — mais l'absence de\nplafond est une surface de déni de service.\n\n**Le même appel ouvre et reprend**, et c'est délibéré : le parcours présente son lien, le\nservice sait seul si c'est une arrivée ou un retour. Faire choisir le navigateur lui\ndemanderait de se souvenir de quelque chose qu'il vient précisément de perdre.","operationId":"open_journey_session_v1_sessions_open_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneySession"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}":{"get":{"tags":["dossiers"],"summary":"Get Session","description":"L'état d'une session, par son identifiant et jamais par son jeton.","operationId":"get_session_v1_sessions__session_id__get","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/advance":{"post":{"tags":["dossiers"],"summary":"Advance","description":"Faire avancer une session : consentement, capture, envoi, repli, fin.\n\nAppelé par le parcours hébergé au nom du sujet, et authentifié par le **jeton de parcours** —\npas par une clé d'API, que le parcours n'a pas (M10 R1). Cet endpoint exigeait auparavant une\nclé alors que son docstring disait déjà « appelé par le parcours hébergé » : le parcours ne\npouvait donc pas faire avancer sa propre session.\n\nLe jeton ne vaut que pour **sa** session : un identifiant qui n'est pas le sien est refusé, ce\nqui rend l'usurpation impossible même en connaissant l'identifiant d'une autre session.\n\nLa transition est vérifiée par la machine à états : `capturing` n'est atteignable que depuis\n`consented`, ce qui rend M10 R8 structurelle plutôt que dépendante d'une vérification qu'un\ndéveloppeur pourrait oublier.","operationId":"advance_v1_sessions__session_id__advance_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdvanceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/events":{"post":{"tags":["dossiers"],"summary":"Report Journey Event","description":"Ce que le parcours rapporte de son déroulé : une photo écartée, l'aide, le repli.\n\nAuthentifié par le jeton de parcours, comme l'avancement. Le corps est lu contre une liste\nfermée (`domain/journey_events`) : un champ inattendu est refusé, pas ignoré — c'est ce qui\ngarde ce journal sans donnée personnelle.","operationId":"report_journey_event_v1_sessions__session_id__events_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"title":"Payload"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/journeys/metrics":{"get":{"tags":["dossiers"],"summary":"Get Journey Metrics","description":"Les mesures du parcours hébergé, ventilées par plateforme et par pays (M10 §11).\n\n« Le taux d'abandon par étape est l'indicateur produit le plus important du module […] c'est\nla mesure que le client regardera en premier. » Il la lit ici, pour ses propres sessions.\nPar défaut, les trente derniers jours.","operationId":"get_journey_metrics_v1_journeys_metrics_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Journey Metrics V1 Journeys Metrics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/capture-challenge":{"post":{"tags":["dossiers"],"summary":"Open Capture Challenge","description":"Émettre un défi de capture pour cette session.\n\nL'aléa et la suite de teintes viennent du serveur. Un défi produit par le parcours pourrait\nêtre choisi par l'attaquant, et ne prouverait rien.","operationId":"open_capture_challenge_v1_sessions__session_id__capture_challenge_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeIssued"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/capture-challenge/response":{"post":{"tags":["dossiers"],"summary":"Answer Capture Challenge","description":"Répondre au défi. Contrôle gratuit, avant tout appel payant.\n\nTous les refus portent le même code et le même message. Distinguer « aléa inconnu » de\n« cadence trop régulière » indiquerait à l'attaquant quel contrôle a réagi, et le\ndispositif s'userait à mesure qu'il est sondé.","operationId":"answer_capture_challenge_v1_sessions__session_id__capture_challenge_response_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeResponse"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/motion-challenge":{"post":{"tags":["dossiers"],"summary":"Open Motion Challenge","description":"Émettre un défi de mouvement. L'ordre des mouvements vient du serveur.","operationId":"open_motion_challenge_v1_sessions__session_id__motion_challenge_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MotionIssued"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sessions/{session_id}/motion-challenge/response":{"post":{"tags":["dossiers"],"summary":"Answer Motion Challenge","description":"Répondre au défi de mouvement.\n\nLes images servent à mesurer la rotation, puis sont oubliées : rien n'en est écrit. Les\ndirections annoncées par le parcours ne comptent pas — seul l'ordre des images, comparé à\ncelui que le serveur a tiré.","operationId":"answer_motion_challenge_v1_sessions__session_id__motion_challenge_response_post","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MotionResponse"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/journey-texts":{"get":{"tags":["dossiers"],"summary":"Get Journey Texts","description":"Les phrases du parcours qu'une organisation peut réécrire, telles que servies par défaut.\n\nGabarits intacts (`{client}`, `{retention_days}`) : c'est ce que la console montre sous chaque\nchamp de l'éditeur de textes. `locales` : les langues du parcours.","operationId":"get_journey_texts_v1_journey_texts_get","parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string","maxLength":10,"default":"fr","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Journey Texts V1 Journey Texts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/flows":{"get":{"tags":["dossiers"],"summary":"Get Flows","description":"Les parcours du client, avec leur version active et la dernière écrite.","operationId":"get_flows_v1_flows_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Flows V1 Flows Get"}}}}}}},"/v1/flows/{name}/versions":{"get":{"tags":["dossiers"],"summary":"Get Flow Versions","description":"Les versions d'un parcours, de la plus récente à la plus ancienne.","operationId":"get_flow_versions_v1_flows__name__versions_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Flow Versions V1 Flows  Name  Versions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["dossiers"],"summary":"Create Flow Version","description":"Enregistrer une nouvelle version, en brouillon. Elle doit être lisible, pas encore valide :\nce qui l'empêcherait d'être activée est rendu dans `problems`.","operationId":"create_flow_version_v1_flows__name__versions_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowDraft"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Flow Version V1 Flows  Name  Versions Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/flows/{name}/versions/{version}":{"get":{"tags":["dossiers"],"summary":"Get Flow Version","description":"Une version, sa définition, ce qui l'empêcherait d'être activée, et le coût estimé par\nservice — celui que le client a réellement payé ces trente derniers jours.","operationId":"get_flow_version_v1_flows__name__versions__version__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}},{"name":"version","in":"path","required":true,"schema":{"type":"integer","minimum":1,"title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Flow Version V1 Flows  Name  Versions  Version  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/flows/{name}/activate":{"post":{"tags":["dossiers"],"summary":"Activate Flow","description":"Activer une version — nouvelle, ou antérieure pour revenir en arrière (M7 §10).\n\n`traffic` < 100 essaie la version sur cette part des nouveaux dossiers, à côté de celle en\nservice ; 100 la met en service (et généralise un essai). Réactiver à 100 % la version en\nservice pendant un essai arrête l'essai. Les dossiers déjà ouverts conservent la leur (R1).\nDepuis la console, l'administrateur reconfirme son identité : changer le parcours de tous les\nnouveaux clients finaux est l'acte le plus large qu'un client puisse faire.","operationId":"activate_flow_v1_flows__name__activate_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowActivation"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Activate Flow V1 Flows  Name  Activate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/flows/{name}/rollout":{"get":{"tags":["dossiers"],"summary":"Get Flow Rollout","description":"L'essai en cours : la version essayée face à celle en service, sur les dossiers ouverts\ndepuis son début. `null` s'il n'y a pas d'essai.","operationId":"get_flow_rollout_v1_flows__name__rollout_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Flow Rollout V1 Flows  Name  Rollout Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/flows/{name}/simulate":{"post":{"tags":["dossiers"],"summary":"Simulate Flow","description":"Rejouer les dossiers récents du parcours dans la version en service et dans celle-ci\n(M7 §10). Rien n'est appelé, rien n'est facturé, aucun dossier n'est touché.\n\n`before` est absent si aucune version n'est en service. Un dossier dont le rejeu atteint une\nétape jamais mesurée est compté dans `unknown`, avec l'étape en cause : rien n'est deviné.","operationId":"simulate_flow_v1_flows__name__simulate_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowSimulation"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Simulate Flow V1 Flows  Name  Simulate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/audit":{"get":{"tags":["preuve"],"summary":"Get Case Audit","description":"Le journal d'un dossier : qui a fait quoi, et quand (M9 §10). Filtrable par type d'acteur.\n\nDes codes et des références, jamais une donnée personnelle : le journal n'en contient pas.","operationId":"get_case_audit_v1_cases__case_id__audit_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"actor_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/ActorType"},{"type":"null"}],"title":"Actor Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Case Audit V1 Cases  Case Id  Audit Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/operators/me/activity":{"get":{"tags":["preuve"],"summary":"Get My Activity","description":"Ce que l'opérateur agissant a fait, du plus récent au plus ancien (écran « Mon profil »).\n\nAucune habilitation particulière : chacun lit sa propre trace, et rien d'autre.","operationId":"get_my_activity_v1_operators_me_activity_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Cursor"}},{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get My Activity V1 Operators Me Activity Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cases/{case_id}/evidence":{"get":{"tags":["preuve"],"summary":"Get Evidence","description":"Le dossier de preuve (M9 §7, §10) : PDF lisible, ou JSON canonique pour la vérification.\n\nLa chaîne est vérifiée avant toute lecture ; rompue, le dossier n'est pas rendu — un rapport\nrassurant sur une chaîne cassée est pire que pas de rapport.","operationId":"get_evidence_v1_cases__case_id__evidence_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","title":"Case Id"}},{"name":"format","in":"query","required":false,"schema":{"enum":["pdf","json"],"type":"string","default":"pdf","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/exports":{"post":{"tags":["preuve"],"summary":"Create Export","description":"L'export réglementaire d'une période : filigrané, plafonné, sous ré-authentification.\n\n« Exports plafonnés et filigranés avec l'identité de l'opérateur et l'horodatage. Alerte\nautomatique sur volume inhabituel » (M6 §9). L'export est lui-même journalisé.","operationId":"create_export_v1_exports_post","parameters":[{"name":"X-Tano-Operator","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Operator"}},{"name":"X-Tano-Reauthenticated-At","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Tano-Reauthenticated-At"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActorType":{"type":"string","enum":["system","operator","agent","staff","subject","provider"],"title":"ActorType","description":"Types d'acteur admis par `audit.entries`. Liste fermée de cadre/04."},"AdvanceRequest":{"properties":{"status":{"$ref":"#/components/schemas/SessionStatus"}},"type":"object","required":["status"],"title":"AdvanceRequest"},"ApiKeyCreated":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"prefix":{"type":"string","title":"Prefix"},"secret":{"type":"string","title":"Secret"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"permissions":{"items":{"type":"string"},"type":"array","title":"Permissions","default":[]}},"type":"object","required":["id","label","prefix","secret","scopes"],"title":"ApiKeyCreated"},"ApplicantSubmission":{"properties":{"values":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","maxProperties":40,"title":"Values"}},"type":"object","title":"ApplicantSubmission","description":"Ce que la personne saisit : les champs demandés par le parcours, en texte."},"CaptureOpened":{"properties":{"id":{"type":"string","title":"Id"},"subject":{"type":"string","title":"Subject"},"key":{"type":"string","title":"Key"},"chunk_bytes":{"type":"integer","title":"Chunk Bytes"}},"type":"object","required":["id","subject","key","chunk_bytes"],"title":"CaptureOpened","description":"La capture, et sa clé — rendue **une seule fois**, comme un jeton.\n\nLa clé est émise par le service et non par le navigateur : un chiffrement dont le destinataire\nn'a pas la clé n'est pas un chiffrement, c'est une perte. Elle est conservée scellée sous la clé\ndu client, et aucune lecture ultérieure ne la rend."},"CaptureState":{"properties":{"id":{"type":"string","title":"Id"},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","title":"Status"},"received":{"items":{"type":"integer"},"type":"array","title":"Received"}},"type":"object","required":["id","subject","status","received"],"title":"CaptureState"},"CaseCreated":{"properties":{"id":{"type":"string","title":"Id"},"status":{"type":"string","title":"Status"},"flow_name":{"type":"string","title":"Flow Name"},"country":{"type":"string","title":"Country"},"expires_at":{"type":"string","title":"Expires At"},"environment":{"type":"string","title":"Environment","default":"prod"}},"type":"object","required":["id","status","flow_name","country","expires_at"],"title":"CaseCreated"},"CaseStatus":{"type":"string","enum":["created","collecting","processing","review","decided","abandoned","expired"],"title":"CaseStatus","description":"L'avancement d'un dossier. Cycle de vie de cadre/01-glossaire-domaine.md."},"ChallengeIssued":{"properties":{"id":{"type":"string","title":"Id"},"nonce":{"type":"string","title":"Nonce"},"sequence":{"items":{"type":"string"},"type":"array","title":"Sequence"},"step_ms":{"type":"integer","title":"Step Ms"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["id","nonce","sequence","step_ms","expires_at"],"title":"ChallengeIssued","description":"Le défi de capture, rendu une seule fois.\n\nL'aléa revient au serveur avec la réponse : c'est lui qui relie la capture au défi, et il\nne vaut qu'une fois."},"ChallengeResponse":{"properties":{"nonce":{"type":"string","maxLength":128,"minLength":32,"title":"Nonce"},"baseline":{"$ref":"#/components/schemas/ColourBody"},"measured":{"items":{"$ref":"#/components/schemas/ColourBody"},"type":"array","maxItems":8,"minItems":2,"title":"Measured"},"telemetry":{"$ref":"#/components/schemas/TelemetryBody"}},"type":"object","required":["nonce","baseline","measured","telemetry"],"title":"ChallengeResponse","description":"Ce que le parcours a mesuré, et non ce qu'il en conclut.\n\nLe service déduit lui-même les teintes renvoyées : une réponse qui se contenterait de nommer\ndes couleurs s'écrirait sans caméra."},"ChunkBody":{"properties":{"position":{"type":"integer","maximum":63.0,"minimum":0.0,"title":"Position"},"iv":{"type":"string","maxLength":24,"minLength":16,"title":"Iv"},"data":{"type":"string","maxLength":700000,"minLength":1,"title":"Data"}},"type":"object","required":["position","iv","data"],"title":"ChunkBody","description":"Un bloc scellé, avec son vecteur d'initialisation.\n\nLes deux voyagent en base 64 : le corps est du JSON, et encoder en base 16 doublerait le poids\nd'un envoi que le forfait du sujet paie."},"ChunkReceived":{"properties":{"position":{"type":"integer","title":"Position"},"stored":{"type":"boolean","title":"Stored"},"received":{"items":{"type":"integer"},"type":"array","title":"Received"}},"type":"object","required":["position","stored","received"],"title":"ChunkReceived"},"ColourBody":{"properties":{"r":{"type":"number","maximum":255.0,"minimum":0.0,"title":"R"},"g":{"type":"number","maximum":255.0,"minimum":0.0,"title":"G"},"b":{"type":"number","maximum":255.0,"minimum":0.0,"title":"B"}},"type":"object","required":["r","g","b"],"title":"ColourBody","description":"Une couleur moyenne mesurée sur le visage. Des nombres, jamais une image."},"CompleteBody":{"properties":{"chunk_count":{"type":"integer","maximum":64.0,"minimum":1.0,"title":"Chunk Count"}},"type":"object","required":["chunk_count"],"title":"CompleteBody"},"DecisionRecorded":{"properties":{"id":{"type":"string","title":"Id"},"task_id":{"type":"string","title":"Task Id"},"sequence":{"type":"integer","title":"Sequence"},"task_status":{"type":"string","title":"Task Status"},"case_outcome_notified":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Case Outcome Notified"}},"type":"object","required":["id","task_id","sequence","task_status","case_outcome_notified"],"title":"DecisionRecorded"},"DeclaredData":{"properties":{"surname":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Surname"},"given_names":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Given Names"},"birth_date":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Birth Date"},"place_of_birth":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Place Of Birth"},"country_of_birth":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Country Of Birth"},"sex":{"anyOf":[{"type":"string","enum":["F","M","X"]},{"type":"null"}],"title":"Sex"},"nationality":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Nationality"},"phone":{"anyOf":[{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string","maxLength":254},{"type":"null"}],"title":"Email"},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Country"},"city":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"City"},"district":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"District"},"street":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Street"},"landmark":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Landmark"},"postcode":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Postcode"},"tax_residence_country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Tax Residence Country"},"tax_number":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Tax Number"},"father_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Father Name"},"mother_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Mother Name"}},"type":"object","title":"DeclaredData","description":"Ce que le client déclare du sujet à l'ouverture. Confronté, jamais cru.\n\nL'identité (M1 R4) est confrontée à la pièce. Les autres champs sont ceux du catalogue des\ndonnées du demandeur : le client peut les envoyer pour **préremplir** le formulaire du parcours\n— un champ verrouillé garde alors sa valeur. Rien hors du catalogue : chaque champ est une\ndonnée personnelle de plus à chiffrer, conserver et purger, et sa finalité est le parcours qui\nla demande."},"EmbeddingSettings":{"properties":{"origins":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Origins"}},"type":"object","required":["origins"],"title":"EmbeddingSettings"},"EndpointCreated":{"properties":{"id":{"type":"string","title":"Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"status":{"type":"string","title":"Status"},"secret":{"type":"string","title":"Secret"}},"type":"object","required":["id","url","events","status","secret"],"title":"EndpointCreated"},"ExportRequest":{"properties":{"start":{"type":"string","format":"date-time","title":"Start"},"end":{"type":"string","format":"date-time","title":"End"}},"type":"object","required":["start","end"],"title":"ExportRequest"},"FieldCorrection":{"properties":{"field_path":{"type":"string","maxLength":64,"minLength":1,"title":"Field Path"},"value":{"type":"string","maxLength":200,"minLength":1,"title":"Value"}},"type":"object","required":["field_path","value"],"title":"FieldCorrection"},"FlowActivation":{"properties":{"version":{"type":"integer","minimum":1.0,"title":"Version"},"traffic":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Traffic","default":100}},"type":"object","required":["version"],"title":"FlowActivation"},"FlowDraft":{"properties":{"steps":{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":40,"minItems":1,"title":"Steps"},"journey":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Journey"}},"type":"object","required":["steps"],"title":"FlowDraft","description":"Une nouvelle version, en brouillon. Le nom et le numéro sont fixés par le service."},"FlowSimulation":{"properties":{"version":{"type":"integer","minimum":1.0,"title":"Version"}},"type":"object","required":["version"],"title":"FlowSimulation"},"GenericCopy":{"properties":{"texts":{"additionalProperties":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"type":"object","title":"Texts"}},"type":"object","required":["texts"],"title":"GenericCopy","description":"Les textes des écrans qui n'ont aucun flux derrière eux.\n\nServis **sans jeton**, et c'est la raison d'être de cet endpoint : un lien mort ou expiré doit\nse dire au sujet, et l'ouverture de session échoue précisément dans ce cas. Aucune donnée\npersonnelle, aucun nom de client — on ne sait pas de qui il s'agit."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IntegrationDecision":{"properties":{"outcome":{"type":"string","enum":["approve","reject","resubmit"],"title":"Outcome"},"reason_code":{"type":"string","maxLength":64,"minLength":1,"title":"Reason Code"},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment"},"steps":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecaptureStep"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Steps"}},"type":"object","required":["outcome","reason_code"],"title":"IntegrationDecision","description":"Ce qu'une intégration tranche : approuver, refuser, ou demander une reprise."},"JourneySession":{"properties":{"id":{"type":"string","title":"Id"},"case_id":{"type":"string","title":"Case Id"},"status":{"type":"string","title":"Status"},"locale":{"type":"string","title":"Locale"},"consented_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consented At"},"expires_at":{"type":"string","title":"Expires At"},"journey_token":{"type":"string","title":"Journey Token"},"resumed":{"type":"boolean","title":"Resumed"},"acquired":{"items":{"type":"string"},"type":"array","title":"Acquired"},"branding":{"additionalProperties":{"type":"string"},"type":"object","title":"Branding"},"refusal":{"type":"string","title":"Refusal"},"gallery":{"type":"boolean","title":"Gallery"},"capture_method":{"type":"string","title":"Capture Method","default":"live"},"return_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Return Url"},"embed_origins":{"items":{"type":"string"},"type":"array","title":"Embed Origins","default":[]},"documents":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","title":"Documents"},"issuing":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Issuing"},"resubmission":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resubmission"},"applicant_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Applicant Data"},"questionnaires":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Questionnaires"},"texts":{"additionalProperties":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"type":"object","title":"Texts"}},"type":"object","required":["id","case_id","status","locale","consented_at","expires_at","journey_token","resumed","acquired","branding","refusal","gallery","return_url","documents","texts"],"title":"JourneySession","description":"Ce que l'ouverture rend au parcours hébergé, et qu'aucune autre lecture ne rend.\n\nLe jeton de parcours est ici, une seule fois. Le reste — marque, pièces acceptées, route de\nrefus, textes — vient de la définition de flux et de `platform.copy` : **le parcours n'écrit\naucune phrase et ne connaît aucune pièce d'avance**."},"KeyEnvironment":{"type":"string","enum":["prod","sandbox","test"],"title":"KeyEnvironment","description":"L'environnement porté par la clé, visible dans son préfixe.\n\nUne clé de bac à sable ne peut pas servir en production, et l'inverse non plus.\nL'environnement est dans la clé plutôt que dans l'adresse appelée : c'est ce qui\npermet de détecter une clé de production collée par erreur dans une configuration\nde test, avant qu'elle ne consomme du volume facturé."},"MotionFrame":{"properties":{"direction":{"type":"string","pattern":"^(left|right)$","title":"Direction"},"image":{"type":"string","maxLength":533341,"minLength":100,"title":"Image"}},"type":"object","required":["direction","image"],"title":"MotionFrame"},"MotionIssued":{"properties":{"id":{"type":"string","title":"Id"},"nonce":{"type":"string","title":"Nonce"},"directions":{"items":{"type":"string"},"type":"array","title":"Directions"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["id","nonce","directions","expires_at"],"title":"MotionIssued","description":"Le défi de mouvement : les directions à demander, dans l'ordre tiré par le serveur."},"MotionResponse":{"properties":{"nonce":{"type":"string","maxLength":128,"minLength":32,"title":"Nonce"},"frames":{"items":{"$ref":"#/components/schemas/MotionFrame"},"type":"array","maxItems":4,"title":"Frames"},"telemetry":{"$ref":"#/components/schemas/TelemetryBody"},"selfie":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Selfie"}},"type":"object","required":["nonce","telemetry"],"title":"MotionResponse","description":"Une image par mouvement réussi. La rotation se mesure ici, pas dans le navigateur."},"NewApiKey":{"properties":{"label":{"type":"string","maxLength":100,"minLength":1,"title":"Label"},"environment":{"$ref":"#/components/schemas/KeyEnvironment"},"scopes":{"items":{"$ref":"#/components/schemas/Service"},"type":"array","minItems":1,"title":"Scopes"},"ip_allowlist":{"items":{"type":"string"},"type":"array","title":"Ip Allowlist"},"permissions":{"items":{"type":"string","enum":["personal_data","decisions"]},"type":"array","title":"Permissions"}},"type":"object","required":["label","environment","scopes"],"title":"NewApiKey"},"NewCapture":{"properties":{"subject":{"type":"string","maxLength":40,"pattern":"^[a-z][a-z0-9_-]*$","title":"Subject"}},"type":"object","required":["subject"],"title":"NewCapture","description":"Ce que le sujet va photographier : un code de pièce du flux, ou « face »."},"NewCase":{"properties":{"flow_name":{"type":"string","maxLength":64,"pattern":"^[a-z][a-z0-9_]*$","title":"Flow Name"},"country":{"type":"string","pattern":"^[A-Z]{2}$","title":"Country"},"external_ref":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"External Ref"},"declared":{"anyOf":[{"$ref":"#/components/schemas/DeclaredData"},{"type":"null"}]}},"type":"object","required":["flow_name","country"],"title":"NewCase"},"NewEndpoint":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Url"},"events":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Events"}},"type":"object","required":["url","events"],"title":"NewEndpoint"},"NewOperator":{"properties":{"role":{"$ref":"#/components/schemas/OperatorRole"},"countries":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Countries"},"max_sensitivity":{"$ref":"#/components/schemas/Sensitivity"},"email":{"type":"string","maxLength":254,"minLength":3,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email"}},"type":"object","required":["role","countries","max_sensitivity","email"],"title":"NewOperator"},"NewSession":{"properties":{"case_id":{"type":"string","maxLength":64,"minLength":1,"title":"Case Id"},"locale":{"type":"string","pattern":"^[a-z]{2}(-[A-Z]{2})?$","title":"Locale","default":"fr"},"lifetime_minutes":{"anyOf":[{"type":"integer","maximum":60.0,"minimum":1.0},{"type":"null"}],"title":"Lifetime Minutes"},"return_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Return Url"}},"type":"object","required":["case_id"],"title":"NewSession"},"OpenSessionRequest":{"properties":{"token":{"type":"string","maxLength":128,"minLength":16,"title":"Token"}},"type":"object","required":["token"],"title":"OpenSessionRequest","description":"Le jeton arrive dans le **corps**, jamais en paramètre d'URL.\n\nUn paramètre de requête finit dans les journaux du serveur, dans ceux du répartiteur de\ncharge, et dans l'en-tête `Referer` d'une navigation sortante."},"OperatorClearance":{"properties":{"role":{"$ref":"#/components/schemas/OperatorRole"},"countries":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Countries"},"max_sensitivity":{"$ref":"#/components/schemas/Sensitivity"}},"type":"object","required":["role","countries","max_sensitivity"],"title":"OperatorClearance"},"OperatorDecision":{"properties":{"outcome":{"$ref":"#/components/schemas/OperatorOutcome"},"reason_code":{"type":"string","maxLength":64,"minLength":1,"title":"Reason Code"},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment"},"steps":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecaptureStep"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Steps"}},"type":"object","required":["outcome","reason_code"],"title":"OperatorDecision"},"OperatorOutcome":{"type":"string","enum":["approve","reject","escalate","return","resubmit"],"title":"OperatorOutcome","description":"Les sorties possibles d'un opérateur. M6 §6, et la demande de reprise."},"OperatorRole":{"type":"string","enum":["reviewer","supervisor","admin","support"],"title":"OperatorRole","description":"Les rôles de la console de revue."},"QuestionnaireSubmission":{"properties":{"answers":{"additionalProperties":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}]},"type":"object","maxProperties":80,"title":"Answers"}},"type":"object","title":"QuestionnaireSubmission","description":"Les réponses à un questionnaire : un texte, ou les valeurs d'un choix multiple."},"RecaptureStep":{"type":"string","enum":["document","face"],"title":"RecaptureStep","description":"Ce qu'une demande de reprise peut faire refaire à la personne."},"Revision":{"properties":{"outcome":{"$ref":"#/components/schemas/OperatorOutcome"},"reason_code":{"type":"string","maxLength":64,"minLength":1,"title":"Reason Code"},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment"}},"type":"object","required":["outcome","reason_code"],"title":"Revision"},"RevisionRecorded":{"properties":{"id":{"type":"string","title":"Id"},"task_id":{"type":"string","title":"Task Id"},"previous_id":{"type":"string","title":"Previous Id"},"previous_outcome":{"type":"string","title":"Previous Outcome"},"outcome":{"type":"string","title":"Outcome"},"case_decision_id":{"type":"string","title":"Case Decision Id"}},"type":"object","required":["id","task_id","previous_id","previous_outcome","outcome","case_decision_id"],"title":"RevisionRecorded"},"Sensitivity":{"type":"string","enum":["standard","high"],"title":"Sensitivity","description":"Le niveau de sensibilité d'un dossier, et le plafond d'un opérateur."},"Service":{"type":"string","enum":["identity","document","kyb","screening","scoring","review","orchestration"],"title":"Service","description":"Services souscriptibles. Liste fermée, identique à la contrainte en base."},"SessionCreated":{"properties":{"id":{"type":"string","title":"Id"},"case_id":{"type":"string","title":"Case Id"},"token":{"type":"string","title":"Token"},"url":{"type":"string","title":"Url"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["id","case_id","token","url","expires_at"],"title":"SessionCreated"},"SessionState":{"properties":{"id":{"type":"string","title":"Id"},"case_id":{"type":"string","title":"Case Id"},"status":{"type":"string","title":"Status"},"locale":{"type":"string","title":"Locale"},"consented_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consented At"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["id","case_id","status","locale","consented_at","expires_at"],"title":"SessionState"},"SessionStatus":{"type":"string","enum":["issued","opened","consented","capturing","uploading","fallback","completed","declined","expired"],"title":"SessionStatus","description":"Les états d'une session de parcours. M10 §5."},"SubjectPresented":{"properties":{"external_sub":{"type":"string","maxLength":255,"minLength":1,"title":"External Sub"},"invitation":{"anyOf":[{"type":"string","maxLength":128,"minLength":16},{"type":"null"}],"title":"Invitation"},"display_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Display Name"}},"type":"object","required":["external_sub"],"title":"SubjectPresented","description":"Le sujet qu'un jeton d'identité portait, présenté par la console.\n\n`invitation` n'est fourni qu'à la première connexion : c'est le jeton opaque remis à\nl'opérateur, que `register_operator` consomme en le remplaçant par son sujet."},"SupportAccessRequest":{"properties":{"operator_id":{"type":"string","maxLength":64,"minLength":1,"title":"Operator Id"},"case_id":{"type":"string","maxLength":64,"minLength":1,"title":"Case Id"},"reason":{"type":"string","maxLength":600,"minLength":1,"title":"Reason"}},"type":"object","required":["operator_id","case_id","reason"],"title":"SupportAccessRequest"},"TaskStatus":{"type":"string","enum":["queued","assigned","in_progress","escalated","decided","cancelled"],"title":"TaskStatus","description":"Les états au repos d'une tâche."},"TelemetryBody":{"properties":{"label":{"type":"string","maxLength":200,"title":"Label","default":""},"declared_width":{"type":"integer","maximum":16384.0,"minimum":0.0,"title":"Declared Width","default":0},"declared_height":{"type":"integer","maximum":16384.0,"minimum":0.0,"title":"Declared Height","default":0},"frame_width":{"type":"integer","maximum":16384.0,"minimum":0.0,"title":"Frame Width","default":0},"frame_height":{"type":"integer","maximum":16384.0,"minimum":0.0,"title":"Frame Height","default":0},"frame_intervals_ms":{"items":{"type":"number"},"type":"array","maxItems":240,"title":"Frame Intervals Ms"}},"type":"object","title":"TelemetryBody","description":"Ce que le parcours rapporte de sa propre capture.\n\nRien ici n'est cru sur parole : cela vient d'un environnement que l'attaquant contrôle.\nCes valeurs sont des indices, et elles sont bornées pour qu'un corps malformé soit refusé\navant d'atteindre le moindre traitement."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}