{"openapi":"3.1.0","info":{"title":"AYAEL KYC","description":"Service interne de vérification d'identité","version":"0.1.0"},"paths":{"/kyc/cases":{"post":{"tags":["kyc"],"summary":"Create Verification Case","operationId":"create_verification_case_kyc_cases_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["kyc"],"summary":"List Verification Cases","description":"Dossiers du projet appelant, du plus récent au plus ancien.\n\nLe back-office AYAEL a sa propre liste, mais elle est servie en HTML et\nauthentifiée par session : inexploitable par un back-office tiers. Cette\nroute existe pour qu'un projet appelant puisse afficher SES dossiers dans\nsa propre interface d'administration sans dupliquer la base.\n\nLe filtre sur `source_app` n'est pas négociable : c'est ce qui empêche un\nprojet de lire les dossiers d'un autre.","operationId":"list_verification_cases_kyc_cases_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CaseOut"},"title":"Response List Verification Cases Kyc Cases Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}":{"get":{"tags":["kyc"],"summary":"Get Verification Result","operationId":"get_verification_result_kyc_cases__case_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}/documents":{"get":{"tags":["kyc"],"summary":"List Case Documents","description":"Les pièces d'un dossier : ce qui a été déposé, quand, sans les images.\n\nUn back-office tiers a besoin de savoir quoi afficher avant de demander\nquoi que ce soit de lourd. Le contenu se lit pièce par pièce, à l'adresse\nsuivante.","operationId":"list_case_documents_kyc_cases__case_id__documents_get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}/documents/{document_id}":{"get":{"tags":["kyc"],"summary":"Get Case Document","description":"L'image elle-même.\n\nCHAQUE LECTURE LAISSE UNE TRACE, rattachée au dossier : c'est la\ncontrepartie de faire sortir une pièce d'identité du back-office AYAEL.\nElle apparaît dans l'onglet Journal de la fiche, à côté des décisions\nhumaines, et nomme l'application plutôt qu'un opérateur — c'est tout ce\nqu'AYAEL sait : qui regarde derrière la clé est l'affaire de l'appelant,\net relève de SON journal à lui.","operationId":"get_case_document_kyc_cases__case_id__documents__document_id__get","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"document_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Document Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/sandbox/cases":{"delete":{"tags":["kyc"],"summary":"Purge Sandbox","description":"Efface TOUS les dossiers de ce bac à sable, images comprises.\n\nLA DOCUMENTATION DISAIT LE CONTRAIRE — « il n'y a pas de route pour cela,\net il n'y en aura pas, une clé ne doit pas pouvoir effacer des dossiers ».\nLa règle était juste, sa portée trop large : ce qu'elle protège, ce sont\nles dossiers de PRODUCTION, qui justifient des décisions prises sur de\nvrais clients. Un bac à sable ne justifie rien.\n\nD'où la garde : une clé de production reçoit 403 et n'efface jamais rien,\nquelle que soit la requête. Seule une application marquée `bac_a_sable`\npeut vider le sien — et seulement le sien, le cloisonnement par\n`source_app` valant ici comme ailleurs.\n\nSans délai, contrairement à la purge automatique : celui qui appelle cette\nroute sait ce qu'il fait, et c'est souvent entre deux séries d'essais\nqu'il en a besoin.","operationId":"purge_sandbox_kyc_sandbox_cases_delete","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}/document":{"post":{"tags":["kyc"],"summary":"Submit Document","operationId":"submit_document_kyc_cases__case_id__document_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"kind","in":"query","required":true,"schema":{"type":"string","title":"Kind"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_submit_document_kyc_cases__case_id__document_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"409":{"description":"Dossier déjà vérifié : il ne sera plus relu. Une correction se reprend dans un NOUVEAU dossier portant le même user_id."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}/submit":{"post":{"tags":["kyc"],"summary":"Finalize Submission","description":"Enregistre la soumission et répond immédiatement (§20 du CDC : ne pas\nbloquer la requête HTTP sur des traitements de plusieurs secondes). Les\nvérifications (duplicate/OCR/Face Match/Liveness) et l'évaluation des\nrègles sont déléguées au worker RQ (`app/verification.py`), qui notifie\nl'appelant via le webhook une fois terminé -- déjà le mécanisme utilisé\npour toute transition de statut, rien de nouveau à construire côté MMA.","operationId":"finalize_submission_kyc_cases__case_id__submit_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"409":{"description":"Dossier déjà vérifié : il ne sera plus relu. Une correction se reprend dans un NOUVEAU dossier portant le même user_id."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/kyc/cases/{case_id}/decision":{"post":{"tags":["kyc"],"summary":"Submit Review Decision","description":"§11 du CDC : la décision finale reste humaine, jamais automatique.\n\nET ELLE N'APPARTIENT PAS À L'APPLICATION APPELANTE (24/09/2026). Cette\nroute n'était protégée que par la clé : un intégrateur pouvait approuver\nses propres dossiers, et l'un l'a fait — un client vérifié par celui qui\nl'inscrit n'est vérifié par personne.\n\nElle subsiste pour Mobile Money Africa, qui statue depuis son propre\nback-office en production depuis des mois. `peut_decider` nomme les\napplications concernées, une à une : « les internes peuvent » aurait\nrouvert la porte à la prochaine application maison sans que personne ne\nle décide.","operationId":"submit_review_decision_kyc_cases__case_id__decision_post","parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewDecisionCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"403":{"description":"Cette application ne tranche pas ses propres dossiers. Les décisions sont prises par les opérateurs d'AYAEL KYC et vous parviennent par le webhook. Réservée aux quelques applications ouvertes nommément, qui ont leurs propres relecteurs."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"Body_submit_document_kyc_cases__case_id__document_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_submit_document_kyc_cases__case_id__document_post"},"CaseCreate":{"properties":{"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["user_id"],"title":"CaseCreate"},"CaseOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","title":"User Id"},"source_app":{"type":"string","title":"Source App"},"status":{"type":"string","title":"Status"},"kyc_level":{"type":"integer","title":"Kyc Level"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"normalized_result":{"additionalProperties":true,"type":"object","title":"Normalized Result","default":{}},"verified_identity":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Verified Identity"},"declared_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Declared Data"},"sandbox":{"type":"boolean","title":"Sandbox","default":false}},"type":"object","required":["id","user_id","source_app","status","kyc_level","created_at"],"title":"CaseOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ReviewDecisionCreate":{"properties":{"reviewer_id":{"type":"string","title":"Reviewer Id","description":"Identifiant de l'opérateur HUMAIN qui tranche, chez vous. Ni votre application (elle vient de la clé), ni le client vérifié. Conservé tel quel dans le journal du dossier.","examples":["operateur-1"]},"decision":{"type":"string","title":"Decision"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"correction_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correction Reason"}},"type":"object","required":["reviewer_id","decision"],"title":"ReviewDecisionCreate"},"SubmissionCreate":{"properties":{"declared_data":{"additionalProperties":true,"type":"object","title":"Declared Data"},"document_type":{"type":"string","title":"Document Type"},"document_country":{"type":"string","title":"Document Country"},"liveness_challenge":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Liveness Challenge"}},"type":"object","required":["declared_data","document_type","document_country"],"title":"SubmissionCreate"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}